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

C# 无法在方法调用中将字典转换为IDictionary,c#,.net,type-conversion,covariance,implicit-conversion,C#,.net,Type Conversion,Covariance,Implicit Conversion,我一辈子都搞不清楚这件事。假设我有以下两个dictionary对象: // 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对象:

// 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);
//假设“query”是一个LINQ查询表。
字典d1=query.ToDictionary(k=>k.Key,v=>v.Value);
字典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=Tuple.Create(d1,d2);
我必须明确地进行转换:

Tuple<IDictionary<string, int>, IDictionary<string, int>> = Tuple.Create(d1 as IDictionary<string, int>, d2 as IDictionary<string, int>);
Tuple=Tuple.Create(d1作为IDictionary,d2作为IDictionary);
我不理解为什么编译器不能计算协方差运算-字典实现IDictionary-尤其是因为我们都知道这样的东西当然可以工作:

IDictionary<string, int> d3 = d1;
IDictionary d3=d1;
我确信这种行为有很好的理由,我很好奇它是什么

更新1: 我只是想澄清一下,我对行为感到好奇,而不是对如何解决问题感到好奇。我知道不同的解决方案:)

更新2:
谢谢大家的回答。我不知道
Tuple
是不变的,现在我知道了。

尝试将变量类型从
Dictionary
更改为
IDictionary。

IDictionary d1=query.ToDictionary(k=>k.Key,v=>v.Value);
IDictionary d1=query.ToDictionary(k=>k.Key,v=>v.Value);

Tuple.Create的类型参数是从类型中推断出来的,因此右侧是一个包含两个字典的Tuple,这与IDictionarys的Tuple是不同的类型-如果您显式地将类型参数添加到Tuple.Create为IDictionary类型,那么一切都应该按预期工作,因为该方法没有问题参数应为更具体的类型

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

基本上,问题在于
Tuple
族的类型参数不协变。不可能,因为这是一门课。但是,可以创建协变的接口或委托版本,因为在输入位置没有接受类型参数的成员

这是最简单的:

。。。正在将这两个类型参数推断为
字典
,因此您正在尝试从
元组
转换为
元组
,它不起作用

带有
as
的版本更改了参数类型,以便类型推断提供所需的类型参数-但根据Sebastian的回答,直接编写类型参数并完全避免推断会更简单:

Tuple.Create<IDictionary<string, int>, IDictionary<string, int>>(d1, d2)
x
的类型现在将是
Tuple
,这正是您想要的

编辑:如注释中所述,您最好在此时使用构造函数:

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

由于C#中的类(因此
元组
类)不支持协方差,因此
元组
元组
之间没有转换


编译器已为您对
Tuple.Create
的调用推断出返回类型的最具体类型,并且在推断过程中不使用左侧的类型。

您正在尝试分配

Tuple<Dictionary<string, int>, Dictionary<string, int>>
元组
…到

Tuple<IDictionary<string, int>, IDictionary<string, int>>
元组

…但是
元组是一个类,因此

可以工作。但我对这种行为很好奇,因为如果我使用隐式类型变量声明,例如,
vard1=query.ToDictionary(k=>k.Key,v=>v.Value)它不会工作。我想问题是,为什么我必须手动进行转换?通过使用var,编译器会将类型设置为Dictionary,因为Enumerable.ToDictionary返回Dictionary而不是IDictionary。你是对的。我把我的意思打错了。我想问为什么传递
query.ToDictionary(k=>k.Key,v=>v.Value)
不起作用。谢谢你的回答。谢谢你的详细回答。所有的答案都很好,但由于给出的细节,我将这一个标记为答案。@agarhy当然,当(像这里)需要显式指定静态
元组的类型参数
T1
T2
。Create
方法,您还可以使用泛型类型
Tuple
的普通实例构造函数和一个新的对象表达式:
newtuple(d1,d2)
var x = Tuple.Create<IDictionary<string, int>, IDictionary<string, int>>(d1, d2);
var x = new Tuple<IDictionary<string, int>, IDictionary<string, int>>(d1, d2);
Tuple<Dictionary<string, int>, Dictionary<string, int>>
Tuple<IDictionary<string, int>, IDictionary<string, int>>