我知道,我知道…埃里克·利珀特(Eric Lippert)对此类问题的回答通常类似于“, 因为它不值得设计,实施,测试和记录它的成本 ”。
但是,我仍然需要一个更好的解释……我正在阅读有关C#4新功能的博客文章,并且在有关COM Interop的部分中,以下部分引起了我的注意:
顺便说一句,此代码使用了另一个新功能:索引属性(仔细研究Range之后的方括号。) 但是,此功能仅适用于COM互操作; 您不能在C#4.0中创建自己的索引属性。
好的,但是为什么呢?我已经知道并感到遗憾,因为无法在C#中创建索引属性,但是这句话让我重新考虑了一下。我可以看到实现它的几个很好的理由:
PropertyInfo.GetValue
index
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属性,以使其返回该内部类的实例。
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索引属性。
IIndexer<int, string>
你怎么看 ?您想在C#中看到此功能吗?如果没有,为什么?
这是我们设计C#4的方式。
首先,我们列出了可以考虑添加到该语言的所有可能功能。
然后,我们将这些功能分类为“这很不好,我们绝对不能做”,“这太棒了,我们必须做”和“这很好,但这次我们不要做”。
然后,我们查看了设计,实施,测试,记录,运送和维护“必须拥有”功能所需的预算,发现我们超出了预算100%。
因此,我们将一堆东西从“必须拥有”存储桶移到了“不错拥有”存储桶。
索引属性永远不在“必须拥有”列表的顶部 附近 。他们在“好”列表上的位置很低,并且在“坏主意”列表上调情。
我们花在设计,实施,测试,文档化或维护好的功能X上的每一分钟,都是我们无法花费在出色的功能A,B,C,D,E,F和G上的每一分钟。我们必须毫不留情地确定优先级,以便仅尽力而为。索引属性会很不错,但是不错的地方还差得远不能实际实现。