简体   繁体   English

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

[英]Cannot Convert Dictionary to IDictionary in a Method Call

I can't for the life of me figure this out. 我不能为我的生活弄清楚这一点。 Say I have the following two dictionary objects: 假设我有以下两个字典对象:

// 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);

The following statement produces a compile time error that an implicit conversion between a Dictionary and IDictionary is not possible: 以下语句产生编译时错误,无法在Dictionary和IDictionary之间进行隐式转换:

// Compile time error!
Tuple<IDictionary<string, int>, IDictionary<string, int>> = Tuple.Create(d1, d2);

I have to do the conversion explicitly: 我必须明确地进行转换:

Tuple<IDictionary<string, int>, IDictionary<string, int>> = Tuple.Create(d1 as IDictionary<string, int>, d2 as IDictionary<string, int>);

I am not understanding why the compiler can't figure out the covariance operation - Dictionary implements IDictionary - especially since something like this will of course work as we all know: 我不明白为什么编译器无法弄清楚协方差操作 - Dictionary实现了IDictionary - 特别是因为像这样的东西当然会起作用我们都知道:

IDictionary<string, int> d3 = d1;

I am sure there is a good reason for this behavior and I am curious what it is. 我确信这种行为有充分的理由,我很好奇它是什么。

Update 1: Just to clarify, I am curious about the behavior not how to solve the problem. 更新1:只是为了澄清,我很好奇行为不是如何解决问题。 I am aware of the different solutions :) 我知道不同的解决方案:)

Update 2: Thank you all for the great answers. 更新2:谢谢大家的答案。 I did not know Tuple was invariant and now I do. 我不知道Tuple是不变的,现在我做了。

Basically, the problem is that the Tuple family isn't covariant in its type arguments. 基本上,问题是Tuple族在其类型参数中不是协变的。 It can't be, because it's a class. 它不可能,因为它是一个类。 An interface or delegate version could be created that would be covariant, however, as there are no members accepting the type parameters in input positions. 接口或委托版本可以创建将被然而协变,因为没有成员接受在输入位置的类型的参数。

This is simplest to see with Tuple<T1> : 使用Tuple<T1>最简单:

Tuple<string> stringTuple = Tuple.Create("Foo");
Tuple<object> objectTuple = stringTuple;

This call: 这个电话:

Tuple.Create(d1, d2);

... is inferring both type arguments as Dictionary<string, int> , so you're trying to convert from Tuple<Dictionary<string, int>, Dictionary<string, int>> to Tuple<IDictionary<string, int>, IDictionary<string, int>> , which doesn't work. ...将两个类型参数推断为Dictionary<string, int> ,因此您尝试将Tuple<Dictionary<string, int>, Dictionary<string, int>>Tuple<IDictionary<string, int>, IDictionary<string, int>> ,它不起作用。

The version with as changes the argument types so that type inference gives the desired type arguments - but it would be simpler to just write the type arguments directly, and avoid inference entirely, as per Sebastian's answer: 带有as的版本更改了参数类型,以便类型推断提供所需的类型参数 - 但是直接编写类型参数会更简单,并且完全避免推断,根据Sebastian的回答:

Tuple.Create<IDictionary<string, int>, IDictionary<string, int>>(d1, d2)

If you use var at this point, it's not so bad: 如果你在这一点上使用var ,那就不是那么糟糕了:

var x = Tuple.Create<IDictionary<string, int>, IDictionary<string, int>>(d1, d2);

The type of x will now be Tuple<IDictionary<string, int>, IDictionary<string, int>> which is what you want. x的类型现在是Tuple<IDictionary<string, int>, IDictionary<string, int>>这就是你想要的。

EDIT: As noted in comments, you might as well just use the constructor at that point: 编辑:如评论中所述,您可能只是在此时使用构造函数:

var x = new Tuple<IDictionary<string, int>, IDictionary<string, int>>(d1, d2);

You are trying to assign... 你正试图分配......

Tuple<Dictionary<string, int>, Dictionary<string, int>>

...to... ...至...

Tuple<IDictionary<string, int>, IDictionary<string, int>>

...but the Tuple<T1, T2> is a class and therefore invariant . ...但是Tuple<T1, T2>是一个类,因此是不变的

Tuple.Create的类型参数是从类型中推断出来的,因此右侧是两个字典的元组,这是与IDictionarys的元组不同的类型 - 如果你明确地将类型参数添加到Tuple.Create是类型的IDictionary一切都应该按预期工作,因为方法参数可以是更具体的类型。

 Tuple.Create<IDictionary<string, int>,IDictionary<string, int>>(d1,d2)

There is no conversion between a Tuple<Dictionary<string, int>, Dictionary<string, int>> and a Tuple<IDictionary<string, int>, IDictionary<string, int>> since classes in C# (and therefore the Tuple<T1, T2> class) do not support covariance. Tuple<Dictionary<string, int>, Dictionary<string, int>>Tuple<IDictionary<string, int>, IDictionary<string, int>>之间没有转换Tuple<IDictionary<string, int>, IDictionary<string, int>>因为C#中的类(因此Tuple<T1, T2> class)不支持协方差。

The compiler has inferred the most specific type of the return type for your call to Tuple.Create , and does not use the type on the left-hand side during inferrence. 编译器为您调用Tuple.Create推断了最具体的返回类型,并且在推理期间不使用左侧的类型。

Try changing the variable type from Dictionary<string, int> to IDictionary<string, int>. 尝试将变量类型从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);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM