Как сделать универсальный класс с наследованием? - PullRequest
1 голос
/ 20 мая 2009

Как я могу заставить работать следующий код? Я не думаю, что я вполне понимаю C # дженерики. Возможно, кто-то может указать мне правильное направление.

    public abstract class A
    {
    }

    public class B : A
    {
    }

    public class C : A
    {
    }

    public static List<C> GetCList()
    {
        return new List<C>();
    }

    static void Main(string[] args)
    {
        List<A> listA = new List<A>();

        listA.Add(new B());
        listA.Add(new C());

        // Compiler cannot implicitly convert
        List<A> listB = new List<B>();

        // Compiler cannot implicitly convert
        List<A> listC = GetCList();

        // However, copying each element is fine
        // It has something to do with generics (I think)
        List<B> listD = new List<B>();
        foreach (B b in listD)
        {
            listB.Add(b);
        }
    }

Это, вероятно, простой ответ.

Обновление: Во-первых, это невозможно в C # 3.0, но будет возможно в C # 4.0.

Чтобы запустить его в C # 3.0, который является обходным решением до 4.0, используйте следующее:

        // Compiler is happy
        List<A> listB = new List<B>().OfType<A>().ToList();

        // Compiler is happy
        List<A> listC = GetCList().OfType<A>().ToList();

Ответы [ 2 ]

5 голосов
/ 20 мая 2009

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

List<Giraffe> giraffes = new List<Giraffe>();
List<Animal> animals = giraffes; // suppose this were legal.
// animals is now a reference to a list of giraffes, 
// but the type system doesn't know that.
// You can put a turtle into a list of animals...
animals.Add(new Turtle());  

И, эй, вы просто поместили черепаху в список жирафов, и теперь целостность системы типов нарушена. Вот почему это незаконно.

Ключевым моментом здесь является то, что «животные» и «жирафы» относятся к ОДНОМУ ОДНОМУ ОБЪЕКТУ, а этот объект представляет собой список жирафов. Но список жирафов не может сделать столько же, сколько список животных; в частности, он не может содержать черепаху.

3 голосов
/ 20 мая 2009

вы всегда можете сделать это

List<A> testme = new List<B>().OfType<A>().ToList();

Как указал "Боян Ресник", вы также можете сделать ...

List<A> testme = new List<B>().Cast<A>().ToList();

Разница в том, что приведение () завершится неудачей, если один или несколько типов не совпадают. Где OfType () вернет IEnumerable , содержащий только объекты, которые могут быть преобразованы

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...