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