我有一个对象列表,它是我的类型QuoteHeader
,我希望将此列表作为对象列表传递给能够接受List<object>
的方法。
我的代码行是......
Tools.MyMethod((List<object>)MyListOfQuoteHeaders);
但我在设计时遇到以下错误......
Cannot convert type 'System.Collections.Generic.List<MyNameSpace.QuoteHeader>'
to 'System.Collections.Generic.List<object>'
我是否需要对班级做任何事情才允许这样做?我以为所有类都继承自对象,所以我无法理解为什么这不起作用?
答案 0 :(得分:39)
这不合法的原因是因为它不安全。假设它是合法的:
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
但“动物”实际上是长颈鹿的名单;你不能把老虎列入长颈鹿名单。
在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<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
这是安全的,因为IEnumerable<T>
没有公开任何接收 T的方法。
要解决您的问题,您可以:
List<object>
,并使用不安全的数组协方差。List<T>
IEnumerable<object>
并使用C#4。答案 1 :(得分:5)
您无法将List<OneType>
转换为List<OtherType>
,因为它实际上是您要投射的列表的实例,以及列表本身。
有一种扩展方法可以让你这样做(MSDN reference):
IEnumerable<Object> myNewEnumerable = myEnumerable.Cast<Object>();
此方法将尝试将一种类型列表的每个实例强制转换为另一种类型,并将它们添加到新的枚举中。如果无法转换任何实例,它将抛出异常。
就系统而言,列表的两种类型只是不同的类型,所以就像说:
A objectOfTypeA;
B objectOfTypeB = (B) objectofTypeA;
为了能够进行强制转换,必须在可用类型之间进行隐式或显式转换,但没有(除非你提供了一个,你可以做到)。
您希望它能够正常运行,因为List<object>
始终能够在其他列表中保留任何类型,但是当您按照这些条款考虑它时,您可以看到它为什么没有。
我确信有一个技术上更有能力的答案,但我认为这就是它的主旨。
您可能有兴趣阅读Eric Lippert's series on Covariance and Contravariance,因为这可能会对您有所帮助。
This question也可能有用
答案 2 :(得分:3)
List<MyClass> x = someList.Select(f => (MyClass)f).ToList();
答案 3 :(得分:1)
我认为你的意思是列表是相互继承的类型,或者可以从一种类型转换为另一种类型 - 在这种情况下,试试这个:
Tools.MyMethod(MyListOfQuoteHeaders.Cast<OtherType>());
答案 4 :(得分:0)
感谢您的回复。
我将解释我想做什么以及我作为解决方案提出的内容。
我需要一个方法,我可以通过传入任何类型的对象列表来调用,然后将该列表输出到XML。传递给该方法的还有一个字符串,它是一个系统文件结构路径位置,指向XML文件保存到的位置。由于我有越来越多的类和类型,我想避免编写多种方法来满足每种类型的类。我不确定我是否以正确的方式解决了这个问题,但它是解决我的问题和工作的轻量级解决方案。如果有任何问题,或者如果有人有任何意见,请随意...
所以...我的方法现在看起来像这样......
public static Enums.Status WriteListToXML<T>(string outputPath, List<T> 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<QuoteHeader>(@"C:\XMLDocuments\output\QuoteHeaders.xml", quoteHeadersList);
就像我说的那样,它可能不是最整洁的解决方案,但它在我的场景中运作良好。
答案 5 :(得分:-1)
问题在于,在编译时,编译器会发出2个单独的类,1代表List<MyClass>
,1代表List<Object>
。它们基本上是两种不同的类型。这就是Generic类型的工作方式,至少在.Net中。
假设这是.Net,你可以做
MyListOfQuoteHeaders.Cast<Object>()
基本上是
var objects = new List<Object>();
foreach(var item in MyListOfQuoteHeaders)
{
objects.Add((object)item);
}
return objects;