为什么我不能从List 转换为List ?

我有一个对象列表,它是我的类型QuoteHeader ,我想将此列表作为对象列表传递给一个能够接受List

我的代码行读了……

 Tools.MyMethod((List)MyListOfQuoteHeaders); 

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

 Cannot convert type 'System.Collections.Generic.List' to 'System.Collections.Generic.List' 

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

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

 List giraffes = new List(); List 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 

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

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

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

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

 List giraffes = new List(); IEnumerable animals = giraffes; // Legal in C# 4 foreach(Animal animal in animals) { } // Every giraffe is an animal, so this is safe 

它是安全的,因为IEnumerable不会暴露任何接受 T的方法。

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

  • 从旧列表中创建新的对象列表。
  • 使方法采用object []而不是List ,并使用不安全的数组协方差。
  • 使方法通用,因此需要List
  • 使该方法采用IEnumerable
  • 使该方法采用IEnumerable并使用C#4。

您无法将ListList因为它实际上是您要转换的列表的实例,以及List本身。

有一个扩展方法,允许您这样做( MSDN参考 ):

 IEnumerable myNewEnumerable = myEnumerable.Cast(); 

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

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

 A objectOfTypeA; B objectOfTypeB = (B) objectofTypeA; 

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

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

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

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

这个问题也可能有用

 List x = someList.Select(f => (MyClass)f).ToList(); 

我假设您的意思是列表是相互inheritance的类型,或者可以从一种类型转换为另一种类型 – 在这种情况下,请尝试:

 Tools.MyMethod(MyListOfQuoteHeaders.Cast()); 

感谢您的回复。

我将解释我想做什么以及我提出的解决方案。

我需要一个方法,我可以通过传入任何类型的对象列表调用,然后将该列表输出到XML。 传递给该方法的还有一个字符串,它是一个系统文件结构路径位置,指向XML文件保存到的位置。 由于我有越来越多的类和类型,我想避免编写多种方法来满足每种类型的类。 我不确定我是否以正确的方式解决了这个问题,但它是我的问题和工作的轻量级解决方案。 如果有任何问题,或者如果有人有任何意见,请随意…

所以…我的方法现在看起来像这样……

  public static Enums.Status WriteListToXML(string outputPath, List inboundList) { try { XmlSerializer xmlSerializer = new XmlSerializer(inboundList.GetType()); using (StreamWriter streamWriter = System.IO.File.CreateText(outputPath)) { xmlSerializer.Serialize(streamWriter, inboundList); } return Enums.Status.Success; } catch (Exception ex) { return Enums.Status.Failure; } } 

……我的呼叫线上写着……

 WriteListToXML(@"C:\XMLDocuments\output\QuoteHeaders.xml", quoteHeadersList); 

就像我说的,它可能不是最整洁的解决方案,但它在我的场景中运作良好。

问题是在编译时,编译器会发出2个单独的类,1表示List ,1表示List 。 它们基本上是两种不同的类型。 这至少是.Net中Generic类型的工作方式。

假设这是.Net,你可以做到

 MyListOfQuoteHeaders.Cast() 

这基本上做了

 var objects = new List(); foreach(var item in MyListOfQuoteHeaders) { objects.Add((object)item); } return objects;