Search code examples
c#indexed-properties

Named indexed property in C#?


A few languages - like Delphi - has a very convenient way of creating indexers: not only the whole class, but even single properties can be indexed, for instance:

type TMyClass = class(TObject)
protected
    function GetMyProp(index : integer) : string;
    procedure SetMyProp(index : integer; value : string);
public
    property MyProp[index : integer] : string read GetMyProp write SetMyProp;
end;

This can be used easily:

var c : TMyClass;

begin
    c = TMyClass.Create;
    c.MyProp[5] := 'Ala ma kota';
    c.Free;
end;

Is there a way to achieve the same effect in C# easily?


Solution

  • The well-known solution is to create a proxy class:

    public class MyClass
    {
        public class MyPropProxy
        {
            private MyClass c;
    
            // ctor etc.
    
            public string this[int index]
            {
                get
                {
                    return c.list[index];
                }
                set
                {
                    c.list[index] = value;
                }
            }
        }
    
        private List<string> list;
        private MyPropProxy myPropProxy;
    
        // ctor etc.
    
        public MyPropProxy MyProp
        { 
            get
            {
                return myPropProxy;
            }
        }
    }
    

    But (with exception, that this actually solves the problem), this solution introduces mostly only cons:

    • It causes the code to be polluted by (possibly) a lot of small proxy classes.
    • Presented solution breaks encapsulation a little (inner class accesses private members of the outer class), a better one would pass an instance of list to MyPropProxy's ctor, what would require even more code.
    • Exposing internal helper classes is not something I would suggest. One may solve that by introducing additional interface, but that's even one more entity to implement (test, maintain etc.)

    There's another way, though. It also pollutes the code a little, but surely a lot less, than the previous one:

    public interface IMyProp
    {
        string this[int index] { get; }
    }
    
    public class MyClass : IMyProp
    {
        private List<string> list;
    
        string IMyProp.this[int index]
        {
            get
            {
                return list[index];
            }
            set
            {
                list[index] = value;
            }
        }
    
        // ctor etc.
    
        public IMyProp MyProp 
        {
            get
            {
                return this;
            }
        }
    }
    

    Pros:

    • No proxy classes (which occupy space in memory, serve only a single purpose and (in the simplest solution) breaks encapsulation.
    • Simple solution, requires little code to add another indexed property

    Cons:

    • Each property requires a different public interface
    • With increase of indexed properties, the class implements more and more interfaces

    This is the simplest (in terms of code length and complexity) way of introducing indexed properties to C#. Unless someone posts even shorter and simpler one, of course.