2011-04-28 17 views
10

考虑:IEnumerable <IMyInterface>隐式地从类[]但不是来自Struct []。为什么?

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.Co llections.Generic.IEnumerable <MyApp.MyNS.IMyInterface>'

,而必须写成:

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

回答

4

问题是数组协方差。 This specification谈论它:

对于任何两个引用类型A和B,如果隐式引用转换(第6.1.4节)或显式引用转换(第6.2.3节)中存在从A到B,则相同的参考转换也从数组类型A [R]存在于阵列类型B [R],其中R是任何给定的秩指示符(但是相同的两种阵列类型)

这方面的一个简单的例子那也失败了

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

while

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

工作正常。你基本上正在尝试做同样的事情。您有一组数值类型MyStruct,并且您试图隐式将其转换为IMyInterface,该数组未包含在数组协方差规范中。

+0

这个问题用C#3.0标记,所以你说什么差异? – 2011-04-28 21:43:00

+0

@Darin对不起错误的引用 – 2011-04-28 21:52:34

+0

了解我确实看到我的答案中存在空白,但我不明白这个解释的一件事是,如果这实际上只是一个协变问题,那他为什么要实例化赋值enumerable用'MyClass'的数组,但不包含'MyStruct'的数组。这尤其是为什么我认为这与拳击有关。 – LJM 2011-04-29 02:56:57

0

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

1

工作的人确实隐式装箱,然后投射到IMyInterface。问题是编译器不一定知道该结构是一个IMyInterface。拳击然后铸造得到你描述你的对象作为IMyInterface。

我实际上是在阅读关于CLR Via C#的文章,所以如果您认为我错误地表达了这一点,请纠正我。

+1

“[T]编译器不一定知道该结构是一个'IMyInterface'”但他有结构的定义,所以他确实知道它实现了接口。 – svick 2011-04-28 22:28:19

相关问题