我不能为我的生活弄清楚这一点。假设我有以下两个字典对象:
// 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);
以下语句产生编译时错误,即无法在Dictionary和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>);
我不明白为什么编译器无法弄清楚协方差操作 - Dictionary实现IDictionary - 特别是因为像这样的东西当然会起作用我们都知道:
IDictionary<string, int> d3 = d1;
我确信这种行为有充分的理由,我很好奇它是什么。
更新1: 只是为了澄清,我很好奇行为不是如何解决问题。我知道不同的解决方案:)
更新2:
谢谢大家的答案。我不知道Tuple
是不变的,现在我做了。
答案 0 :(得分:6)
基本上,问题是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
,则
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);
答案 1 :(得分:3)
您正在尝试分配...
Tuple<Dictionary<string, int>, Dictionary<string, int>>
...到...
Tuple<IDictionary<string, int>, IDictionary<string, int>>
...但Tuple<T1, T2>
是一个类,因此 invariant 。
答案 2 :(得分:2)
Tuple.Create的类型参数是从类型中推断出来的,因此右侧是两个Dictionaries的元组,这是一个与IDictionarys的元组不同的类型 - 如果你明确地将类型参数添加到Tuple.Create到属于IDictionary类型,一切都应该按预期工作,因为方法参数可以是更具体的类型。
Tuple.Create<IDictionary<string, int>,IDictionary<string, int>>(d1,d2)
答案 3 :(得分:2)
Tuple<Dictionary<string, int>, Dictionary<string, int>>
和Tuple<IDictionary<string, int>, IDictionary<string, int>>
之间没有转换,因为C#中的类(因此Tuple<T1, T2>
类)不支持协方差。
编译器为您调用Tuple.Create
推断出最具体的返回类型,并且在推理期间不使用左侧的类型。
答案 4 :(得分:0)
尝试将变量类型从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);