📅  最后修改于: 2023-12-03 15:13:49.404000             🧑  作者: Mango
在 C# 中,当我们使用引用类型时,我们需要时刻考虑到可能出现 null 值的情况。Null 值在引用类型中通常代表着这个对象不存在或者未被初始化。因此,在我们使用对象的属性和方法之前,必须先对其进行 null 检查,避免引发 NullReferenceException 异常。
常规的 Null 检查方法包括使用 if 语句和三元运算符来判断一个对象是否为 null。例如,下面代码检查了一个对象是否为 null,如果不是则调用其 ToString() 方法并将结果赋给一个字符串变量:
object obj = null;
string str;
if (obj != null)
{
str = obj.ToString();
}
else
{
str = "Object is null.";
}
或者可以使用三元运算符来简化上面的代码:
object obj = null;
string str = (obj != null) ? obj.ToString() : "Object is null.";
使用三元运算符可以使代码更加简短和易于阅读,但是如果判断语句比较复杂,建议使用 if 语句进行判断。
C# 6.0 引入了一个新的运算符,称为 "null 合并运算符"(??),它可以在一行代码中完成常规的 Null 检查操作。例如:
object obj = null;
string str = obj?.ToString() ?? "Object is null.";
在上面的代码中,如果 obj 不为 null,则调用其 ToString() 方法;否则,返回一个默认的字符串 "Object is null."。
虽然常规的 Null 检查方法可以有效地避免 NullReferenceException 异常,但是在多线程环境下,还是会存在一些问题。例如,在下面的代码中,多个线程同时对 obj 进行了 null 检查,但是在执行之前,obj 被另一个线程设置为了 null,这时候线程就有可能引发 NullReferenceException 异常。
object obj = null;
// 线程 A
if (obj != null)
{
Console.WriteLine(obj.ToString());
}
// 线程 B
obj = new object();
要解决这个问题,可以使用 C# 6.0 中引入的 "安全导航运算符"(?。)。它和 null 合并运算符相似,但是如果对象为 null,它不会返回默认值,而是直接返回 null。因此,用它进行 Null 检查时,需要在代码中进一步判断是否为 null,可以使用 if 语句或者 Null 条件表达式。
例如,下面的代码使用安全导航运算符和 Null 条件表达式对对象进行了异常安全的 Null 检查:
object obj = null;
// 线程 A
var str = obj?.ToString();
if (str != null)
{
Console.WriteLine(str);
}
// 线程 B
obj = new object();
在上面的代码中,使用安全导航运算符和 Null 条件表达式进行了 Null 检查,如果对象为 null,则返回 null;否则,调用其 ToString() 方法并返回一个字符串。在使用这种方式进行 Null 检查时,需要进行进一步的判断,避免因为多线程操作导致空指针异常的发生。
总之,Null 检查是写每个程序员都需要掌握的基本技能之一。无论是在单线程还是多线程环境下,我们都需要时刻保持注意,避免因为空指针异常而导致程序崩溃。