Cast List <object>和Cast IEnumerable <object>之间的区别是什么?

Ovi*_*udi 4 c# generics casting interface class

我试图从对象(对象包含一个List<Apple>)转换为List<object>,但它失败并出现异常:

无法将类型为"System.Collections.Generic.List [list_cast_object_test.Apple]"的对象强制转换为"System.Collections.Generic.List [System.Object]".

当我ListIEnumerableIList(接口)替换它时效果很好,我不明白它的区别......

代码如下:

    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; }
}
Run Code Online (Sandbox Code Playgroud)

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

Ehs*_*jad 6

这是因为in IEnumerable<T> T是协变而in List<T> T不支持协方差.

在c#中查看有关Covariance和Contraviance的更多信息

如果你想做那样的事情,那么你必须使用ToList<T>()重载,它将它包装到对象类型,如:

 List<object> result = resultObject.ToList<object>();
Run Code Online (Sandbox Code Playgroud)

在这里我们能够转换List<Apple>List<Object>由于新List<T>创建T的类型,Object但我们不能将原始List<Apple>引用转换为List<object>.

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