以下是我遇到的问题的简化版本:
var list = new List<int> {1, 2, 3, 4, 5};
// list Count = 5 System.Collections.Generic.List<int>
var obj = list as object;
// obj Count = 5 object {System.Collections.Generic.List<int>}
var enumerable = obj as IEnumerable<object>;
// enumerable null System.Collections.Generic.IEnumerable<object>
注释是Visual Studio 2017中观察窗口中的值
但是,如果我输入:
obj as IEnumerable<object>
在观察窗口中,我得到:
obj as IEnumerable<object> Count = 5 System.Collections.Generic.IEnumerable<object> {System.Collections.Generic.List<int>}
那么为什么我可以在监视窗口中投射它并且它可以工作,但如果我在代码中执行它,它的计算结果为null?
答案 0 :(得分:9)
仅针对参考类型支持通用接口的差异。值类型不支持方差。例如,
IEnumerable<int>
无法隐式转换为IEnumerable<object>
,因为整数由值类型表示。
这里有一点有用的是,以下两件事情是非常不同的操作:
var l = (object) new List<int>();
var i = (object) 42;
尽管语法看起来一样。第一行仅将列表视为另一种类型(有些检查是否实际上可以使用强制转换),而第二行将整数转换为包含它的对象(装箱)。第三个变体是调用转换运算符,但看起来仍然相同。由于第一种变体可以随意改变对象并且只是以不同的方式解释它,它比第二种变体便宜得多。我在这个上下文中猜测这是唯一可以用于接口协方差的选项。