【问题标题】:What is the difference between Cast List<object> and Cast IEnumerable<object>Cast List<object> 和 Cast IEnumerable<object> 有什么区别
【发布时间】:2016-02-03 12:45:18
【问题描述】:

我尝试将对象(对象包含List&lt;Apple&gt;)转换为List&lt;object&gt;,但失败并出现异常:

无法将“System.Collections.Generic.List[list_cast_object_test.Apple]”类型的对象转换为“System.Collections.Generic.List[System.Object]”类型。

当我将List 替换为IEnumerableIList(一个接口)时,它运行良好,但我不明白其中的区别......

代码如下:

    private void Form1_Load(object sender, EventArgs e) {
        object resultObject = GetListAsObject();

        // this cast works fine, it's normal...
        var resAsIt = (List<Apple>)resultObject;

        // also when I use a generic interface of 'object' cast works fine
        var resAsIEnumerable = (IEnumerable<object>)resultObject;

        // but when I use a generic class of 'object' it throws me error: InvalidCastException
        var resAsList = (List<object>)resultObject;
    }

    private object GetListAsObject() {
        List<Apple> mere = new List<Apple>();
        mere.Add(new Apple { Denumire = "ionatan", Culoare = "rosu" });
        mere.Add(new Apple { Denumire = "idared", Culoare = "verde" });
        return (object)mere;
    }
}
public class Apple {
    public string Denumire { get; set; }
    public string Culoare { get; set; }
}

有人可以解释一下发生了什么吗?转换为泛型接口和转换为泛型类有什么区别?

【问题讨论】:

  • IEnumerable&lt;T&gt; 是协变的
  • 这是lion eats giraffe 的问题。 IEnumerable&lt;&gt; 对长颈鹿来说是安全的,因为你不能 add lions。

标签: c# class generics interface casting


【解决方案1】:

这是因为IEnumerable&lt;T&gt; T 是协变的,而List&lt;T&gt; T 不支持协变。

查看更多关于Covariance and Contraviance in c#

如果你想做这样的事情,你必须使用 ToList&lt;T&gt;() 重载,它将其包装成对象类型,如:

 List<object> result = resultObject.ToList<object>();

在这里,由于T 的类型为Object,我们能够将List&lt;Apple&gt; 转换为List&lt;Object&gt;,因为T 的类型为Object,但我们不能将原始List&lt;Apple&gt; 引用转换为List&lt;object&gt;

在这种情况下,它将创建 Object 类型的实例,并将对您的类型的引用存储为类型 object 的引用,但在值类型或 strcuts 的情况下,它将具有装箱成本。

【讨论】:

  • resultObject 是一个对象类,没有ToList函数。
  • ToList 是一种扩展方法。在您的班级顶部添加声明using System.Linq;
  • @PatrickHofman OP 从方法返回 List&lt;T&gt; 类型为 Object
【解决方案2】:

IEnumerable&lt;T&gt; 是一个接口,由于T 类型定义为协变的(实际上是IEnumerable&lt;out T&gt;,请注意out),您可以将T 强制转换为基本实现,因此@987654326 @ 是 List&lt;Apple&gt; 类型列表中的有效转换。

但是,List&lt;Apple&gt; 类型不等于List&lt;object&gt; 类型,列表List&lt;Apple&gt; 也不等于List&lt;object&gt;List&lt;T&gt; 上的类型参数是协变的,因此该转换无效。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-05-18
    • 2011-08-12
    • 2013-05-31
    • 2018-06-20
    • 1970-01-01
    • 2019-12-06
    • 2013-04-11
    • 2014-09-03
    相关资源
    最近更新 更多