Как вы управляете классом C # Generics, где тип является контейнером базового класса? - PullRequest
0 голосов
/ 11 июня 2011

Я получаю следующую ошибку

Наилучшее совпадение перегруженного метода для `System.Collections.Generic.List> .Add (MyContainer) 'имеет недопустимые аргументы (CS1502) (GenericsTest)

Для следующего класса:

A и B - дочерние классы MyBase.

public class GenericConstraintsTest
{

    private MyList<MyContainer<MyBase>> myList = new MyList<MyContainer<MyBase>>();

    public GenericConstraintsTest ()
    {
        MyContainer<A> ca = new MyContainer<A>(new A());

        this.Add<A>(new A());
        this.Add<B>(new B());
    }


    public void Add<S> (S value) where S : MyBase
    {
        MyContainer<S> cs = new MyContainer<S>(value);
        myList.Add(cs);    
    }


    public static void Main()
    {
        GenericConstraintsTest gct = new GenericConstraintsTest();
    }
}

Что я делаю не так?

Приветствия

1 Ответ

6 голосов
/ 11 июня 2011

Вы пытаетесь позвонить myList.Add с MyContainer<A> и MyContainer<B> соответственно. Ни один из них не может быть преобразован в MyContainer<MyBase>, поскольку два экземпляра универсального типа с различными параметрами универсального типа всегда не связаны, даже если параметры типа связаны между собой.

Единственный способ сделать это - создать IMyContainer<out T> ковариантный универсальный интерфейс. Это позволит вам разыграть IMyContainer<A> до IMyContainer<MyBase>, если A происходит от MyBase. (Примечание: только интерфейсы могут иметь параметры ковариантного и контравариантного типа, и это доступно только в .Net 4).

Например:

public interface IMyContainer<out T> { }
public class MyContainer<T> : IMyContainer<T> 
{
    public MyContainer(T value) { }
}
public class MyBase { }
public class A : MyBase { }
public class B : MyBase { }

public class GenericConstraintsTest
{

    private List<IMyContainer<MyBase>> myList = new List<IMyContainer<MyBase>>();

    public GenericConstraintsTest()
    {
        MyContainer<A> ca = new MyContainer<A>(new A());

        this.Add<A>(new A());
        this.Add<B>(new B());
    }


    public void Add<S>(S value) where S : MyBase
    {
        MyContainer<S> cs = new MyContainer<S>(value);
        myList.Add(cs);
    }


    public static void Main()
    {
        GenericConstraintsTest gct = new GenericConstraintsTest();
    }
}
...