为什么根据我初始化值的方式,将IEnumerable <t>的值转换为不同的行为?

时间:2016-05-31 18:25:02

标签: c# casting

我有一些代码带有一个值(类型为object)并试图将它转换为IEnumerable的int和uint,如下所示:

run_gui()
{
    exec "$GAME_BIN" $args <&$gui_infd >&$gui_outfd
}

run_ai1()
{
    exec "$ai1" <&$ai1_infd >&$ai1_outfd
}

以这种方式初始化值时:

var idList = value as IEnumerable<int>;
var uintList = value as IEnumerable<uint>;

idList和uintList都有值,但调用idList.ToList()会产生uint number = 1; object value = new []{ number }; 。但是,当使用ArrayTypeMismatchException生成值时,idList按预期为null。

此外,在VS 2015的即时窗口中调用new List<uint>{ number }会返回null,正如我所期望的那样,即使该值是使用集合初始化程序生成的。

.Net fiddle reproducing the error here

这里发生了什么?

1 个答案:

答案 0 :(得分:3)

我认为这是因为C#和CLR如何处理intuint之间的转换,如answer所述。首先请注意,此代码不会编译:

uint[] a1 = new[] { 1u };
var a2 = (int[])a1;

因为C#并不相信存在演员阵容。但是如果你走这条路:

uint[] a1 = new[] { 1u };
var a2 = (int[]) (object) a1;

运行时将决定此演员表是否有效,并且它(CLR)的思维方式不同,并且允许从uint[]转换为int[](反之亦然),如我所链接的答案中所描述的那样。< / p>

List<int>List<uint>的情况并非如此 - CLR并未对它们进行特殊处理,因此无法在彼此之间进行处理。

因此,在您的情况下,uint[]可以转换为int[]int[]实现IEnumerable<int>,因此您的idList不会为空。列表不是这样 - 因此你的问题。

至于为什么ToList在第一种情况下失败,那是因为内部它做了类似的事情:

 uint[] a1 = new[] { 1u };
 var a2 = (int[]) (object) a1;
 // ToList copies contents to new array
 int[] copy = new int[a2.Length];
 Array.Copy(a2, copy, a2.Length);

Array.Copy直接检查一个数组中的元素类型是否与另一个数组中的元素类型兼容。