在C#中命名为索引属性?

Spo*_*ook 3 c# indexed-properties

一些语言 - 比如Delphi - 有一种非常方便的方法来创建索引器:不仅是整个类,甚至单个属性都可以被编入索引,例如:

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;
Run Code Online (Sandbox Code Playgroud)

这可以很容易地使用:

var c : TMyClass;

begin
    c = TMyClass.Create;
    c.MyProp[5] := 'Ala ma kota';
    c.Free;
end;
Run Code Online (Sandbox Code Playgroud)

有没有办法在C#中轻松实现同样的效果?

Spo*_*ook 10

众所周知的解决方案是创建一个代理类:

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;
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

但是(除了这实际上解决了这个问题),这个解决方案大多只引入缺点:

  • 它导致代码被(可能)许多小代理类污染.
  • 提出的解决方案会稍微破坏封装(内部类访问外部类的私有成员),更好的方法是将列表实例传递给MyPropProxyctor,这将需要更多的代码.
  • 公开内部帮助程序类不是我建议的.可以通过引入额外的接口来解决这个问题,但这甚至可以实现一个实体(测试,维护等)

不过还有另一种方式.它还污染了一些代码,但肯定比前一代码少了很多:

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;
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

优点:

  • 没有代理类(占用内存空间,仅用于单一目的,并且(在最简单的解决方案中)打破封装.
  • 简单的解决方案,需要很少的代码来添加另一个索引属性

缺点:

  • 每个属性都需要不同的公共接口
  • 随着索引属性的增加,该类实现了越来越多的接口

这是将索引属性引入C#的最简单(就代码长度和复杂性而言)的方式.当然,除非有人发布更短更简单的帖子.