zoukankan      html  css  js  c++  java
  • 可空类型

    可空类型这个优美的特性是在C#2.0里面提出来的。

    1、可空类型

    当我们在使用数据库的时候,会发现这样的一个矛盾点:数据库的字段设置是允许为null的,比如日期的字段,当你想把数据库表映射为C#中的对象时会发现,DateTime类型在C#语言中是不能为null的!

       1.1 简介

             可空类型也是值类型,但它是包含null值的值类型:int? nullable=null;

             int?就是可空的int类型。很明显,这又是一个语法糖,肯定不会存在int?这样的类型。对于编译器而言,int?会被编译成Nullable<int>类型,即可空类型。

             C#2.0中提供的可空类型是Nullable<T>和Nullable(这个T就是一个泛型参数)。在C#中,定义是这样的public struct Nullable<T> where T:struct ,很明显,泛型只能是值类型。下面的代码演示了可空类型的使用方法:

              

     1 static void Main(string[] args)
     2 
     3 {
     4 Nullable<int> value = 1;//int? value=1也可以
     5 Console.WriteLine("可空类型有值的输出情况:");
     6 Display(value);
     7 Console.WriteLine();
     8 
     9 value = new Nullable<int>();
    10 Console.WriteLine("可空类型没有值的输出情况:");
    11 Display(value);
    12 Console.ReadKey();
    13 
    14 }
    15 
    16 private static void Display(int? value)
    17 {
    18 Console.WriteLine("可空类型是否有值:{0}",value.HasValue);
    19 if (value.HasValue)
    20 {
    21 Console.WriteLine("值为:{0}",value.Value);
    22 }
    23 //如果可空类型有值,则返回Value属性的值,否则就返回默认值
    24 Console.WriteLine("GetValueorDefault():{0}",value.GetValueOrDefault());
    25 //如果可空类型有值,则返回Value属性的值,否则就返回2
    26 Console.WriteLine("GetValueorDefault():{0}", value.GetValueOrDefault(2));
    27 //如果HasValue属性为true,则Value属性返回对象的哈希代码,否则为0
    28 Console.WriteLine("GetHashCode()方法的使用:{0}",value.GetHashCode());
    29 }

        1.2 空合并操作符

              即为??操作符,它会对左右两个操作数进行判断,如果左边的数不为null,就返回左边的数;如果左边的数为null,就返回右边的数。这个操作符可用于可空类型,也可以用于引用类型,但是不能用于值类型。例如:

    1 string stringnotnull="123"
    2 string stringisnull=null;
    3 string result=stringnotnull ?? "456";
    4 string result=stringisnull ?? "12";

    以上的代码运行结果为:result=“123”;result2=“12”。

        1.3 可空类型的装箱与拆箱操作

              既然值类型存在着装箱和拆箱的过程,而可空类型属于值类型,那么它自然也就存在装箱和拆箱操作,下面我们就来看看可空类型的装箱和拆箱的过程。

              当把一个可空类型赋给引用类型变量时,CLR会对可空类型(Nullable<T>)对象进行装箱处理。CLR首先检测可空类型是否为null。如果有null,CLR将不会进行实际的装箱操作(因为null可以直接赋值给一个引用类型变量);如果不为null,CLR则从可空类型对象中获取值,并对该值进行装箱(即值类型的装箱过程)。

              当把一个已装箱的值类型赋值给可空类型变量时,CLR会对已装箱的值类型进行拆箱处理。如果已装箱值类型的引用为null,则CLR会把可空类型也设为null。

              

     1 static void Main(string[] args)
     2         {
     3             Console.WriteLine("可空类型的装箱和拆箱的使用如下:");
     4             BoxAndUnbox();
     5             Console.ReadKey();
     6         }
     7 
     8         private static void BoxAndUnbox()
     9         {
    10             Nullable<int> nullable = 5;
    11             int? nullablewithoutvalue = null;
    12             Console.WriteLine("读取不为null的可空类型的类型为{0}",nullable.GetType());
    13             //出现NullReferenceException的异常
    14             //Console.WriteLine("读取为null的可空类型的类型为{0}", nullablewithoutvalue.GetType());
    15             object obj = nullable;
    16             Console.WriteLine("获得装箱后obj的类型:{0}",obj.GetType());
    17 
    18             int value = (int) obj;
    19             nullable = (int?) obj;
    20 
    21             //对一个没有值的可空类型的对象进行装箱操作
    22             obj = nullablewithoutvalue;
    23             Console.WriteLine("对null的可空类型装箱后obj是否为null:{0}",obj==null);
    24 
    25             //拆箱一定要为可空类型
    26             nullable = (int?) obj;
    27         }

    运行的结果如下:

    由以上的结果可以得知:

    (1)通过GetType方法来获得赋值的可空类型时,返回的将是赋值的类型,在前面的的代码中即是System.Int32,而不是System.Nullable<System.Int32>类型。

    (2)对已赋值的可空类型装箱后,如果使用GetType函数去获得装箱后的引用类型,输出的将仍然是赋值的类型,在前面的代码中即为System.Int32。

    (3)如果把一个没有值的可空类型装箱之后再拆箱,不能拆箱为非可空类型的值类型,否则会抛出NullReferenceException异常。因为没有值的可空类型装箱后obj等于null,即引用一个空地址,如果拆箱为非可空类型的值类型,相当于把null赋值给一个int型的变量,而int类型属性值类型,不能被赋值为null,因此会出现异常。

    (4)还有一点必须要注意:没有值的可空类型在调用GetType函数之前,编译器会对可空类型进行装箱操作,使其变为null,即空引用。所以之后再调用GetType函数时,就会抛出空引用异常了。

  • 相关阅读:
    极大/小搜索,alpha/beta剪枝
    消息系统
    渲染主线程都在干什么
    好玩的虚拟CPU执行代码
    好玩的隐藏属性
    好玩的对象存储
    透视投影矩阵
    绕任意轴旋转
    视图变换
    正交投影矩阵
  • 原文地址:https://www.cnblogs.com/Helius/p/5747399.html
Copyright © 2011-2022 走看看