繁体   English   中英

为什么我不能从列表中投射<myclass>列出<object> ?<div id="text_translate"><p> 我有一个对象列表,它们属于我的QuoteHeader类型,我想将此列表作为对象列表传递给能够接受List&lt;object&gt;的方法。</p><p> 我的代码行显示...</p><pre> Tools.MyMethod((List&lt;object&gt;)MyListOfQuoteHeaders);</pre><p> 但是我在设计时收到以下错误...</p><pre> Cannot convert type 'System.Collections.Generic.List&lt;MyNameSpace.QuoteHeader&gt;' to 'System.Collections.Generic.List&lt;object&gt;'</pre><p> 我需要对我的 class 做任何事情来允许这样做吗? 我认为所有类都继承自 object 所以我不明白为什么这不起作用?</p></div></object></myclass>

[英]Why can't I cast from a List<MyClass> to List<object>?

我有一个对象列表,它们属于我的QuoteHeader类型,我想将此列表作为对象列表传递给能够接受List<object>的方法。

我的代码行显示...

Tools.MyMethod((List<object>)MyListOfQuoteHeaders);

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

Cannot convert type 'System.Collections.Generic.List<MyNameSpace.QuoteHeader>' 
to 'System.Collections.Generic.List<object>'

我需要对我的 class 做任何事情来允许这样做吗? 我认为所有类都继承自 object 所以我不明白为什么这不起作用?

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

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# 中,这对于引用类型的 arrays 是合法的:

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 的方法。

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

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

您不能将List<OneType>转换为List<OtherType>因为它实际上是您要转换的列表的实例,以及 List 本身。

有一种扩展方法可以让您执行此操作( MSDN 参考):

IEnumerable<Object> myNewEnumerable = myEnumerable.Cast<Object>();

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

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

A objectOfTypeA;
B objectOfTypeB = (B) objectofTypeA;

为了能够进行强制转换,必须在可用类型之间进行隐式或显式转换,而这是不存在的(除非您提供了一个,您可能可以这样做)。

您希望它能够工作,因为List<object>将始终能够在另一个列表中保存任何类型,但是当您以这些术语考虑它时,您会明白为什么它不能。

我确信有一个技术上更胜任的答案,但我认为这就是它的要点。

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

这个问题也可能有用

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

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

Tools.MyMethod(MyListOfQuoteHeaders.Cast<OtherType>());

感谢您的许多回复。

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

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

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

    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);

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

问题是在编译时,编译器发出 2 个单独的类,1 个代表List<MyClass> ,一个代表List<Object> 它们本质上是两种不同的类型。 这就是通用类型的工作方式,至少在.Net 中是这样。

假设这是.Net,你可以做

MyListOfQuoteHeaders.Cast<Object>()

基本上可以

var objects = new List<Object>();

foreach(var item in MyListOfQuoteHeaders)
{
   objects.Add((object)item);
}

return objects;

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM