今天早些时候发生的一件事让我摸不着头脑。
Nullable<T>
类型的任何变量可以分配给null
.例如:
int? i = null;
起初我看不出如果不以某种方式定义从 object
的隐式转换,这怎么可能至 Nullable<T>
:
public static implicit operator Nullable<T>(object box);
但是上面的运算符显然不存在,就好像它存在那么下面的运算符也必须是合法的,至少在编译时(它不是):
int? i = new object();
然后我意识到也许 Nullable<T>
type 可以定义到一些永远无法实例化的任意引用类型的隐式转换,如下所示:
public abstract class DummyBox
{
private DummyBox()
{ }
}
public struct Nullable<T> where T : struct
{
public static implicit operator Nullable<T>(DummyBox box)
{
if (box == null)
{
return new Nullable<T>();
}
// This should never be possible, as a DummyBox cannot be instantiated.
throw new InvalidCastException();
}
}
但是,这并不能解释我接下来发生的事情:如果 HasValue
属性是 false
对于任何 Nullable<T>
值,则该值将装箱为 null
:
int? i = new int?();
object x = i; // Now x is null.
此外,如果HasValue
是true
, 然后 该值将装箱为 T
而不是 T?
:
int? i = 5;
object x = i; // Now x is a boxed int, NOT a boxed Nullable<int>.
但是这似乎暗示有一个来自Nullable<T>
的自定义隐式转换。至 object
:
public static implicit operator object(Nullable<T> value);
这显然不是object
的情况。是所有类型的基类,用户定义的与基类型之间的隐式转换是非法的(它们也应该是非法的)。
似乎object x = i;
应该框i
像任何其他值类型一样,所以 x.GetType()
会产生与 typeof(int?)
相同的结果(而不是抛出 NullReferenceException
)。
所以我仔细研究了一下,果然,这种行为是特定于 Nullable<T>
的类型,在 C# 和 VB.NET 规范中专门定义,并且在任何用户定义中不可重现 struct
(C#) 或 Structure
(VB.NET)。
这就是为什么我仍然感到困惑。
这种特殊的装箱和拆箱行为似乎无法手动实现。它之所以有效,是因为 C# 和 VB.NET 都对 Nullable<T>
进行了特殊处理。类型。
在
Nullable<T>
的地方,理论上是否可能存在一种不同的基于 CLI 的语言?没有得到这种特殊待遇?而且不会Nullable<T>
type 因此在不同的语言中表现出不同的行为?C# 和 VB.NET 如何实现这种行为? CLR 支持吗? (也就是说,CLR 是否允许类型以某种方式“覆盖”它的装箱方式,即使 C# 和 VB.NET 本身禁止它?)
可能(在 C# 或 VB.NET 中)将
Nullable<T>
装箱吗?作为object
?
最佳答案
有两件事正在发生:
1) 编译器不将“null”视为空引用,而是将其视为空值...它需要转换成的任何类型的空值。在 Nullable<T>
的情况下这只是 HasValue
的 False 值领域/属性(property)。所以如果你有一个 int?
类型的变量, 该变量的值很可能是 null
- 你只需要改变你对什么的理解null
有点意思。
2) 装箱可为空的类型得到 CLR 本身的特殊处理。这与您的第二个示例相关:
int? i = new int?();
object x = i;
编译器会将任何可空类型值与非可空类型值不同地装箱。如果该值不为空,则结果将与将相同值装箱为不可空类型值相同 - 所以 int?
值为 5 的装箱方式与 int
相同值为 5 - “可空性”丢失。但是,可空类型的空值仅装箱为空引用,而不是创建一个对象。
应社区的要求,这是在 CLR v2 周期的后期引入的。
这意味着没有“装箱的可空值类型值”这样的东西。
关于c# - Nullable<T> 的装箱/拆箱行为如何可能?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3775582/