1
可空值类型

引用类型的变量可以为空,值类型的变量则不被允许赋值为null,而可空值类型便是可以赋值为null的值类型。

可空值类型的声明与初始化
int? x = null;
int? y = 1;
类型之间的转换
  • int转int?总是会成功
int? a = 5;     //正确
  • int?转int需要显示转换
int c = a;      //错误,无法从int?隐式转换为int
int c = (int)a; //正确
  • 可空基元类型之间的转型
int? b = null;
//d=5
double? d = 5;
//e=null
double? e = b;
C#对可空值类型应用操作符规则
  • 一元操作符(++,+,-,--,!,~):操作数是null,结果就是null
int? a = null;
Console.WriteLine(a++);     //null
Console.WriteLine(a + 10);  //null
  • 二元操作符(+,-,*,/,%,&,|,^,<<,>>):两个操作数其中一个为null,结果就为null。特例:&,|和Boolean?类型的操作数时,情况如下
bool? a = null;
bool? b = true;
Console.WriteLine(a & b);   //结果为null
Console.WriteLine(a | b);   //结果为true

bool? c = false;
Console.WriteLine(a & c);   //结果为false
Console.WriteLine(a | c);   //结果为null
  • 相等性操作符(==,!=):两个操作数皆为null,两者相等;一个为null,一个不为null,则不等;皆不为null,则比较数值是否相等。
int? a = null;
int? b = null;
int? c = 10;
Console.WriteLine(a == b);  //true
Console.WriteLine(a == c);  //false
  • 关系操作符(<,>,<=,>=):两个操作数任意一个为null,返回false。两个操作数都不是null,就比较值返回结果。
int? a = null;
int? b = null;
int? c = 10;
Console.WriteLine(a > b);   //false
Console.WriteLine(a > c);   //false
空接合操作符(??)

??:获取两个操作数,如果左边的操作数不为null,则返回左边操作数的值,反之返回右边操作数的值。

int? a = null;
//等价于int b = z.HasValue ? z.Value :123
int b = a ?? 123;
Console.WriteLine(b); //结果为123

int? c = 3;
Console.WriteLine(c ?? 123); //结果为3
可空值类型的装箱与拆箱
  • 装箱:CLR对可空值类型装箱时,如果实例为null,不装箱任何东西,并返回null,否则(以int?为例)则会装箱一个Int32的值
int? a = null;
object o = a;
Console.WriteLine(o == null); //true

a = 1;
o = a;
Console.WriteLine(o); //结果为1
Console.WriteLine(o.GetType()); //输出System.Int32
  • 拆箱:如果已装箱值类型的引用是null,将其拆箱成一个可空值类型(T?),CLR会直接将T?的值设为null
object o = null;
//a=null
int? a = (int?)o;
Console.WriteLine(a == null); //输出true
//引发System.NullReferenceException异常
int b = (int)o;
可重载自定义值类型的操作符方法,从而让编译器正确对待它
struct Position
{
    private int m_X, m_Y;
    public Position(int x, int y)
    {
        this.m_X = x;
        this.m_Y = y;
    }

    public static bool operator ==(Position pos1, Position pos2)
    {
        return (pos1.m_X == pos2.m_X) && (pos1.m_Y == pos2.m_Y);
    }

    public static bool operator !=(Position pos1, Position pos2)
    {
        return (pos1.m_X != pos2.m_X) || (pos1.m_Y != pos2.m_Y);
    }
}

static void Main(string[] args)
{
    Position? pos1 = new Position(1, 2);
    Position? pos2 = new Position(3, 4);
    Position? pos3 = new Position(3, 4);
    Console.WriteLine(pos1 == pos2); //false
    Console.WriteLine(pos1 != pos2); //true
    Console.WriteLine(pos2 == pos3); //true
}

DoubleJ
7 声望3 粉丝

« 上一篇
Attribute
下一篇 »
命名空间