C# 怪异词典

C# 怪异词典,c#,.net,generics,C#,.net,Generics,在项目(.NET Framework“I belive”4.6.2)期间,我在工作中遇到了有趣且令人困惑的行为: var dict = new Dictionary<string, Dictionary<string, SomeFunnyStuff>>(); // Dictionary hard working collector 我们得到: 参数1:无法从System.Collections.Generic.Dictionary>'转换为System.Collecti

在项目(.NET Framework“I belive”4.6.2)期间,我在工作中遇到了有趣且令人困惑的行为:

var dict = new Dictionary<string, Dictionary<string, SomeFunnyStuff>>();
// Dictionary hard working collector
我们得到:

参数1:无法从System.Collections.Generic.Dictionary>'转换为System.Collections.Generic.IDictionary>

如果我没有错的话,我们在C#4.0中得到了协方差和反方差,这有什么奇怪的呢

因此,在那次令人震惊的(至少对我来说:-)发现之后,我回到了家,开始测试,即使是最基本的员工,比如(它可以工作):

IEnumerable working=new List();
在这之后,创建.netcore(3.1)项目和测试会给出同样的结果,这让人感到奇怪

所以我的问题是:

  • 我认为这是正常行为还是缺乏测试?(很少有人创建字典的字典)
  • 如果这是正常的,有人能解释它背后的好主意吗?(意思是为什么它是不允许的?可能是一些MSIL问题或CLR问题,我相信有人可以合理地解释,如果这是计划的行为)
谢谢你花时间 4

您的“非接口”指令比接口指令更严格。所以它们不能互换。如果我们稍微简化一下类型,这就更容易讨论了

interface IFoo {}
class Foo : IFoo {}
// ... //

// This is fine. A List is an IList, and every IFoo is an IFoo.
IList<IFoo> myList1 = new List<IFoo>();
// This is fine as well, obviously.
List<Foo> myList2 = new List<Foo>();

// Not fine - an IList might not be a list. Can't be automatically assigned.
List<IFoo> myList3 = myList1;
// Not fine - myList2 can only contain Foo objects, but myList4 should be able to contain any IFoo object.
List<IFoo> myList4 = myList2;
接口IFoo{}
类Foo:IFoo{}
// ... //
//这很好。列表是一个IList,每个IFoo都是一个IFoo。
IList myList1=新列表();
//显然,这也很好。
List myList2=新列表();
//不好-IList可能不是列表。无法自动分配。
列表myList3=myList1;
//不好-myList2只能包含Foo对象,但myList4应该能够包含任何IFoo对象。
列表myList4=myList2;
在您的代码中,
词典
不能与
IDictionary
完成相同的工作。接口one必须接受
IDictionary
类型的任何值。但具体的一个只能接受
字典
类型的值

e、 g

idicational somedictfromwhere=GetOtherDict();
var dict=新字典();
dict.Add(“someKey”,someotherdict fromwhere);//OOPS-无法编译。IDictionary可能不是字典。
将您的
dict
更改为
字典
,一切正常。

“如果我没有错的话,我们在C#4.0中获得了协方差和逆变”——C#对于泛型接口具有类型差异是正确的。但类型差异并不意味着你可以随意混合。它仍然需要是安全的,在您的示例中,它是不安全的,因为字典类型是读/写的,因此既不能是协变量也不能是反变量。请参阅标记的重复问题和数百个类似问题,以了解更多有关原因的详细信息。
var sample = new SampleStackoverflowClass(dict);
IEnumerable<IEnumerable<IEnumerable<object>>> working = new List<List<List<string>>>();
interface IFoo {}
class Foo : IFoo {}
// ... //

// This is fine. A List is an IList, and every IFoo is an IFoo.
IList<IFoo> myList1 = new List<IFoo>();
// This is fine as well, obviously.
List<Foo> myList2 = new List<Foo>();

// Not fine - an IList might not be a list. Can't be automatically assigned.
List<IFoo> myList3 = myList1;
// Not fine - myList2 can only contain Foo objects, but myList4 should be able to contain any IFoo object.
List<IFoo> myList4 = myList2;
IDicationary<string,SomeFunnyStuff> someDictFromSomewhere = GetOtherDict();
    var dict = new Dictionary<string, Dictionary<string, SomeFunnyStuff>>();
dict.Add("someKey", someOtherDictFromSomewhere); // OOPS - won't compile. IDictionary<K,V> might not be a Dictionary<K,V>.