为什么拆箱枚举会产生奇怪的结果?
考虑以下几点::
Object box = 5;
int @int = (int)box; // int = 5
int? nullableInt = box as int?; // nullableInt = 5;
StringComparison @enum = (StringComparison)box; // enum = OrdinalIgnoreCase
StringComparison? nullableEnum = box as StringComparison?; // nullableEnum = null.
2 件事::
- 为什么我可以取消装箱到
StringComparison
?我想这是因为它的基础类型是 Int32 但我仍然觉得很奇怪。 - 为什么
nullableEnum
的值为 null?
据我了解,唯一有效的拆箱是从装箱值类型到它的类型或可为空类型。如果 int
可以取消装箱为 Enum
,那么为什么对于可为 null 的值则不成立呢?同样,如果我装箱的不是 5,而是 StringComparison.OrdinalIgnoreCase
,则 nullableInt
将为 null,但 nullableEnum
不会。
Consider the following::
Object box = 5;
int @int = (int)box; // int = 5
int? nullableInt = box as int?; // nullableInt = 5;
StringComparison @enum = (StringComparison)box; // enum = OrdinalIgnoreCase
StringComparison? nullableEnum = box as StringComparison?; // nullableEnum = null.
2 things::
- Why can I unbox to
StringComparison
? I guess this is because it's underlying type isInt32
but I still find it odd. - Why does
nullableEnum
have a value of null?
As I understand the only valid unboxing is from a boxed value type is to it's type or to a nullable type. If int
can unbox to Enum
, then why doesn't the same hold true for the nullable values? Similarly, if Instead of 5 I boxed StringComparison.OrdinalIgnoreCase
, it would be that nullableInt
would be null, but nullableEnum
would not be.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
严格来说,我认为这是运行时的
错误实现细节,因为 C# 规范说也就是说,如果拆箱到 StringComparison 有效,则拆箱到 Nullable有效。也应该有效。目前尚不清楚两者是否都应该有效或者都应该失败。规范说
您必须确定装箱 int 是否被视为 StringComparison 类型的装箱值,因为 StringComparison 的基础类型是 int。规范还指出,如果盒子包含“不兼容的对象”,则会抛出 InvalidCastException。 int 当然与 StringComparison “兼容”,因为您可以安全地将四个字节从堆复制到 StringComparison 变量中。
Strictly speaking I think it's a
bug inimplementation detail of the runtime, since the C# spec saysThat is, if unboxing to StringComparison works, then unboxing to Nullable<StringComparison> should work too. It's a little unclear whether both should work or both should fail. The spec says that
You have to decide whether a boxed int is a considered to be a boxed value of type StringComparison because the underlying type of StringComparison is int. The spec goes on to say that an InvalidCastException is thrown if the box contains an "incompatible object". An int is certainly "compatible" with StringComparison, because you can safely copy the four bytes from the heap into your StringComparison variable.
当您将枚举或整数转换为对象时,它仍然保留类型信息。因此
box is StringComparison
将返回false
。但允许将任何 enum 或 int 转换为任何 enum,因此显式转换(StringComparison)box
有效。这是枚举的特例。另一方面,Nullable
只是一个普通的类,当您强制转换或检查类型时,T 不会以任何特定方式处理。这就是为什么这段代码会抛出异常。When you cast enum or integer to object, it still holds type information. So
box is StringComparison
will returnfalse
. But it is allowed to cast any enum or int to any enum, so explicit cast(StringComparison)box
works. It is a special case for enums.Nullable<T>
, on the other hand, is just a usual class, T is not handled in any specific way when you cast or check type. This is why this code will throw exception.1)是的,枚举的基础类型是 int,这就是它以这种方式工作的原因。更。您可以执行以下操作:
2) 因为
StringComparison?
实际上是Nullable
这是不同的类型。而as
运算符仅检查对象是否与 as 运算符中指定的类型相同。1) Yes, underlying type of enum is int and that's why it works in this way. Even more. You can do following:
2) Because
StringComparison?
is actuallyNullable<StringComparison>
which is different type. Andas
operator only checks if the object is of the same type as specified in as operator.