C#中 ??, ?, ?:,?.运算符

2020年10月09日 09:56 0 点赞 1 评论 更新于 2025-11-21 21:34

在C#编程中,有几个特殊的运算符能极大地提升代码的简洁性和可读性。下面将详细介绍可空类型修饰符(?)、三元表达式运算符(?:)、空合并运算符(??)和NULL检查运算符(?.)。

可空类型修饰符(?)

在C#里,引用类型可以使用空引用表示一个不存在的值,但值类型通常不能表示为空。例如,string str = null; 是合法的,而 int i = null; 会导致编译器报错。

为了让值类型也能表示为空,可使用可空类型,通过可空类型修饰符 “?” 来实现,表现形式为 “T?”。比如,int? 表示可空的整型,DateTime? 表示可为空的时间类型。

实际上,T?System.Nullable<T>(泛型结构)的缩写形式。也就是说,当使用 T? 时,编译器在编译时会将其转换为 System.Nullable<T> 的形式。例如,int? 编译后会变成 System.Nullable<int>

三元(运算符)表达式(?:)

三元表达式是一种简洁的条件判断语句,其基本形式为 x? y : z

如果表达式 x 的值为 true,则返回 y;如果 x 的值为 false,则返回 z。它是省略 if {} else {} 语句的简单形式。

示例代码如下:

bool condition = true;
int result = condition? 1 : 2; // 由于 condition 为 true,result 的值为 1

空合并运算符(??)

空合并运算符用于定义可空类型和引用类型的默认值。

如果该运算符的左操作数不为 null,则返回左操作数;否则返回右操作数。例如,对于表达式 a?? b,当 anull 时返回 b,当 a 不为 null 时返回 a 本身。

空合并运算符是右结合运算符,即操作时从右向左进行组合。例如,“a?? b?? c” 的形式会按 “a?? (b?? c)” 进行计算。

示例代码如下:

string a = null;
string b = "default";
string result = a?? b; // 由于 a 为 null,result 的值为 b,即 "default"

NULL检查运算符(?.)

在实际编程中,经常需要对对象进行 NULL 检查,以避免空引用异常。例如,要获取一个 Point 序列的第一个点的 X 坐标,最初可能会这样写:

int firstX = points.First().X;

但这段代码没有进行 NULL 检查,可能会引发空引用异常。正确的写法应该是:

int? firstX = null;
if (points != null)
{
var first = points.FirstOrDefault();
if (first != null)
firstX = first.X;
}

虽然这样的代码是正确的,但变得难以阅读。在 C# 6.0 中,引入了 ?. 运算符,上述代码可以简化为:

int? firstX = points?.FirstOrDefault()?.X;

从这个例子可以看出 ?. 运算符的基本用法:如果对象为 NULL,则不进行后面的获取成员的运算,直接返回 NULL

需要注意的是,由于 ?. 运算符返回的可以是 NULL,当返回的成员类型是 struct 类型时,?.. 运算符的返回值类型是不一样的。例如,对于一个可空的 Point 类型 Point? pointpoint?.X 的返回类型是 int?,而 point.X 会在 pointnull 时引发异常。