当 IReadOnlyList<T>
在 .NET 4.5 中被引入时,我曾一度认为拼图上缺失的部分终于插入到了正确的位置:一种传递真正只读可索引接口的方式,在此之前我必须使用自己的只读接口并在所有内容周围创建包装类。
我期望该接口被放置在“自然”的层次结构中,这理想情况下将是:
IEnumerable<T>
.GetEnumerator()
-> IReadOnlyCollection<T> : IEnumerable<T>
.Count
-> IReadOnlyList<T> : IReadOnlyCollection<T>
.Item[...]
-> IList<T> : IReadOnlyList<T>
.Add(...)
.Clear()
.Contains(...)
(etc)
但是事实证明, IList<T>
不继承IReadOnlyList<T>
。
这样做有原因吗?
一些澄清:
请注意,IReadOnlyList<T>
只是一个契约,指出列表提供了一种获取列表计数并读取特定索引处的值的方法。它的命名不够准确,因为它并没有强制执行实际实现是只读的。
List<T>
实现了 IEnumerable<T>
,而 IList<T>
继承自 IEnumerable<T>
,但这并不意味着这些类仅可以被枚举。
因此,如果您想将列表传递给一个方法,并且只允许对其进行索引(读取),但不允许修改,则需要将其包装在新实例中。同时,您可以将其传递给接受IEnumerable<T>
或IList<T>
的方法而不必将其包装起来。这就是我认为有问题的地方。
我还相信应该为 IReadOnlyCollection
命名为 ICountable
,为 IReadOnlyList
命名为 IIndexable
:
IEnumerable<T>
.GetEnumerator()
-> ICountable<T> : IEnumerable<T>
.Count
-> IIndexable<T> : ICountable<T>
.Item[...]
-> IList<T> : IIndexable<T>
.Add(...)
.Clear()
.Contains(...)
(etc)
List<>
实现了IList<>
,但它不是只读的,那么它为什么要实现IReadOnlyList<>
呢? - Tim SchmelterList<>
实际上实现了IReadOnlyList<>
。而这个问题并不是关于List<>
,而是关于IList<>
。 - user4003407IReadOnlyList<T>
上编写扩展方法,而且我也不能同时为IList<T>
和IReadOnlyList<T>
编写它们,否则会出现模糊的方法错误。呃。 - Mike Marynowski