代码之家  ›  专栏  ›  技术社区  ›  Darius Kucinskas

通用列表合并

  •  2
  • Darius Kucinskas  · 技术社区  · 14 年前

    我不能合并列表和列表吗?OOP说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 回复  |  直到 14 年前
        1
  •  5
  •   Bevan    14 年前

    我假设你没有使用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
  •  2
  •   Community kfsone    7 年前

    如果您使用的是C#4(.NET 4),只需删除最后一行中的演员:

    list1.AddRange(list2);
    

    如果使用的是C#3(.NET 3.5),则需要使用Cast()LINQ扩展名:

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

    无法将list2强制转换为List的原因是该List不是协变的。你可以在这里找到一个很好的解释为什么不是这样:

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

    第一行工作的原因是AddRange()接受IEnumerable,而IEnumerable是协变的。.NET3.5不实现泛型集合的协方差,因此需要在C#3中使用Cast()。

        3
  •  0
  •   p.campbell    14 年前

    如果可以的话,可以尝试使用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>());
    
        4
  •  0
  •   Alexei Levenkov    14 年前

    你不能这么做,因为MyType2是MyType,但是 List<MyType2> 不是 List<MyType> . 2之间没有继承关系 List<XXX> 类型。

    通过使用LINQ的Cast方法,您可以轻松地完成复制,该方法将每个元素强制转换为所需的类型。

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