简体   繁体   中英

c# generic list merge

Way I could not merge List and List? OOP says MyType2 is 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);
        }
    }
}

I'm going to assume that you're not using C# 4.0.

In earlier versions of C#, this won't work because the language doesn't support contravariance and covariance of generic types.

Don't worry about the academic jargon - they're just the terms for the kinds of variance (ie variation) permitted.

Here's a good article on the details: http://blogs.msdn.com/b/csharpfaq/archive/2010/02/16/covariance-and-contravariance-faq.aspx

To make your code work, write this:

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

If you're using C#4 (.NET 4), you can simply remove the cast in your last line:

list1.AddRange(list2);

If you're using C#3 (.NET 3.5), you need to using the Cast() LINQ extension:

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

The reason that you can't cast list2 to List is that List is not covariant. You can find a good explanation of why this is not the case here:

In C#, why can't a List<string> object be stored in a List<object> variable

The reason the first line works is that AddRange() takes an IEnumerable and IEnumerable is covariant. .NET 3.5 does not implement covariance of generic collections and hence the need for the Cast() in C#3.

Perhaps try using LINQ if you can, along with an explicit cast to MyType . Using 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>());

You can't do that because MyType2 is MyType, but List<MyType2> is not List<MyType> . There are no inheritance relationship between 2 List<XXX> types.

You can easily achive copying by using LINQ's Cast method which will cast each element to type you want.

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM