我一生都不能弄清楚这一点。说我有以下两个字典对象:
// Assume "query" is a LINQ queryable.
Dictionary<string, int> d1 = query.ToDictionary(k => k.Key, v => v.Value);
Dictionary<string, int> d1 = query.ToDictionary(k => k.Key, v => v.Value);
以下语句产生编译时间错误,这是词典和idictionary之间的隐式转换:
// Compile time error!
Tuple<IDictionary<string, int>, IDictionary<string, int>> = Tuple.Create(d1, d2);
我必须明确进行转换:
Tuple<IDictionary<string, int>, IDictionary<string, int>> = Tuple.Create(d1 as IDictionary<string, int>, d2 as IDictionary<string, int>);
我不明白为什么编译器无法弄清楚协方差操作 - 字典实施IDICTIONARY-尤其是因为这样的事情当然会正如我们所知道的:
IDictionary<string, int> d3 = d1;
我确定这种行为有充分的理由,我很好奇它是什么。
更新1:只是为了澄清,我对行为而不是如何解决问题感到好奇。我知道不同的解决方案:)
更新2:谢谢大家的出色答案。我不知道Tuple
是不变的,现在我愿意。
基本上,问题是Tuple
家族在其类型参数中并不协变。不可能,因为这是一堂课。但是,可以创建一个接口或委托版本可以创建将是协变的,但是,由于没有成员接受输入位置中的类型参数。
这是最简单的Tuple<T1>
:
Tuple<string> stringTuple = Tuple.Create("Foo");
Tuple<object> objectTuple = stringTuple;
此通话:
Tuple.Create(d1, d2);
...将两种类型的参数推断为Dictionary<string, int>
,因此您正在尝试从Tuple<Dictionary<string, int>, Dictionary<string, int>>
转换为 Tuple<IDictionary<string, int>, IDictionary<string, int>>
,不起作用。
具有as
的版本更改了参数类型,因此类型推断给出了所需的类型参数 - 但是只能直接编写类型参数,并完全避免推断,如Sebastian的答案:
Tuple.Create<IDictionary<string, int>, IDictionary<string, int>>(d1, d2)
如果此时使用var
,它不是 so bad:
var x = Tuple.Create<IDictionary<string, int>, IDictionary<string, int>>(d1, d2);
x
的类型现在将是Tuple<IDictionary<string, int>, IDictionary<string, int>>
,您想要的。
编辑:正如评论中指出的那样,您不妨使用构造函数:
var x = new Tuple<IDictionary<string, int>, IDictionary<string, int>>(d1, d2);
您正在尝试分配...
Tuple<Dictionary<string, int>, Dictionary<string, int>>
... to ...
Tuple<IDictionary<string, int>, IDictionary<string, int>>
...但是Tuple<T1, T2>
是一类,因此不变。
元组的类型参数是从类型中推断出的类型参数,因此右侧是两个词典的元组,这与Idictionarys的元素是不同的类型 - 如果您明确添加元组的类型参数。创建类型Idictionary的所有内容都应按预期工作,因为方法参数可以具有更具体的类型。
Tuple.Create<IDictionary<string, int>,IDictionary<string, int>>(d1,d2)
Tuple<Dictionary<string, int>, Dictionary<string, int>>
和Tuple<IDictionary<string, int>, IDictionary<string, int>>
之间没有转换,因为C#中的类(因此Tuple<T1, T2>
类)不支持协方差。
编译器已将呼叫的返回类型的最特定类型推断为Tuple.Create
,并且在次要期间不使用左侧的类型。
尝试将变量类型从Dictionary<string, int>
更改为IDictionary<string, int>.
IDictionary<string, int> d1 = query.ToDictionary(k => k.Key, v => v.Value);
IDictionary<string, int> d1 = query.ToDictionary(k => k.Key, v => v.Value);