Ответ 1
Как и Bharathram Attiyannan ответил, дисперсия просто не поддерживается для типов значений.
Обходной путь прост:
List<FooStruct> listOfFooStruct = new List<FooStruct>();
IEnumerable<IFoo> enumerableOfFoo = listOfFooStruct.Cast<IFoo>();
private static void TestStructInterface()
{
IFoo foo1 = new FooClass(); // works
IFoo foo2 = new FooStruct(); // works
IEnumerable<IFoo> foos1 = new List<FooClass>(); // works
IEnumerable<IFoo> foos2 = new List<FooStruct>(); // compiler error
}
interface IFoo
{
string Thing { get; set; }
}
class FooClass : IFoo
{
public string Thing { get; set; }
}
struct FooStruct : IFoo
{
public string Thing { get; set; }
}
Компилятор жалуется:
Невозможно неявно преобразовать тип 'System.Collections.Generic.List < Tests.Program.FooStruct > ' к 'System.Collections.Generic.IEnumerable < Tests.Program.IFoo > '. Явное преобразование существует (вы пропускаете листинг?)
Почему?
Почему существует различие между классами и структурами?
Любые обходные пути?
Как и Bharathram Attiyannan ответил, дисперсия просто не поддерживается для типов значений.
Обходной путь прост:
List<FooStruct> listOfFooStruct = new List<FooStruct>();
IEnumerable<IFoo> enumerableOfFoo = listOfFooStruct.Cast<IFoo>();
Об этом уже ответили - Почему ковариация и контравариантность не поддерживают тип значения, но суммируя его для более удобного поиска.
Поведение, которое вы пытаетесь реализовать, называется Variance.
Это связано с ограничением, применяемым в CLR, которое объясняется в Eric Lippert Blog -
Ковариантные и контравариантные преобразования интерфейса и делегата типы требуют, чтобы все переменные аргументы типа были ссылочными типами
Причина объясняется в MSDN:
Отклонение применяется только к ссылочным типам; если вы укажете тип значения для параметра типа варианта этот параметр типа инвариантен для результирующий построенный тип.