CLR via C# 读书笔记 可空值类型

可空值类型

一个值类型的变量永远不可能为null;它总是包含值类型的值本身。某些情况下会成为问题。如:数据库中的一个列可能允许值为空 ,为了与数据库中的列相对应,CLR引入了可空值类型 。

可空值类型FCL中的定义

[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 Boolean 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 Boolean Equals(object other)
{
if(!HasValue) return (other == null);
if(other == null) return false;
return value.Equals(other);
}

public override int GetHashCode()
{
if(!HasValue) return 0;
return value.GetHashCode();
}

public override string ToString()
{
if(!HasValue) return "";
return value.ToString();
}

public static implicit operator Nullable<T>(T value)
{
return new Nullable<T>(value);
}
}

在代码中使用可空类型

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());

C#对可空值类型的支持

    1. ?表示法声明初始化变量
      c#提供了一个更清晰的语法来处理可空值类型。c#允许用问号表示法来声明并初始化变量。
      Int32? a = 5;
      Int32? b = null;
      Int32?等价于Nullable<Int32>
    2. 可空类型与操作符
      一元操作符(++,+,-,--,!,~)操作数是Null,结果就是Null。
      二元操作符(+,-,*,/,%,&,|,^,<<,>>) 两个操作数中任何一个是null,结果就是null。& ,| 操作符应用于Boolean?操作数的时候。




      相等性操作符(==,!=) 两个操作数都是null ,两者相等,一个操作数为null,两者不相等,两个操作数都不为null,比较值来判断是否相等.

      关系操作符(<,>,<=,>=) 两个操作数任何一个是null ,结果就是false。两个操作数都不是null 就比较值。

    3. 可空实例上执行转换和转型
      Int32? a = 5;//从非可空的 Int32 转换为Nullable<Int32>
      
      Int32? b = null;//从null隐式转换为Nullable<Int32>
      
      Int32 c = (Int32)a;//从Nullable<Int32>强制转换为非可空的Int32
      
      //在可空基元类型之间转型 
      Double? d = 5;//Int32 转型为Double?
      
      Double? e = b;//Int32? 转型为Double?

??空接合操作符

c#提供了一个所谓的“空接和操作符”,即??操作符,它要获取两个操作数,如果左边的操作数不为null,返回值为左边操作数的值。如果左边的操作数为 null,返回右边的操作数的值

Int32? b = null;
int? c = 1;
int a = 32;
Console.WriteLine(b ?? a);//返回32
Console.WriteLine(c ?? a);//返回1 

可空值类型的装箱

值类型转换为引用类型需要装箱。当CLR对一个Nullable<T>实例进行装箱时,先做null判断,如果是,CLR不进行装箱,直接返回null,如果实例不为null ,则同对待普通的值类型一样进行装箱过程

可空值类型的拆箱

CLR允许将一个已装箱的值类型T拆箱为一个T或者一个Nullabe<T>。如果对已装箱值类型的引用为null,CLR会将Nullabe<T>的值设为null。

可空值类型调用GetType
调用Nullable<T>类型的实例的GetType时,返回的类型是T,而不是Nullable<T>

Int32? a = 5;

Console.WriteLine(a.GetType());//返回System.Int32 不是 System.Nullable<Int32>

 

原文地址:https://www.cnblogs.com/whx1973/p/2594904.html