Почему я получаю сообщение об ошибке «Параметр типа должен быть неизменным ...»? - PullRequest
7 голосов
/ 26 мая 2011

Я попытаюсь сократить этот пример кода:

public interface IThing
{
    //...  Stuff
}

public class Thing1 : IThing
{  
}

public class Thing2 : IThing
{  
}

public interface IThingView<out T>
{
    ICollection<T> ViewAll();
}

public class ThingView<T> : IThingView<T>
{
    ICollection<T> ViewAll() { return new List<T>(); }  //  There's a big operation here
}

public interface IThingViewerFactory
{
    public IThingView<IThing> Build(string Which);
}

public class ThingViewerFactory
{
    public IThingView<IThing> Build(string Which)
    {
        if(Which.Equals("Thing1") { return new (IThingView<IThing>)new ThingViewer<Thing1>();}
        else { return new (IThingView<IThing>)new ThingViewer<Thing2>();}
    }
}

Это грубое представление о том, что я делаю. У меня есть несколько классов Thing, для которых требуется программа просмотра, которая будет следовать интерфейсу comon. Я хотел бы, чтобы фабрика генерировала их, передавая строку с именем. Я продолжаю получать сообщение об ошибке компилятора:

Недопустимая дисперсия: параметр типа 'T' должен быть неизменно действительным для 'IThingView.ViewAll ()'. 'T' является ковариантным.

Я понимаю, что даже если я получу это на работу, мне придется потом делать кастинг ... Я в порядке с этим. И я понимаю, что такой подход, скорее всего, не нужен. В этот момент это стало скорее вопросом гордости / любопытства.

Спасибо!

Ответы [ 2 ]

11 голосов
/ 26 мая 2011

Вы не можете сделать ковариант ICollection<T>, так как он позволяет поместить в него T s.

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

6 голосов
/ 26 мая 2011

Чтобы раскрыть SLaks, ответьте:
Чтобы компилировать код, измените тип возвращаемого значения ViewAll с ICollection<T> на IEnumerable<T>.

...