InvalidCastException尝试从盒装int转换为可为空的枚举

dev*_*xer 5 c# generics enums casting nullable

我有一个枚举,Foo:

public enum Foo { Alpha, Bravo, Charlie }
Run Code Online (Sandbox Code Playgroud)

如果我尝试从盒装int到下面的演员Foo?,我得到一个InvalidCastException:

var x = (Foo?)(object)1;
Run Code Online (Sandbox Code Playgroud)

这让我进行了一些实验......

var x = (Foo)(object)1; // succeeds
var x = (long)(object)1; // fails
var x = (long?)(object)1; // fails
var x = (long)1; // succeeds
var x = (long?)1; // succeeds
var x = (int)(object)1; // succeeds
var x = (int?)(object)1; // succeeds
Run Code Online (Sandbox Code Playgroud)

这告诉我的是你可以从盒装int到枚举而不是a long,你不能从盒装转换int为任何类型的可以为空的除外int?.

顺便说一句,我首先要把它int放到object第一位的原因是我真的试图从int一个泛型参数转换成一个泛型参数TValue,如下所示:

var x = (TValue)(object)1;
Run Code Online (Sandbox Code Playgroud)

如果我没有(object),它将无法编译.(有关详细信息,请参阅Eric Lippert撰写的博客文章.)

问题

  1. 为什么你可以从盒装int转换为枚举,但不能转换为可空的枚举(而不是a long或a long?)?

  2. 什么是最简单的重写方式,var x = (TValue)(object)1;以便它可以编译,在运行时工作,并且具有高性能(假设TValue确定是Foo?在运行时)?

pho*_*oog 5

要回答第一个问题,只有当盒装值是枚举的基础类型时,才能从盒装值转换为枚举值.如果你宣布

enum Foo : byte { ...
Run Code Online (Sandbox Code Playgroud)

你将无法从盒装int转换为Foo.

要回答第二个问题,请尝试

var x = (TValue)Enum.ToObject(typeof(TValue), 1);
Run Code Online (Sandbox Code Playgroud)

这涉及拳击; 如果你需要一个不会打包的解决方案,那将会更复杂.