IEnumerable <IMyInterface> неявно из класса [], но не из структуры []. Зачем?

Дано:

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)
};

Ответ 1

Проблема - это ковариация массива. Эта спецификация говорит об этом:

Для любых двух ссылочных типов A и B, если между A и B существует неявное ссылочное преобразование (раздел 6.1.4) или явное ссылочное преобразование (раздел 6.2.3), то из массива также существует такое же ссылочное преобразование тип A [R] к типу массива B [R], где R - любой заданный спецификатор ранга (но тот же для обоих типов массивов)

Простым примером этого, который также терпит неудачу, является

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

а

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

работает отлично. Вы в основном пытаетесь сделать то же самое. У вас есть массив типов значений MyStruct, и вы пытаетесь неявно использовать его для IMyInterface, который не покрывается спецификацией ковариации массива.

Ответ 2

Тот, который работает, делает неявный бокс, а затем бросается на IMyInterface. Проблема в том, что компилятор не обязательно знает, что struct является IMyInterface. Бокс затем кастинг получает вас, которые описывают ваш объект как IMyInterface.

Я действительно читаю об этом на CLR Via С# прямо сейчас, поэтому, если вы думаете, что я исказил это, пожалуйста, поправьте меня.

Ответ 3

Структура не является классом. При их создании существуют разные правила. Не исследуя его, я предполагаю, что тип не может быть выведен в первом примере, потому что это не класс. Когда это явное, нет проблем.