为什么我不能从List <MyClass>转换为List <object>?

Kar*_*arl 23 c# generics casting covariance

我有一个对象列表,这是我的类型QuoteHeader,我想将此列表作为对象列表传递给一个能够接受的方法List<object>.

我的代码行读了......

Tools.MyMethod((List<object>)MyListOfQuoteHeaders);
Run Code Online (Sandbox Code Playgroud)

但是我在设计时遇到以下错误......

Cannot convert type 'System.Collections.Generic.List<MyNameSpace.QuoteHeader>' 
to 'System.Collections.Generic.List<object>'
Run Code Online (Sandbox Code Playgroud)

我是否需要对我的班级做任何事情才允许这样做?我以为所有类都继承自对象,所以我无法理解为什么这不起作用?

Eri*_*ert 41

这不合法的原因是因为它不安全.假设它是合法的:

List<Giraffe> giraffes = new List<Giraffe>();
List<Animal> animals = giraffes; // this is not legal; suppose it were.
animals.Add(new Tiger());  // it is always legal to put a tiger in a list of animals
Run Code Online (Sandbox Code Playgroud)

但"动物"实际上是长颈鹿的名单; 你不能把老虎列入长颈鹿名单.

不幸的是,在C#中,这与引用类型数组合法:

Giraffe[] giraffes = new Giraffe[10];
Animal[] animals = giraffes; // legal! But dangerous because...
animals[0] = new Tiger(); // ...this fails at runtime!
Run Code Online (Sandbox Code Playgroud)

在C#4中,这在IEnumerable上是合法的,但不是IList:

List<Giraffe> giraffes = new List<Giraffe>();
IEnumerable<Animal> animals = giraffes; // Legal in C# 4
foreach(Animal animal in animals) { } // Every giraffe is an animal, so this is safe
Run Code Online (Sandbox Code Playgroud)

它是安全的,因为IEnumerable<T>不暴露任何接受 T的方法.

要解决您的问题,您可以:

  • 从旧列表中创建一个新的对象列表.
  • 使方法采用对象[]而不是a List<object>,并使用不安全的数组协方差.
  • 使方法通用,所以需要一个 List<T>
  • 使该方法采用IEnumerable
  • 使方法采用IEnumerable<object>并使用C#4.


小智 6

List<MyClass> x = someList.Select(f => (MyClass)f).ToList();
Run Code Online (Sandbox Code Playgroud)

  • 欢迎来到这里,在这里,解释为什么使用您的解决方案而不仅仅是如何使用是一个很好的做法。这将使您的答案更有价值,并帮助更多的读者更好地理解您是如何做到的。我还建议您查看我们的常见问题解答:http://stackoverflow.com/faq。 (4认同)

Sam*_*der 5

你不能List<OneType>转换List<OtherType>为实际上是你想要转换的列表的实例,以及List本身.

有一个扩展方法,可以让你这样做(MSDN参考):

IEnumerable<Object> myNewEnumerable = myEnumerable.Cast<Object>();
Run Code Online (Sandbox Code Playgroud)

此方法将尝试将一种类型的列表的每个实例转换为另一种类型,并将它们添加到新的可枚举中.如果无法转换任何实例,它将抛出异常.

就系统而言,列表的两种类型只是不同的类型,所以就像说:

A objectOfTypeA;
B objectOfTypeB = (B) objectofTypeA;
Run Code Online (Sandbox Code Playgroud)

为了能够进行强制转换,必须在可用类型之间进行隐式或显式转换,但没有(除非您提供了一个,您可以做到).

你希望它能够工作,因为它List<object>总是可以在另一个列表中保存任何类型,但是当你在这些术语中考虑它时,你可以看到它为什么没有.

我确信有一个技术上更有能力的答案,但我认为这就是它的主旨.

您可能有兴趣阅读Eric Lippert关于协方差和逆变的系列,因为这可能对您有所帮助.

这个问题也可能有用