在.NET 4.5中引入IReadOnlyList<T>
时,有一会儿我认为难题的缺失部分终于被插入到位:一种传递真正的只读可索引接口(interface)的方法,以前我不得不使用自己的只读接口(interface)并创建包装类周围的一切。
我期望将接口(interface)放置在“自然”层次结构内,理想情况下是:
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>
的方法,而无需对其进行包装。这是我发现要打破的东西。我也相信专有名称应该像
ICountable
的IReadOnlyCollection
和IIndexable
的IReadOnlyList
一样:IEnumerable<T>
.GetEnumerator()
-> ICountable<T> : IEnumerable<T>
.Count
-> IIndexable<T> : ICountable<T>
.Item[...]
-> IList<T> : IIndexable<T>
.Add(...)
.Clear()
.Contains(...)
(etc)
最佳答案
@ w.b在包含答案的注释中放置指向New interfaces IReadOnlyList and IReadOnlyDictionary的链接:
为了更清楚地解释这一点:
假设为.NET 4.0编写的程序包含一个实现MyList<T>
的IList<T>
类。显然,由于该接口(interface)不存在,因此无法实现IReadOnlyList<T>
。
现在假设系统管理员安装了.NET 4.5,并假定.NET 4.5使IList<T>
实现IReadOnlyList<T>
。
如果随后将程序加载,则运行时将检测到MyList<T>
声明实现IList<T>
,但实际上并未实现所有方法:它未实现IReadOnlyList<T>
的方法。该程序将不再起作用。
C#编译器可能可以按名称匹配方法,但是运行时不这样做。由于.NET 4.5应该具有向后二进制兼容性,因此即使这些其他接口(interface)包含所需方法的严格子集,也无法扩展这些接口(interface)以实现其他接口(interface)。