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

时间:2011-03-13 11:53:53

标签: c# linq casting

为什么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(); 

4 个答案:

答案 0 :(得分:14)

Cast方法只能在枚举类型及其基础整数类型之间执行装箱/拆箱转换,引用转换和转换。拆箱必须是正确的类型 - 它不能拆箱到可以为空的类型(与C#转换不同)。

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

对于每个值,Cast会从装箱的enum值中取消装箱到int值,然后Select会转换int值到int?值。

在这种情况下,你也可以逃脱:

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

即。没有Cast步骤。但是,如果你有一个object数组,则不会工作:

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

您无法将装箱的枚举值取消装入可以为空的int值。 Cast版本在这种情况下仍然适用,因为它会拆分两个步骤(首先取消装箱到int,然后从int转换为int?。)

答案 1 :(得分:3)

这是因为内部Cast()做了类似的事情:

object o = Test.A;

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

你必须先Cast()到一个int:

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

或根本不使用Cast()

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

答案 2 :(得分:0)

它不起作用,因为我们需要了解什么是枚举和什么是int? (可以为空)

int?实际上并不是一个int它是Nullable的通用实例, - 语法T?是System.Nullable的简写,其中T是值类型。这两种形式是可以互换的。 Link

枚举枚举元素的默认基础类型为int。Link

因此存在int和enum之间的隐式转换。但是,enum(int)与Nullable(完全不同的引用类型)之间的隐式转换不存在。这就是你看到InvalidCastException异常的原因。

在第一个int? x = (int?)Test.A;语句中,您强制显式转换为包装值类型并获取整数或获取空值,这是有效的,因为将枚举装入object然后取消装箱它为int?返回一个int。

答案 3 :(得分:-1)

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

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