c#4.0:int一个真实的对象子类型? 协方差,可数和值类型

我想知道为什么IEnumerable不能分配给IEnumerable 。 毕竟IEnumerable是支持协方差的少数接口之一……

  • 子类型关系和协方差的东西适用于引用类型
  • int似乎是object的正确子类型

两种function的组合不起作用……

 class A { } class B : A { } class Program { static void Main(string[] args) { bool b; b = typeof(IEnumerable).IsAssignableFrom(typeof(List)); Console.WriteLine("ienumerable of ref types is covariant: " + b); //true b = typeof(IEnumerable).IsAssignableFrom(typeof(List)); Console.WriteLine("ienumerable of value tpyes is covariant: " + b); //false b = typeof(object).IsAssignableFrom(typeof(int)); Console.WriteLine("int is a subtype of object: " + b); //true } } 

谢谢你的帮助! 塞巴斯蒂安

在盒装之前,值类型不是对象的LSP子类型。

方差不适用于值类型。 完全没有。


certificateint不是对象的正确子类型 (LSP意义上的子类型):

作品:

 object x = new object(); lock (x) { ... } 

不起作用(违反替代性):

 int y = new int(); lock (y) { ... } 

返回true:

 object x = new object(); object a = x; object b = x; return ReferenceEquals(a, b); 

返回false(违反替代性):

 int y = new int(); object a = y; object b = y; return ReferenceEquals(a, b); 

当然,问题的主题(界面差异)是第三个演示。

问题是object是引用类型,而不是值类型。 您可以将int分配给object类型的变量的唯一原因是装箱。

为了将List分配给IEnumerable您必须选中列表中的每个元素。 您不能仅通过将引用分配给列表并将其称为其他类型来实现此目的。

简单的答案是,这只是在C#和CLR中实现方差的方式之一。

从“generics中的协方差和逆变” :

差异仅适用于参考类型; 如果为变量类型参数指定值类型,则该类型参数对于生成的构造类型是不变的。

.net中的每个值类型都有一个对应的(“盒装”)对象类型。 非盒装值类型实际上在对象类型层次结构之外,但编译器将执行从值类型到盒装类类型的扩展。 有一个“类”Boxed 会有所帮助,它将支持与T之间的扩展转换,但这将是一个类类型。 在内部,我认为这是编译器隐含的做法,但我不知道如何明确地做到这一点。 对于像“整数”这样的任何特定类型,定义一个类似于Boxed 的类都没有困难,但我不知道以通用方式做这样的事情的任何方式。