如何理解C#可空值类型 - 编程语言

博主:xiaoweixiaowei 2023-01-18 条评论

如何理解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 == null) return 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);              }          }

调用和输出:

   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

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

Int32? x = 5;

Int32? y = null;

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

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

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

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

如何理解C#可空值类型 - 编程语言

注意:在操作值类型时会生成大量代码,代码类似对基类(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;");

当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>

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

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

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

关于如何理解C#可空值类型问题的解答就分享到这里了,希望以上内容可以对大家有一定的帮助,如果你还有很多疑惑没有解开,可以关注云行业资讯频道了解更多相关知识。

The End

发布于:2023-01-18,除非注明,否则均为 主机评测原创文章,转载请注明出处。