C# 为什么是<;enum>;无法强制转换为<;int?>;?

C# 为什么是<;enum>;无法强制转换为<;int?>;?,c#,linq,casting,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

为什么
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(); 
enum测试{A=1,B=2};
智力?x=(int?)Test.A;//有效的
var collection1=new[]{Test.A}.Cast().ToList();
//已引发InvalidCastException(指定的强制转换无效。)
var collection2=new[]{Test.A}.Cast().ToList();

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

i、 e.无
Cast
步骤。但是,如果您有一个
对象
数组,则这不起作用:

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

无法将装箱的枚举值取消装箱为可为空的int值。不过,在这种情况下,
Cast
版本仍然可以工作,因为它将两个步骤分开(首先取消装箱到
int
,然后从
int
转换到
int?

我不知道为什么
Cast()
不起作用,但您可以使用
Select()
来做您想做的事情

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

这是因为内部
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();

这是行不通的,因为我们需要了解什么是enum,什么是int?(可为空int)

int?不是真正的int,而是Nullable的一般实例,-语法T?是System.Nullable的缩写,其中T是值类型。这两种形式可以互换

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

因此,int和enum之间存在隐式转换。但是枚举(int)到null(这是完全不同的引用类型)之间的隐式转换并不存在。这就是为什么您会看到InvalidCastException异常


在第一个
int中的哪个位置?x=(int?)测试A语句您正在强制显式转换,以装箱值类型并获取整数或获取空值,这是有效的,因为将枚举装箱到
对象中,然后将其作为
int?
解除装箱将返回一个int。

。我不记得曾经以这种方式使用linq进行过铸造,我只使用已知类型
:/
。。。我想
{Test.A}.Select(x=>(int?.x)。ToList()
也应该可以工作?@Kobi:查看我的最新编辑-我已经浏览了几个版本:)也可以通过在Select:
Select(x=>(int?)x
中强制转换两次值来避免
Cast()
。但是,如果集合仅实现非泛型IEnumerable,则需要使用
Cast()。这就是我3分钟前修复它的原因。@Jaroslav:你知道为什么
Cast().Cast()
不起作用吗?@Homam:在内部,
Cast()
在将对象强制转换为目标类型之前,会将值装箱到对象,而不能将装箱枚举直接强制转换为
Nullable
类型。它在内部工作,就像Jaroslav所展示的那样。
Test的
Cast()
(int?)(对象)测试相同。A
总是会失败。但有趣的是,
Cast().Cast()
不起作用,因为
Cast().Select(x=>x)。Cast()
工作正常。@mgronber:
Cast()
如果枚举数的类型已经正确,则不会包装它
Cast()
对枚举器实例没有影响。在本例中,它与IEnumerable的
new[]{Test.A}相同<因此,code>arr.Cast().Cast
arr.Cast()
相同,因为
IEnumerator.MoveNext()
首先将值强制转换为
对象
object o = Test.A;

int i = (int)o; // This is valid.
int? ni = (int?)o; // This is not valid!
var collection3 = new[] { Test.A }.Cast<int>().ToList().Cast<int?>().ToList();
var collection4 = new object[] { Test.A, null }.Select(i => i == null ? null : (int?)(int)i).ToList();