您的位置:知识库 » .NET技术

[你必须知道的.NET]第二十一回:认识全面的null

作者: Anytao  来源: 博客园  发布时间: 2008-10-13 11:05  阅读: 5848 次  推荐: 0   原文链接   [收藏]  

系列文章导航:

[你必须知道的.NET] 开篇有益

[你必须知道的.NET] 第一回:恩怨情仇:is和as

[你必须知道的.NET] 第二回:对抽象编程:接口和抽象类

[你必须知道的.NET] 第三回:历史纠葛:特性和属性

[你必须知道的.NET] 第四回:后来居上:class和struct

[你必须知道的.NET] 第五回:深入浅出关键字---把new说透

[你必须知道的.NET] 第六回:深入浅出关键字---base和this

[你必须知道的.NET] 第七回:品味类型---从通用类型系统开始

[你必须知道的.NET] 第八回:品味类型---值类型与引用类型(上)-内存有理

[你必须知道的.NET] 第九回:品味类型---值类型与引用类型(中)-规则无边

[你必须知道的.NET] 第十回:品味类型---值类型与引用类型(下)-应用征途

[你必须知道的.NET] 第十一回:参数之惑---传递的艺术(上)

[你必须知道的.NET] 第十二回:参数之惑---传递的艺术(下)

[你必须知道的.NET] 第十三回:从Hello, world开始认识IL

[你必须知道的.NET] 第十四回:认识IL代码---从开始到现在

[你必须知道的.NET] 第十五回:继承本质论

[你必须知道的.NET] 第十六回:深入浅出关键字---using全接触

[你必须知道的.NET] 第十七回:貌合神离:覆写和重载

[你必须知道的.NET] 第十八回:对象创建始末(上)

[你必须知道的.NET] 第十九回:对象创建始末(下)

[你必须知道的.NET]第二十回:学习方法论

[你必须知道的.NET]第二十一回:认识全面的null

[你必须知道的.NET]第二十二回:字符串驻留(上)---带着问题思考

[你必须知道的.NET]第三十二回,深入.NET 4.0之,Tuple一二


 

2 Nullable<T>(可空类型)

一直以来,null都是引用类型的特有产物,对值类型进行null操作将在编译器抛出错误提示,例如:

            //抛出编译时错误
            int i = null;  
            if (i == null)
            {
                Console.WriteLine("i is null.");
            }

正如示例中所示,很多情况下作为开发人员,我们更希望能够以统一的方式来处理,同时也希望能够解决实际业务需求中对于“值”也可以为“空”这一实际情况的映射。因此,自.NET 2.0以来,这一特权被新的System.Nullable<T>(即,可空值类型)的诞生而打破,解除上述诟病可以很容易以下面的方式被实现:

            //Nullable<T>解决了这一问题
            int? i = null;
            if (i == null)
            {
                Console.WriteLine("i is null.");
            }

你可能很奇怪上述示例中并没有任何Nullable的影子,实际上这是C#的一个语法糖,以下代码在本质上是完全等效的:

            int? i = null;
            Nullable<int> i = null;

显然,我们更中意以第一种简洁而优雅的方式来实现我们的代码,但是在本质上Nullable<T>T?他们是一路货色。

可空类型的伟大意义在于,通过Nullable<T>类型,.NET为值类型添加“可空性”,例如Nullable<Boolean>的值就包括了true、false和null,而Nullable<Int32>则表示值即可以为整形也可以为null。同时,可空类型实现了统一的方式来处理值类型和引用类型的“空”值问题,例如值类型也可以享有在运行时以NullReferenceException异常来处理。

另外,可空类型是内置于CLR的,所以它并非c#的独门绝技,VB.NET中同样存在相同的概念。

Nullable的本质(IL)

那么我们如何来认识Nullable的本质呢?当你声明一个:

            Nullable<Int32> count = new Nullable<Int32>();

时,到底发生了什么样的过程呢?我们首先来了解一下Nullable在.NET中的定义:

    public struct Nullable<T> where T : struct
    {
        private bool hasValue;
        internal T value;
        public Nullable(T value);
        public bool HasValue { get; }
        public T Value { get; }
        public T GetValueOrDefault();
        public T GetValueOrDefault(T defaultValue);
        public override bool Equals(object other);
        public override int GetHashCode();
        public override string ToString();
        public static implicit operator T?(T value);
        public static explicit operator T(T? value);
    }

根据上述定义可知,Nullable本质上仍是一个struct为值类型,其实例对象仍然分配在线程栈上。其中的value属性封装了具体的值类型,Nullable<T>进行初始化时,将值类型赋给value,可以从其构造函数获知:

        public Nullable(T value)
        {
            this.value = value;
            this.hasValue = true;
        }

同时Nullable<T>实现相应的Equals、ToString、GetHashCode方法,以及显式和隐式对原始值类型与可空类型的转换。因此,在本质上Nullable可以看着是预定义的struct类型,创建一个Nullable<T>类型的IL表示可以非常清晰的提供例证,例如创建一个值为int型可空类型过程,其IL可以表示为:

    .method private hidebysig static void Main() cil managed
    {
        .entrypoint
        .maxstack 2
        .locals init (
            [0] valuetype [mscorlib]System.Nullable`1<int32> a)
        L_0000: nop 
        L_0001: ldloca.s a
        L_0003: ldc.i4 0x3e8
        L_0008: call instance void [mscorlib]System.Nullable`1<int32>::.ctor(!0)
        L_000d: nop 
        L_000e: ret 
    }

对于可空类型,同样需要必要的小结:

  • 可空类型表示值为null的值类型。
  • 不允许使用嵌套的可空类型,例如Nullable<Nullable<T>> 。
  • Nullable<T>和T?是等效的。
  • 对可空类型执行GetType方法,将返回类型T,而不是Nullable<T>。
  • c#允许在可空类型上执行转换和转型,例如:
            int? a = 100;
            Int32 b = (Int32)a;
            a = null;

  • 同时为了更好的将可空类型于原有的类型系统进行兼容,CLR提供了对可空类型装箱和拆箱的支持。

0
0
标签:.NET null

.NET技术热门文章

    .NET技术最新文章

      最新新闻

        热门新闻