简体   繁体   English

为什么<enum>的集合无法转换为<int?>?

[英]Why is a collection of <enum> unable to cast to an <int?>?

Why is a collection of enum unable to cast to an int? 为什么enum的集合无法转换为int?

enum Test { A = 1, B = 2 };

int? x = (int?)Test.A; // Valid

var collection1 = new[] { Test.A }.Cast<int>().ToList();

// InvalidCastException has thrown (Specified cast is not valid.)    
var collection2 = new[] { Test.A }.Cast<int?>().ToList(); 

The Cast method can only perform boxing/unboxing conversions, reference conversions, and conversions between an enum type and its underlying integral type. Cast方法只能在枚举类型及其基础整数类型之间执行装箱/拆箱转换,引用转换和转换。 The unboxing has to be to the right type though - it can't unbox to a nullable type (unlike the C# conversion). 取消装箱必须是正确的类型 - 它不能取消装入可以为空的类型(与C#转换不同)。

var collection1 = new[] { Test.A }.Cast<int>()
                                  .Select(x => (int?) x)
                                  .ToList();

For each value, the Cast will unbox from the boxed enum value to the int value, and then the Select will convert the int value to an int? 对于每个值, Cast会从盒装enum值中取消框到int值,然后Select会将int值转换为int? value. 值。

In this case you can also get away with this: 在这种情况下,你可以逃避:

var collection1 = new[] { Test.A }.Select(x => (int?) x)
                                  .ToList();

ie no Cast step. 即没有Cast步骤。 However, that doesn't work if you have an object array instead: 但是,如果您有一个object数组, 不起作用:

// Fails
var collection1 = new object[] { Test.A }.Select(x => (int?) x)
                                         .ToList();

You can't unbox a boxed enum value to a nullable int value. 您不能将装箱的枚举值取消装入可以为空的int值。 The Cast version still works in that case, however, as it splits the two steps (unboxing first to int , then converting from int to int? .) 然而,在这种情况下, Cast版本仍然适用,因为它拆分了两个步骤(首先拆箱为int ,然后从int转换为int?

It is because internally Cast() does something like: 这是因为内部的Cast()做了类似的事情:

object o = Test.A;

int i = (int)o; // This is valid.
int? ni = (int?)o; // This is not valid!

You would have to first Cast() to an int: 你必须首先将Cast()转换为int:

var collection3 = new[] { Test.A }.Cast<int>().ToList().Cast<int?>().ToList();

or not use Cast() at all: 或者根本不使用Cast()

var collection4 = new object[] { Test.A, null }.Select(i => i == null ? null : (int?)(int)i).ToList();

It wouldn't work because we need to understand what is enum and what is int? 它不起作用,因为我们需要了解什么是枚举和什么是int? (nullable int) (可以为空)

int? 诠释? is not really an int it is a generic instance of Nullable, - The syntax T? 是不是真的是一个int它是Nullable的通用实例, - 语法T? is shorthand for System.Nullable, where T is a value type. 是System.Nullable的简写,其中T是值类型。 The two forms are interchangeable. 这两种形式是可以互换的。 Link 链接

Enum The default underlying type of the enumeration elements is int. 枚举枚举元素的默认基础类型是int。 Link 链接

Therefore an implicit conversion between int and enum exists. 因此,存在int和enum之间的隐式转换。 But implicit conversion between an enum(int) to Nullable (which is entirely different reference type) doesnt exist. 但是,enum(int)与Nullable(完全不同的引用类型)之间的隐式转换不存在。 That is why you see an InvalidCastException exception. 这就是您看到InvalidCastException异常的原因。

Where as in the first int? x = (int?)Test.A; 在第一个int? x = (int?)Test.A; int? x = (int?)Test.A; statement you are forcing the explicit conversion to either box the value type and get an integer or get a null, which is works because boxing an enum into object then unboxing it as int? 声明你强制显式转换为框的值类型并获得一个整数或获得一个null,这是有效的,因为将枚举装入object然后将其拆箱为int? is returning an int. 正在返回一个int。

我不知道为什么Cast<>()不起作用,但你可以使用Select()来做你想要的。

var collection = new[] { Test.A }.Select(item => (int?)item).ToList();

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

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