在c#开启可空引用类型(nullable reference types)后,`string?` 判空应优先使用 `== null` 或 `!= null` 进行显式检查,或者使用 `string.isnullorempty()` / `string.isnullorwhitespace()`。编译器会针对 `string?` 发出警告,提示可能为 null,因此必须通过条件判断来缩小类型范围(narrowing),将变量从 `string?` 转换为非空的 `string`,从而消除后续使用的编译警告。

如何消除 string? 的编译警告?
消除 `string?` 编译警告的核心在于“缩小类型”(Narrowing)。当你对一个 `string?` 变量执行了 `null` 检查后,编译器能够推断出在该代码块内该变量不再为 null,从而将其视为 `string`。最常用的方法是使用 `if (variable != null)` 语句。此外,C# 9.0 引入了 null 状态属性(Null State Attributes),但针对局部变量的即时处理,显式的 null 检查是最直接且兼容性最好的方式。如果变量可能为空字符串,则需结合 `string.IsNullOrEmpty` 使用。

using System;
public class Program
{
public static void Main()
{
// 模拟一个可能为 null 的输入
string? input = GetInput();
// 方法1:显式 null 检查(推荐用于大多数场景)
if (input != null)
{
// 在此作用域内,input 被编译器识别为 string
Console.WriteLine(input.Length);
}
else
{
Console.WriteLine("Input is null");
}
// 方法2:处理 null 或空字符串
if (!string.IsNullOrEmpty(input))
{
Console.WriteLine($"Valid input: {input}");
}
}
private static string? GetInput()
{
return null; // 模拟返回 null
}
}
string? 与 string 在 API 设计中的区别是什么?
在 API 设计中,声明参数或返回类型为 `string` 意味着调用者保证传入的值不为 null,且调用者期望返回值不为 null。而 `string?` 则表示该值允许为 null。对于 `string?` 类型的返回值,调用者必须进行 null 检查才能安全使用。这种区分有助于静态分析工具捕捉潜在的 NullReferenceException。在使用 `string?` 时,应避免直接访问其成员(如 `.Length` 或索引器),除非已经通过逻辑确认其非 null。可以使用 null 合并运算符 `??` 提供默认值,这既是一种判空策略,也是一种类型转换手段,将 `string?` 转换为 `string`。

using System;
public class ApiConsumer
{
public void ProcessData(string? data)
{
// 错误做法:直接访问可能导致运行时异常
// int len = data.Length;
// 正确做法1:使用 ?? 提供默认值
string safeData = data ?? "Default";
Console.WriteLine(safeData.Length);
// 正确做法2:使用 null 条件运算符
int? length = data?.Length;
// 正确做法3:显式检查
if (data is not null)
{
Console.WriteLine(data.ToUpper());
}
}
}
当 string? 为 null 时,使用 ?? 运算符的结果是什么?
当 `string?` 变量为 null 时,使用 null 合并运算符 `??` 会返回右侧提供的默认值。这个操作不仅避免了 null 引用异常,还自动将结果类型从 `string?` 提升为 `string`,因为无论左侧是否为 null,最终结果都是一个确定的非 null 字符串。例如,`string? nullableStr = null; string result = nullableStr ?? "fallback";` 中,`result` 将是 "fallback",且其类型为 `string`,后续可直接使用而不产生编译警告。这是处理可选字符串参数或配置项中最简洁的方式。


















