繁体   English   中英

为什么枚举数组可以转换为两个不同的IEnumerable <T> 类型?

[英]Why can enum arrays be cast to two different IEnumerable<T> types?

我似乎偶然发现了C#中不寻常的一些我不完全理解的东西。 假设我定义了以下枚举:

public enum Foo : short 
{
    // The values aren't really important
    A,
    B
}

如果我声明一个Foo数组或通过Enum.GetValues检索一个Enum.GetValues ,我就能成功地将它转换为IEnumerable<short>IEnumerable<ushort> 例如:

Foo[] values = Enum.GetValues( typeof( Foo ) );
// This cast succeeds as expected.
var asShorts = (IEnumerable<short>) values;
// This cast also succeeds, which wasn't expected.
var asUShorts = (IEnumerable<ushort>) values;
// This cast fails as expected:
var asInts = (IEnumerable<int>) values;

对于其他基础类型也会发生这种情况。 枚举数组似乎总是可以转换为底层整数类型的有符号和无符号版本。

我无法解释这种行为。 这是明确定义的行为还是我偶然发现了语言或CLR的特殊怪癖?

它不仅仅是IEnumerable<T> - 你也可以将它转换为数组类型,只要你先欺骗编译器:

public enum Foo : short 
{
    A, B
}

class Test
{
    static void Main()
    {
        Foo[] foo = new Foo[10];
        short[] shorts = (short[]) (object) foo;
        ushort[] ushorts = (ushort[]) (object) foo;        
    }
}

C#语言并不期望这种转​​换是可行的,但CLR很乐意这样做。 反之亦然 - 你可以从short[]转换为Foo[] 哦,如果你有另一个具有相同基础类型的枚举,你也可以投射到那个。 基本上,CLR知道所有这些类型都只是16位整数 - 所有位模式都是有效值,即使它们具有不同的含义 - 因此它允许您将一种类型视为另一种类型。 我不认为这是在CLI规范中记录的 - 无论如何我找不到任何引用。

当LINQ中的优化(在Cast<>ToList )被组合时,这可能会导致一些有趣的问题,仅用于记录。

例如:

int[] foo = new int[10];
var list = foo.Cast<uint>().ToList();

您可能希望这会产生InvalidCastException (例如,如果您使用任何值的List<int>开始),而是最终得到:

Unhandled Exception: System.ArrayTypeMismatchException: Source array type cannot be assigned to destination array type.
   at System.Array.Copy(Array sourceArray, Int32 sourceIndex, Array destinationArray, Int32 destinationIndex, Int32 length, Boolean reliable)
   at System.SZArrayHelper.CopyTo[T](T[] array, Int32 index)
   at System.Collections.Generic.List`1..ctor(IEnumerable`1 collection)
   at System.Linq.Enumerable.ToList[TSource](IEnumerable`1 source)
   at Test.Main()

这是因为Cast操作已经检查并发现int[]已经是一个uint[] ,所以它将它直接传递给ToList() ,然后ToList()尝试使用Array.Copy ,它确实注意到了差异。 哎哟!

暂无
暂无

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

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