【发布时间】:2023-03-29 11:16:02
【问题描述】:
当IReadOnlyList<T> 在 .NET 4.5 中被引入时,我一度认为谜题的缺失部分终于到位:一种传递真正只读可索引接口的方法,以前我必须使用我自己的 read -only 接口并围绕所有内容创建包装类。
我希望将界面放置在“自然”层次结构中,理想情况下是:
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)
【问题讨论】:
-
正如你已经说过的,
IReadonlyList是在 .NET4.5 中引入的,后来IList被添加到 .Net 中。 -
List<>实现了IList<>但它不是只读的,那么为什么要实现IReadOnlyList<>?。 -
@TimSchmelter
List<>实际上实现了IReadOnlyList<>。而且这个问题不是问List<>,而是问IList<>。 -
这实际上很烦人,因为我不能只在
IReadOnlyList<T>上编写扩展方法,也不能同时为IList<T>和IReadOnlyList<T>编写它们,因为那样你会得到模棱两可的方法错误.嘎。