IEnumerable<;IMyInterface>;隐含地来自类[],但不来自结构[].为什么?

本文关键字:结构 为什么 gt IMyInterface IEnumerable lt | 更新日期: 2023-09-27 17:53:29

给定:

public interface IMyInterface{
}
public class MyClass:IMyInterface{
     public MyClass(){}
}
public struct MyStruct:IMyInterface{
     private int _myField;
     public MyStruct(int myField){_myField = myField;}
}

为什么我可以写:

IEnumerable<IMyInterface> myClassImps = new[] {
    new MyClass(),
    new MyClass(),
    new MyClass()
};

但不是:

IEnumerable<IMyInterface> myStructImps = new[]{
    new MyStruct(0),
    new MyStruct(1),
    new MyStruct(2)
};

这给了我以下警告:

错误29无法将类型"MyApp.MyNS.MyStruct[]"隐式转换为"System.Collections.Generic.IEnumerable<MyApp.MyNS.IMyInterface>'

必须改为:

IEnumerable<IMyInterface> myStructImps = new IMyInterface[]{
    new MyStruct(0),
    new MyStruct(1),
    new MyStruct(2)
};

IEnumerable<;IMyInterface>;隐含地来自类[],但不来自结构[].为什么?

问题是数组协方差。这个规范谈论它:

对于任何两种引用类型A和B,如果存在从A到B的隐式引用转换(第6.1.4节(或显式引用转换

一个同样失败的简单例子是

int[] c = new int[0];
object[] d = c;

string[] c = new string[0];
object[] d = c;

工作良好。你基本上是在尝试做同样的事情。您有一个值类型为MyStruct的数组,并试图将其隐式转换为IMyInterface,这不在数组协方差规范中。

工作的执行隐式装箱,然后转换为IMyInterface。问题是编译器不一定知道该结构是IMyInterface。拳击然后施法让你把你的物体描述为IMyInterface。

事实上,我现在正在CLR Via C#中读到这篇文章,所以如果你认为我歪曲了这一点,请纠正我。

结构不是类。实例化它们时有不同的规则。如果不研究它,我的猜测是,在你的第一个例子中无法推断出类型,因为它不是一个类。如果它是明确的,就没有问题。