.NET 4中的IDictionary <TKey,TValue>不是协变的

.NET 4 / Silverlight 4中的IDictionary<TKey, TValue>不支持协方差,即我不能做

 IDictionary<string, object> myDict = new Dictionary<string, string>(); 

类似于我现在可以用IEnumerable<T>做什么。

大概归结为KeyValuePair<TKey, TValue>也不是协变的。 我觉得在词典中至less应该允许协variables的值。

那么这是一个错误还是一个function? 它会不会来,也许在.NET 37.4?

更新(2年后):

在.NET 4.5中将会有一个IReadOnlyDictionary<TKey, TValue> ,但它不会是协变的:·/因为它是从IEnumerable<KeyValuePair<TKey, TValue>>KeyValuePair<TKey, TValue>派生的一个接口,因此不能协变。

BCL团队将不得不重新devise很多来使用一些ICovariantPair<TKey, TValue>来代替。 对于协变接口来说, this[TKey key]强types索引器也是不可能的。 类似的结局只能通过放置一个扩展方法GetValue<>(this IReadOnlyDictionary<TKey, TValue> self, TKey key)来实现,这个方法在某种程度上必须在内部调用一个实际的实现,这看起来像一个相当混乱的方法。

这是一个function。 .NET 4.0只支持安全的协方差。 你提到的转换是潜在的危险,因为你可以添加一个非string元素的字典,如果可能的话:

 IDictionary<string, object> myDict = new Dictionary<string, string>(); myDict["hello"] = 5; // not an string 

另一方面, IEnumerable<T>是一个只读接口。 Ttypes参数仅在其输出位置( Current属性的返回types)中,所以将IEnumerable<string>视为IEnumerable<object>

但是你可以说

 myDict.Add("Hello, world!", new DateTime(2010, 1, 27)); 

这会惨败。 问题是IDictionary<TKey, TValue>中的IDictionary<TKey, TValue>用于input和输出位置。 以机智:

 myDict.Add(key, value); 

 TValue value = myDict[key]; 

那么这是一个错误还是一个function?

这是devise。

它会不会来,也许在.NET 37.4?

不,这本质上是不安全的。

我有一个类似的问题,但有更多的专门的派生types(而不是所有的东西都来自于对象)

诀窍是使方法通用,并把一个where子句放在相关的限制。 假设你正在处理基types和派生types,下面的工作:

 using System; using System.Collections.Generic; namespace GenericsTest { class Program { static void Main(string[] args) { Program p = new Program(); p.Run(); } private void Run() { Dictionary<long, SpecialType1> a = new Dictionary<long, SpecialType1> { { 1, new SpecialType1 { BaseData = "hello", Special1 = 1 } }, { 2, new SpecialType1 { BaseData = "goodbye", Special1 = 2 } } }; Test(a); } void Test<Y>(Dictionary<long, Y> data) where Y : BaseType { foreach (BaseType x in data.Values) { Console.Out.WriteLine(x.BaseData); } } } public class BaseType { public string BaseData { get; set; } } public class SpecialType1 : BaseType { public int Special1 { get; set; } } } 

.NET 4只支持不支持的协方差。 它适用于IEnumerable,因为IEnumerable是只读的。

解决IDictionary上特定types的有用协变问题

 public static class DictionaryExtensions { public static IReadOnlyDictionary<TKey, IEnumerable<TValue>> ToReadOnlyDictionary<TKey, TValue>( this IDictionary<TKey, List<TValue>> toWrap) { var intermediate = toWrap.ToDictionary(a => a.Key, a => a.Value!=null ? a.Value.ToArray().AsEnumerable() : null); var wrapper = new ReadOnlyDictionary<TKey, IEnumerable<TValue>>(intermediate); return wrapper; } }