9ee*_*ee1 5 .net c# type-conversion covariance implicit-conversion
我不能为我的生活弄清楚这一点.假设我有以下两个字典对象:
// 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);
Run Code Online (Sandbox Code Playgroud)
以下语句产生编译时错误,无法在Dictionary和IDictionary之间进行隐式转换:
// Compile time error!
Tuple<IDictionary<string, int>, IDictionary<string, int>> = Tuple.Create(d1, d2);
Run Code Online (Sandbox Code Playgroud)
我必须明确地进行转换:
Tuple<IDictionary<string, int>, IDictionary<string, int>> = Tuple.Create(d1 as IDictionary<string, int>, d2 as IDictionary<string, int>);
Run Code Online (Sandbox Code Playgroud)
我不明白为什么编译器无法弄清楚协方差操作 - Dictionary实现了IDictionary - 特别是因为像这样的东西当然会起作用我们都知道:
IDictionary<string, int> d3 = d1;
Run Code Online (Sandbox Code Playgroud)
我确信这种行为有充分的理由,我很好奇它是什么.
更新1: 只是为了澄清,我很好奇行为不是如何解决问题.我知道不同的解决方案:)
更新2:
谢谢大家的答案.我不知道Tuple
是不变的,现在我做了.
基本上,问题是该Tuple
族在其类型参数中不是协变的.它不可能,因为它是一个类.接口或委托版本可以创建将被然而协变,因为没有成员接受在输入位置的类型的参数.
这是最简单的Tuple<T1>
:
Tuple<string> stringTuple = Tuple.Create("Foo");
Tuple<object> objectTuple = stringTuple;
Run Code Online (Sandbox Code Playgroud)
这个电话:
Tuple.Create(d1, d2);
Run Code Online (Sandbox Code Playgroud)
...正在推断两种类型的参数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)
Run Code Online (Sandbox Code Playgroud)
如果你var
在这一点上使用它,它并没有那么糟糕:
var x = Tuple.Create<IDictionary<string, int>, IDictionary<string, int>>(d1, d2);
Run Code Online (Sandbox Code Playgroud)
现在的类型x
将Tuple<IDictionary<string, int>, IDictionary<string, int>>
是你想要的.
编辑:如评论中所述,您可能只是在此时使用构造函数:
var x = new Tuple<IDictionary<string, int>, IDictionary<string, int>>(d1, d2);
Run Code Online (Sandbox Code Playgroud)