C# 中的、 、.、[]、、=和as
(?) 可空类型
通常来说,编程语言中一般对于数据的引用类型分为值类型和引用类型。例如bool、int等为值类型,而类一般为引用类型。值类型即存储的是数值,引用存储的是对数值地址的引用。从而引用类型可以为空(null),值类型不可为空,使用前未初始化则会出现警告或被默认初始化为该类型的默认值。
(?)符号的作用即修饰值类型,使其可空(可为null)。
举个例子:
1 | |
对应的类型:
1 | |
可以看出来int类型即.Net类型中的System.Int32,而int?则是由Nullable类型对int的封装,使其可空,查阅MSDN文档对Nullable的说明如下
注解
如果可以为类型赋值或将其分配到null,则称该类型为 null,这意味着该类型没有任何值。 默认情况下,所有引用类型(如 String)都可以为 null,但所有值类型(如 Int32)都不是。
在 C# 和 Visual Basic 中,通过在值类型后使用?表示法,将值类型标记为可以为 null。 例如,在 Visual Basic 中 C#int?或Integer?声明可以null分配的整数值类型。
Nullable 类提供 Nullable 结构的互补支持。 Nullable 类支持获取可以为 null 的类型的基础类型,以及针对其基础值类型不支持泛型比较和相等运算的可以为 null 的类型对的比较和相等性运算。
装箱和取消装箱
当对可以为 null 的类型进行装箱时,公共语言运行时将自动框 Nullable 对象的基础值,而不是 Nullable 对象本身。 也就是说,如果 HasValue 属性为true,则 Value 属性的内容为装箱。 如果HasValue属性为false,则null为装箱。 如果可以为 null 的类型的基础值为取消装箱,则公共语言运行时将创建一个新的 Nullable 结构,该结构已初始化为基础值。
(?:) 三目运算符
这个其实不需要怎么解释,也不是c#特有的语法,就是常用的三目运算符。
1 | |
条件 ? 返回值1 : 返回值2,这是三目运算符的基本格式,问号前面也就是三目运算的条件,如果该条件为真(true)返回(返回值1),否则返回(返回值2)。和大部分编程语言相同,需要注意一个三目运算符的两个返回值的类型都必须相同,也就是返回值1和2的类型必须一致。因为在编译期就已经决定好该运算的返回值类型,如果不同,则编译时无法确定返回类型,就会报错。
1 | |
可以看到当返回值类型不同时(int和DateTime类型)将会提示这两种类型无法通过隐式的类型转换变成相同类型。(DateTime类型是时间类型,这里只是为了区分WriteLine函数的参数类型和返回值间的类型)
(?.)和(?[]) Null条件运算符
1 | |
代码中声明两个列表对象,其中一个为null,分别调用Add()函数给列表添加元素,在Vs编译时没有报错,代码编辑器中也没有红线警告,但是当编译运行后,代码运行至list1.Add(7);时,抛出NullReferenceException空指针异常。
很容易的看出由于list1为null并且没有做null检查。改下代码
1 | |
编译运行,程序正常运行,无异常无报错。通过调试诊断工具或者肉眼调试可以知道list1依然为null并且没有执行list1.Add(7)语句,list2中成功添加值为7的元素。
相同的操作,如果使用(?.)语法则变成这样
1 | |
代码执行后的结果与上一段代码相同。
?. 语法,首先判断问号前的对象是否为空,如果为空(null)则返回null并且停止执行其后的代码链,list1为null,不执行.Add()函数;如过不为null则继续执行其后的代码链,如list2.Add(7)。
1 | |
?[]也是同样的意思,如果问号前的对象为空则返回null,否则返回对应的值。
(??)和(??=) Null合并运算符
1 | |
?? 运算符,若左值为null,返回右值;否则返回左值。
(as) 类型转换
as语法对类对象进行强制转换
1 | |