对于IDictionary<TKey, TValue>
,Keys
和Values
属性的类型为ICollection<TKey>
和ICollection<TValue>
。
对于IReadonlyDictionary<TKey, TValue>
,Keys
和Values
属性的类型为IEnumerable<TKey>
和IEnumerable<Value>
。
为什么IReadonlyDictionary<TKey, TValue>
的属性不仅仅是相应的ReadOnly接口,即IReadOnlyCollection<TKey>
和IReadOnlyCollection<TValue>
?
有人可能想知道为什么两个属性都不是IEnumerable
类型,因为你不能通过两个属性改变字典,而是通过Add
和Remove
方法。实际上ICollection
返回的IDictionary.Keys
具有IsReadOnly
属性集,因此尝试在属性上调用Add
或Remove
会抛出NotSupportedException
附加信息不允许变异从字典派生的密钥集合。
如果一个人无法通过其属性改变字典,为什么不是IReadOnlyCollections
两者?
IReadOnly
接口最初是在.NET 4.5中引入的,所以我想如果没有不希望的向后兼容性破坏就无法完成。
答案 0 :(得分:1)
如果他们不想使用IReadonlyDictionary<TKey, TValue>
派生的内容作为后备商店,那么实施自定义IReadOnlyCollection
的人就会减轻负担。
如果您使用的是ReadOnlyDictionary
的内置实现,则无法阻止您转换界面。
IReadOnlyDictionary<Foo, Bar> baz = GetDictionary();
IEnumerable<Foo> keys = baz.Keys;
IReadOnlyCollection<Foo> keysCollection = keys as IReadOnlyCollection<Foo>;
if(keysCollection != null)
{
//This code will execute for the built in implmentation of `ReadOnlyDictionary<Foo, Bar>`
}
答案 1 :(得分:1)
您不会通过Keys
和Values
属性修改键集合或值集合。您只能使用这些属性来访问键和值。因此,它们是否是明确的只读集合并不重要。
只能通过向字典中添加项目来修改键和值,而使用IReadOnlyDictionary
无法做到这一点。
此外,使用ICollection
会对IReadOnlyDictionary
的特定实现如何返回这些属性施加额外限制。 IEnumerable<T>
可以通过多种方式实现,即使是使用yield
语句的方法也是如此。如果返回的类型是ICollection<T>
,那么字典将被强制填充实现ICollection<T>
的内容。它可能仍然会这样做,但如果某些内容实现了ICollection<T>
,那么它也会实现IEnumerable<T>
。
所以我想知道另一种方式 - 为什么IDictionary<T>
会为这些属性而不是ICollection<T>
返回IEnumerable<T>
。 (可能有一个很好的理由。但现在我想知道。)
答案 2 :(得分:0)
IEnumerable<T>
允许您直接利用Linq方法和整个迭代器基础结构,,而无需执行强制转换。
即使通过ReadOnlyDictionary
和Key
集合,您也无法修改基础Value
实施中的数据。 IEnumerable<T>
并不关心其底层实现是否为只读。