简介C#可空值类型

开发 后端
本文介绍了C#可空值类型,并且总结了C#可空值类型对操作符的解释,希望对大家有所帮助。

通常一个值类型变量永远不可能为null,它总是包含值类型的值本身。但是在某些情况下会遇到一些问题如:在映射数据库中的一个C#可空值列时,使用Framework来处理数据库数据时变得相当困难;为了解决这一问题CLR中引入了“C#可空值类型(nullable value type)”

为理解它们是如何工作的,先看看CLR中的逻辑:

[Serializable, StructLayout(LayoutKind.Sequential)]     
 public struct Nullable< T> where T : struct    
 {     
     private Boolean hasValue = false// 用一个字段落表示装态,初始假定为Null     
     internal T value = default(T);     
     public Nullable(T value)     
     {     
         this.value = value;     
         this.hasValue = true;     
     }     
    
     public bool HasValue { get { return hasValue; } }     
     public T Value     
     {     
         get    
         {     
             if (!hasValue) throw new InvalidOperationException("Nullable object must have a value.");     
             return value;     
         }     
     }     
    
     public T GetValueOrDefault() { return value; }     
     public T GetValueOrDefault(T defaultValue)     
     {     
         if (!HasValue) return defaultValue;     
         return value;     
     }     
     public override bool Equals(object obj)     
     {     
         if (!HasValue) return (obj == null);     
         if (obj == nullreturn false;     
         return value.Equals(obj);     
     }     
    
     public override int GetHashCode()     
     {     
         if (!HasValue) return 0;     
         return value.GetHashCode();     
     }     
     public override string ToString()     
     {     
         if (!HasValue) return String.Empty;     
         return value.ToString();     
     }     
    
     public static implicit operator Nullable< T>(T value)     
     {     
         return new Nullable< T>(value);     
    
     }     
    
 }   
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.
  • 28.
  • 29.
  • 30.
  • 31.
  • 32.
  • 33.
  • 34.
  • 35.
  • 36.
  • 37.
  • 38.
  • 39.
  • 40.
  • 41.
  • 42.
  • 43.
  • 44.
  • 45.
  • 46.
  • 47.
  • 48.
  • 49.
  • 50.
  • 51.
  • 52.

调用和输出: 

   static void Main(string[] args)     
        {     
            Nullable< Int32> x = 5;     
            Nullable< Int32> y = null;     
            Console.WriteLine("x:HasValue {0}, value = {1}", x.HasValue, x.Value);     
            Console.WriteLine("y:HasValue {0}, value = {1}", y.HasValue, y.GetValueOrDefault());     
            Console.ReadLine();     
        }     
输出:     
    x:HasValue  True, value = 5     
    y:HasValue False, value = 0    
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.

C#中允许使用问号来申明初始化变量(等同于上面代码)如:

        Int32? x = 5;

        Int32? y = null;

总结一下C#可空值类型对操作符的解释:

a.一元操作符如果操作数为null,结果为null;

b.二元操作符中任何一个为null,结果为null;

c.比较操作符如果两人个操作数都为null,两者相等;如果一个为null,两者不相等;如果两个数都不为null,对值进行比较;

注意:在操作值类型时会生成大量代码,代码类似对基类(Nullable)代码的调用;

//一元操作符:(+ ++ - -- ! ~)     
x++; // x = 6;     
y--; // y = null;     
//二元操作符:(+ - * / % & | ^ < <  >>)     
x = x + 10; // x = 15;     
y = y * 10; // y = null     
// 比较操作符:(== != <  > < = >=)     
if (x == null) Console.WriteLine("x is null;"); else Console.WriteLine("x is not null;");     
if (y == null) Console.WriteLine("y is null;"); else Console.WriteLine("y is not null;");     
if (x != y) Console.WriteLine("x = y;"); else Console.WriteLine("x != y;");     
if (x > y) Console.WriteLine("x > y;"); else Console.WriteLine("x < = y;");    
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.

当CLR对一个Nullable< T>实例进行装箱时,会检查它是否为null,如果为null,CLR不实际进行装箱操作,并会返回null值;

如果实例不为空,将从类型中取出值,并对其进行装箱如:

Int32? a = null;     
            object o = a; //a 为null     
            Console.WriteLine(" o is null = {0}", o == null); // "true"     
    
            Int32? b = 5;     
            o = b; //a 为null     
            Console.WriteLine(" o's type = {0}", o.GetType()); // "System.Int32" 对可空值类型调用GetType时CLR会采取欺骗手法返回T,而不是Nullable< T>   
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.

在应用可空值类型进行拆箱时,CLR会分配内存(这是一个极特殊的行为,在其它所有情况下,拆箱永远不会导致内存的分配),原因在于一个已装箱的值类型不能简单的拆箱为值类型的可空版本,在已装箱的值类型中并不包含Boolean hasValue字段,故在拆箱时CLR必须分配一个Nullable< T>对象,已初始化hasValue = true ,value = 值类型值。这会对应用程序性能造成一定影响。

通过C#可空值类型调用接口方法

Int32? n = 5;     
        Int32 result = ((IComparable)n).CompareTo(5);     
        Console.WriteLine(result); // 0;   
  • 1.
  • 2.
  • 3.

【编辑推荐】

  1. 总结C#哈希表的用法
  2. 不一样的入门:看C# Hello World的17种写法
  3. 什么是WMI?及其示例
  4. 从C#到C++容易出现的问题解答
  5. 浅议.NET、ASP.NET和C#的关系
责任编辑:book05 来源: csdn
相关推荐

2009-08-31 14:34:46

C#值类型C#结构类型

2009-08-26 14:05:19

C#值类型和引用类型

2009-08-19 16:39:44

C#值类型C#引用类型

2009-08-20 09:52:31

C#参数类型

2009-08-03 14:54:23

值类型C#

2009-09-02 17:10:45

C#语言入门

2011-06-08 13:03:52

C#值类型引用类型

2013-05-23 17:21:16

C#

2009-08-25 17:07:27

C#虚拟方法

2009-08-31 15:13:46

C# CWorker类

2009-08-26 17:05:23

C# ThreadPo

2009-10-22 18:41:49

CLR VIA C#教

2009-08-10 17:25:58

C#匿名类型

2009-08-25 17:49:07

C#入门

2009-08-20 14:28:00

C#静态构造函数

2009-08-26 10:34:15

C#类型C#变量

2009-08-14 17:09:48

C#引用类型

2009-08-26 15:46:01

C#匿名类型

2009-08-06 15:30:23

C#类型系统

2009-08-12 14:49:33

C#移位运算符
点赞
收藏

51CTO技术栈公众号