C# 盒装可为空的基础类型可以强制转换为枚举,但盒装枚举类型可以';不能强制转换为可为null的类型 装箱的可空基础类型可以强制转换为枚举,但装箱的枚举类型不能强制转换为可空类型

C# 盒装可为空的基础类型可以强制转换为枚举,但盒装枚举类型可以';不能强制转换为可为null的类型 装箱的可空基础类型可以强制转换为枚举,但装箱的枚举类型不能强制转换为可空类型,c#,casting,enums,nullable,boxing,C#,Casting,Enums,Nullable,Boxing,同样地 装箱的可空枚举可以强制转换为基础类型,但装箱的基础类型不能强制转换为可空枚举 好的,我知道“装箱可空类型”不是描述它的最好方式,但这是为了这个问题。我知道这是被装箱的基础值类型 我将举例说明。假设我有一个enum,基础类型是int enum Sex { Male, Female } 案例一: int? i = 1; object o = i; Sex e = (Sex)o; //success //but Sex e = Sex.Male; object o = e; int?

同样地

  • 装箱的可空枚举可以强制转换为基础类型,但装箱的基础类型不能强制转换为可空枚举
好的,我知道“装箱可空类型”不是描述它的最好方式,但这是为了这个问题。我知道这是被装箱的基础值类型

我将举例说明。假设我有一个
enum
,基础类型是
int

enum Sex { Male, Female }
案例一:

int? i = 1;
object o = i;
Sex e = (Sex)o; //success

//but

Sex e = Sex.Male;
object o = e;
int? i = (int?)o; //invalid cast
案例二:

Sex? e = Sex.Male;
object o = e;
int i = (int)o; //success

//but

int i = 1;
object o = i;
Sex? e = (Sex?)o; //invalid cast
简而言之,

(enum)int? -> succeeds
(int?)enum -> the reverse fails

(int)enum? -> succeeds
(enum?)int -> the reverse fails
或者更简单地说,

强制转换为不可为空->成功
强制转换为可空->失败

现在我知道,一旦你将一个值类型放入框中,它就只能被转换回原来的类型。但是,根据C#规则,装箱的
int
可以转换为
enum
,装箱的
enum
可以转换为
int
,装箱的
int
可以转换为
int
,装箱的
int
可以转换为
int,我一直在寻找对其他场景的一致理解,就是上面列出的那些。但我不明白其中的逻辑首先,我觉得如果他们都失败了,或者都成功了,那么对开发人员来说就更有意义了2,即使是成功的演员阵容看起来也有点奇怪。我的意思是,由于一个值类型可以隐式地转换为其可为null的等价类型(而不是相反),转换为可为null的类型无论如何都应该成功,但在当前的实现中,可为null的类型被成功转换为不可为null的类型,如果前者具有null值,甚至可能失败。如果这整件事是另一回事,它会更容易理解。例如:

Sex? e = null;
object o = e;
int i = (int)o; //succeeds, but sure to explode on cast

//but

int i = 1;
object o = i;
Sex? e = (Sex?)o; //invalid cast, even though its always a safe cast
问题:

  • 那么,什么样的C#规则让这种情况发生

  • 有没有一个简单的方法让我记住这个


  • 我认为这是
    unbox
    unbox的微妙之处。任何
    IL指令

    根据ECMA 335第III.4.32节(
    unbox
    操作-
    unbox。任何
    类似)

    例外情况:
    System.InvalidCastException
    如果obj不是装箱值类型,valuetype是可为
    null的
    并且obj不是装箱的
    T
    ,或者如果obj中包含的值的类型不可由验证器分配给(III.1.8.2.3)valuetype,则抛出

    例如,在这种情况下:

    Sex e = Sex.Male;
    object o = e;
    int? i = (int?)o;
    
    它完全正确地失败-因为valuetype是
    可空的
    ,而obj的值不是装箱的
    int
    。“验证器可分配给”部分不适用于
    可为空的情况


    不幸的是,我怀疑C#规范中是否描述了这种行为——据我所知,我不认为从“boxed
    int
    ”到“底层类型为
    int
    的枚举”的拆箱行为已经被描述,这是在混合中包含可空性的一种先决条件。

    好问题。我认为这实际上是CLR级别的差异,而不是C#级别的差异。有很多东西在CLR级别是有效的,但在C级别是不允许的——比如在
    int[]
    uint[]
    之间施放。规范忍者打击!:)对不起,我来晚了。真是个好发现。虽然我不完全清楚为什么它会被设计成这样,但我还是很困惑。