Подтвердить что ты не робот

Struct vs class, реализующий интерфейс

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 > '. Явное преобразование существует (вы пропускаете листинг?)

Почему?
Почему существует различие между классами и структурами? Любые обходные пути?

4b9b3361

Ответ 1

Как и Bharathram Attiyannan ответил, дисперсия просто не поддерживается для типов значений.

Обходной путь прост:

List<FooStruct> listOfFooStruct = new List<FooStruct>();
IEnumerable<IFoo> enumerableOfFoo = listOfFooStruct.Cast<IFoo>();

Ответ 2

Об этом уже ответили - Почему ковариация и контравариантность не поддерживают тип значения, но суммируя его для более удобного поиска.

Поведение, которое вы пытаетесь реализовать, называется Variance.

Это связано с ограничением, применяемым в CLR, которое объясняется в Eric Lippert Blog -

Ковариантные и контравариантные преобразования интерфейса и делегата типы требуют, чтобы все переменные аргументы типа были ссылочными типами

Причина объясняется в MSDN:

Отклонение применяется только к ссылочным типам; если вы укажете тип значения для параметра типа варианта этот параметр типа инвариантен для результирующий построенный тип.