无法在方法调用中将字典转换为IDictionary

时间:2012-11-11 16:43:24

标签: c# .net 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);

以下语句产生编译时错误,即无法在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是不变的,现在我做了。

5 个答案:

答案 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);