c # универсальный список слияния - PullRequest
2 голосов
/ 25 ноября 2010

Как я не смог объединить Список и Список?ООП говорит, что MyType2 - это MyType ...

using System;
using System.Collections.Generic;

namespace two_list_merge
{
    public class MyType
    {
        private int _attr1 = 0;

        public MyType(int i)
        {
            Attr1 = i;
        }

        public int Attr1
        {
            get { return _attr1; }
            set { _attr1 = value; }
        }
    }

    public class MyType2 : MyType
    {
        private int _attr2 = 0;

        public MyType2(int i, int j)
            : base(i)
        {
            Attr2 = j;
        }

        public int Attr2
        {
            get { return _attr2; }
            set { _attr2 = value; }
        }
    }

    class MainClass
    {
        public static void Main(string[] args)
        {
            int count = 5;
            List<MyType> list1 = new List<MyType>();
            for(int i = 0; i < count; i++)
            {
                list1[i] = new MyType(i);
            }

            List<MyType2> list2 = new List<MyType2>();
            for(int i = 0; i < count; i++)
            {
                list1[i] = new MyType2(i, i*2);
            }           

            list1.AddRange((List<MyType>)list2);
        }
    }
}

Ответы [ 4 ]

5 голосов
/ 25 ноября 2010

Я собираюсь предположить, что вы не используете C # 4.0.

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

Не беспокойтесь об академическом жаргоне - это просто термины для разрешенных видов дисперсии (то есть вариации).

Вот хорошая статья о деталях: http://blogs.msdn.com/b/csharpfaq/archive/2010/02/16/covariance-and-contravariance-faq.aspx

Чтобы ваш код работал, напишите:

list1.AddRange(list2.Cast<MyType>());
2 голосов
/ 25 ноября 2010

Если вы используете C # 4 (.NET 4), вы можете просто удалить приведение в последней строке:

list1.AddRange(list2);

Если вы используете C # 3 (.NET 3.5)вам нужно использовать расширение LINQ для Cast ():

list1.AddRange(list2.Cast<MyType>());

Причина, по которой вы не можете преобразовать list2 в List, заключается в том, что List не является ковариантным.Вы можете найти хорошее объяснение того, почему это не так:

В C #, почему объект List не может быть сохранен в List variable

Причина, по которой первая строка работает, заключается в том, что AddRange () принимает IEnumerable, а IEnumerable является ковариантным..NET 3.5 не реализует ковариацию обобщенных коллекций и, следовательно, необходимость в Cast () в C # 3.

0 голосов
/ 25 ноября 2010

Вы не можете сделать это, потому что MyType2 - это MyType, но List<MyType2> - это не List<MyType>.Не существует отношения наследования между 2 List<XXX> типами.

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

    list1.AddRange(list2.Cast<MyType>());
0 голосов
/ 25 ноября 2010

Возможно, попробуйте использовать LINQ, если можете, вместе с явным приведением к MyType.Использование C # 4.

List<MyType> list1 = new List<MyType> 
     { new MyType(1), new MyType(2), new MyType(3)};

List<MyType2> list2 = new List<MyType2> 
     { new MyType2(11,123), new MyType2(22,456), new MyType2(33, 789) };

var combined = list1.Concat(list2.AsEnumerable<MyType>());
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...