一尘不染

为什么C#不实现索引属性?

c#

我知道,我知道…埃里克·利珀特(Eric Lippert)对此类问题的回答通常类似于“, 因为它不值得设计,实施,测试和记录它的成本 ”。

但是,我仍然需要一个更好的解释……我正在阅读有关C#4新功能的博客文章,并且在有关COM Interop的部分中,以下部分引起了我的注意:

顺便说一句,此代码使用了另一个新功能:索引属性(仔细研究Range之后的方括号。) 但是,此功能仅适用于COM互操作;
您不能在C#4.0中创建自己的索引属性

好的,但是为什么呢?我已经知道并感到遗憾,因为无法在C#中创建索引属性,但是这句话让我重新考虑了一下。我可以看到实现它的几个很好的理由:

  • CLR支持它(例如,PropertyInfo.GetValue有一个index参数),所以很遗憾我们不能在C#中利用它
  • 如文章所示(使用动态调度),它支持COM互操作
  • 它在VB.NET中实现
  • 已经可以创建索引器,即将索引应用于对象本身,因此将概念扩展到属性,保持相同的语法并仅替换this为属性名称可能没什么大不了的

这样可以写这样的东西:

public class Foo
{
    private string[] _values = new string[3];
    public string Values[int index]
    {
        get { return _values[index]; }
        set { _values[index] = value; }
    }
}

目前,我所知道的唯一解决方法是创建一个ValuesCollection实现索引器的内部类(例如),并更改Values属性,以使其返回该内部类的实例。

这很容易做到,但是很烦人……所以也许编译器可以为我们做到!一种选择是生成实现索引器的内部类,并通过公共通用接口公开它:

// interface defined in the namespace System
public interface IIndexer<TIndex, TValue>
{
    TValue this[TIndex index]  { get; set; }
}

public class Foo
{
    private string[] _values = new string[3];

    private class <>c__DisplayClass1 : IIndexer<int, string>
    {
        private Foo _foo;
        public <>c__DisplayClass1(Foo foo)
        {
            _foo = foo;
        }

        public string this[int index]
        {
            get { return _foo._values[index]; }
            set { _foo._values[index] = value; }
        }
    }

    private IIndexer<int, string> <>f__valuesIndexer;
    public IIndexer<int, string> Values
    {
        get
        {
            if (<>f__valuesIndexer == null)
                <>f__valuesIndexer = new <>c__DisplayClass1(this);
            return <>f__valuesIndexer;
        }
    }
}

但是,当然,在那种情况下,该属性 实际上 将返回IIndexer<int, string>,并且 实际上
不是索引属性…最好生成一个真正的CLR索引属性。

你怎么看 ?您想在C#中看到此功能吗?如果没有,为什么?


阅读 245

收藏
2020-05-19

共1个答案

一尘不染

这是我们设计C#4的方式。

首先,我们列出了可以考虑添加到该语言的所有可能功能。

然后,我们将这些功能分类为“这很不好,我们绝对不能做”,“这太棒了,我们必须做”和“这很好,但这次我们不要做”。

然后,我们查看了设计,实施,测试,记录,运送和维护“必须拥有”功能所需的预算,发现我们超出了预算100%。

因此,我们将一堆东西从“必须拥有”存储桶移到了“不错拥有”存储桶。

索引属性永远不在“必须拥有”列表的顶部 附近 。他们在“好”列表上的位置很低,并且在“坏主意”列表上调情。

我们花在设计,实施,测试,文档化或维护好的功能X上的每一分钟,都是我们无法花费在出色的功能A,B,C,D,E,F和G上的每一分钟。我们必须毫不留情地确定优先级,以便仅尽力而为。索引属性会很不错,但是不错的地方还差得远不能实际实现。

2020-05-19