为什么SortedList(TKey,TValue).Keys属性是一个IList(TKey)而不是一个ReadOnlyCollection(TKey)?

3

IList<T>接口除了支持索引访问外,还支持一些SortedList<TKey, TValue>.Keys属性不支持的操作,例如AddRemoveInsert

ReadOnlyCollection<T>(例如List<T>.AsReadOnly的返回值)实现了IList<T>,因此提供了索引访问,但是通过显式实现来隐藏了像Add等非法操作。此外,它只是底层列表的包装器,因此不会创建副本,应该(我认为)不会产生任何真正的性能问题。

有什么想法,为什么SortedList<TKey, TValue.Keys不是ReadOnlyCollection<TKey>?(同样,Values属性为什么不是ReadOnlyColllection<TValue>?)


很奇怪它不是只读集合,因为如果你执行sortedList.Values.Add(2);它会抛出异常。 - Andrey
没错!非常好奇... - Dan Tao
我认为原因是ReadOnlyCollection是一个类而不是接口。使用接口可以编写自定义存储,但ReadOnlyCollection已经有了自己的实现。 - Andrey
据我所知,ReadOnlyCollection<T> 类可以包装实现 IList<T> 接口的任何类的对象;因此,即使 Keys 属性以其自己特殊的方式实现了 IList<T> 接口,它仍然可以作为一个简单地包装该对象的 ReadOnlyCollection<T> 对象来公开,无论它如何实现 IList<T> 接口。 - Dan Tao
1个回答

3
这很晦涩,但我认为这是一种优化。它与泛型实现的方式有关。泛型类方法的机器代码是由JIT编译器在运行时创建的。它需要制作几个具体版本。对于任何引用类型都有一个版本。并且每个在程序中使用的单个值类型参数都有一个版本。
这可能效率低下,潜在地需要生成大量代码。特别是对于泛型框架类而言更糟糕,它们被Ngen-ed。具体的方法实现必须经过JIT编译,并且不能在Ngen映像中。
为了解决这个问题,框架中有私有代码(抱歉,我忘记了在哪里),它实例化各种版本的泛型类。有趣的无操作代码,让我困惑了相当长的时间。但副作用是Ngen.exe会为泛型类方法生成代码。如果您现在在自己的代码中使用这样的泛型类,则将从Ngen映像中获取方法的具体实现,不需要JIT编译器。
您可以看到,System.Collections.ObjectModel.ReadOnlyCollection可能被认为太晦涩而未包含在此列表中。很容易验证,您将看到当您单步进入其中一个方法时,即使您获得了Reference Source .pdbs,也不会进入源代码。
我不100%确定这是确切的解释。但很符合情况。

非常有趣、非常有用的答案。我希望能得到像这样深入的解释。现在我将自己动手去探究你所说的内容。 - Dan Tao

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接