.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>
是一个只读接口。 T
types参数仅在其输出位置( 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; } }