Dan*_*Tao 32 .net c# vb.net boxing nullable
我今天早些时候发生的事情让我摸不着头脑.
Nullable<T>可以为任何类型的变量赋值null.例如:
int? i = null;
起初,我看不出如何做到这一点是可能的,而不以某种方式从定义的隐式转换object到Nullable<T>:
public static implicit operator Nullable<T>(object box);
但是上面的运算符显然不存在,就好像它确实如此,那么下面的内容也必须是合法的,至少在编译时(它不是):
int? i = new object();
然后我意识到,也许Nullable<T>类型可以定义一个隐式转换为一些永远无法实例化的任意引用类型,如下所示:
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,那么该值将被设置为a 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>因此,这种类型不会在不同语言中表现出不同的行为吗?
C#和VB.NET如何实现这种行为?它是否受到CLR的支持?(也就是说,CLR是否允许类型以某种方式"覆盖"它的装箱方式,即使C#和VB.NET本身禁止它?)
甚至可以(在C#或VB.NET中)将a封装Nullable<T>为object?
Jon*_*eet 36
有两件事情发生了:
1)编译器将"null"视为空引用,而不是空值 ...对于需要转换为的任何类型的null值.在Nullable<T>它的情况下,它只是HasValue字段/属性的值为False .因此,如果你有一个类型的变量int?,那么该变量的值很可能是null- 你只需要改变你对null一点点的理解.
2)拳击可空类型由CLR本身进行特殊处理.这与您的第二个示例相关:
    int? i = new int?();
    object x = i;
编译器会将任何可空类型值与不可空类型值区别开来.如果该值不为null,则结果将int?与装入与非可空类型值相同的值相同 - 因此值为5的方式与int使用值5的方式相同- "可空性"将丢失.但是,可空类型的空值仅被设置为空引用,而不是根本创建对象.
这是在社区的要求下在CLR v2周期的后期引入的.
这意味着没有"盒装可空值 - 值类型"这样的东西.