【问题标题】:Type inherited from List<T> cannot be assigned with List<T>从 List<T> 继承的类型不能用 List<T> 分配
【发布时间】:2025-12-18 21:50:02
【问题描述】:

例子:

        public class ListInheritanceTest
        {
            public void Test1()
            {
                List<string> list = new List<string>();
                MyList myList = list;
            }
        }
        public class MyList : List<string>
        {
        }

MyList myList = list 出现错误“无法将类型 'System.Collections.Generic.List' 隐式转换为 'ConsoleTest.MyList'”

我该如何解决这个问题?谢谢。

----编辑----
我不是在问为什么它会给出错误。我想知道使分配工作的解决方法是什么。 上面的代码只是一个简化的例子。目的是在我的代码中将所有 List&lt;SomeType&gt; 转换为 MyList 而不引入任何向后不兼容。

--- 第二次编辑----

让我重新表述这个问题。假设我在上面的代码中以相同的方式定义了 MyList。 List&lt;string&gt; 分配给 MyList 的最简单方法是什么。

我知道

            foreach(var item in list)  
            mylist.Add(item)  

始终有效。只是在寻找更优雅的东西。

【问题讨论】:

  • MyList 扩展 List&lt;T&gt;,所以 MyList 是 List&lt;T&gt;。另一方面,List&lt;T&gt; 不是 MyList 并且不能分配给一个。
  • 您需要将列表中的项目添加到我的列表中
  • MyList myList = new MyList(); 如果这不是答案,你想做什么?
  • 要扩展@JoachimIsaksson 的评论,请查看任何基本的继承教程。您可能会看到某种继承结构,例如Dog : AnimalCat : Animal。如果您有Animal animal = new Cat();,您如何分配Dog dog = animal;
  • 您正试图将猫变成狮子并让它发出咆哮声!不行,那只猫只会喵喵叫。

标签: c# class generics inheritance


【解决方案1】:

我该如何解决这个问题?

改变你的设计。你不能沮丧 - MyList List&lt;string&gt; 但反之亦然。您可以通过重新使用接受任何IEnumerable&lt;T&gt;(包括List&lt;string&gt;)的List&lt;T&gt; 复制构造函数将项目复制到新列表中:

public class ListInheritanceTest
{
    public void Test1()
    {
        List<string> list = new List<string>();
        MyList myList = new MyList(list);  // copy the items in the list
    }
}
public class MyList : List<string>
{
   public MyList(IEnumerable<string> list) : base(list) {}  // reuse the List<T> copy constructor
}

目的是将代码中的所有List 转换为MyList 而不引入任何向后不兼容。

再一次,你不能。 List 不是 MyList。最好的办法是使用复制构造函数或其他方法将列表转换MyList

List&lt;string&gt; 分配给MyList 的最简单方法是什么。

不能List&lt;string&gt; 不一定MyList。就像Cat 不是Tiger 一样。它可能是,但你不能只是 cast 并且把它当作它是。

请注意,如果您创建列表为MyList(例如List&lt;T&gt; newList = new MyList()),那么您可以安全地转换它。事实上,您可以在其他任何地方使用它,就好像它是List&lt;string&gt;(因为它是!)但是您不能安全地将任意List&lt;string&gt; 转换为MyList。期间。

【讨论】:

  • 我认为这可能是将 List 复制到 MyList 的最佳方式
【解决方案2】:

你不能这样做。考虑:

public class MyList : List<string>
{
    public string DoSomething()
    {
        return "Something";
    }
}

//...

List<string> l = new List<string>();
((MyList)l).DoSomething(); // ERROR - List<string> does not define DoSomething()!

【讨论】:

    【解决方案3】:

    我认为这解决了问题,并允许添加任何列表之王(字符串,int,.....):

        public class ListInheritanceTest
        {
            public void Test1()
            {
                List<string> list = new List<string>() { "1", "2", "3", "4", "5" };
    
                MyList<string> myList = new MyList<string>();
                myList.AddRange(list);
    
                foreach (var item in myList)
                {
                    Console.WriteLine(item);
                }
            }
        }
        public class MyList<T> : List<T>
        {
        }
    

    另一种方式,因为 MyList 是从 List 派生的(这将适用于某些特定情况,因为上面的示例更好):

        public class ListInheritanceTest
        {
            public void Test1()
            {
                List<string> list = new MyList<string> { "1", "2", "3", "4", "5" };
    
                MyList<string> myList = (MyList<string>) list;
    
    
                foreach (var item in myList)
                {
                    Console.WriteLine(item);
                }
            }
        }
        public class MyList<T> : List<T>
        {
        }
    

    【讨论】:

    • AddRange 是完成这项工作的好方法!
    • thnx,我会用另一种方式编辑,但这会“更好”。
    【解决方案4】:

    如果您想避免复制列表,则必须稍微更改一下 MyList。这将允许您随时包装您的 List 并拥有相同的界面,而无需复制元素。

    class MyList : IList<string>
    {
        private readonly List<string> theList;
    
        public MyList(List<string> list)
        {
            theList = list;
        }
    
        // Implement the IList<string> interface by
        // calling the same methods on theList
    }
    
    List<string> oldList = new List<string>();
    MyList wrapper = new MyList(oldList);
    

    【讨论】: