@[TOC](C# 中的问号(?)与双问号(??)运算符详解)
1. 问号(?):可空类型声明
在 C# 中,问号(?)用于声明可空类型(Nullable Types),表示该变量可以存储null值。
1.1 基本语法
int?a=newint?();Console.WriteLine(a);// 输出:null1.2 等价写法
上述声明等价于:
int?a=null;也等价于:
int?a;// 声明可空整型变量,默认值为 null1.3 使用场景
可空类型主要用于值类型(如int、float、double等),允许它们像引用类型一样接受null值。这在数据库操作、API 响应处理等场景中非常有用。
2. 双问号(??):空值合并运算符
双问号(??)是 C# 中的空值合并运算符(Null-coalescing operator),用于简化null值检查。
2.1 基本语法
c=a??b;2.2 等价写法
上述表达式等价于:
c=(a==null)?b:a;2.3 使用规则与注意事项
规则 1:类型一致性要求
a和b必须是相同类型,且a必须是可以为null的类型:
- 引用类型(如
object、string等) - 可空值类型(如
int?、float?、double?等) dynamic动态类型
正确示例 1:引用类型
// 例1:a,b 同为引用类型,a 可以为空objecta=null;objectb=10;objectc=a??b;// a,b,c 的类型相同正确示例 2:可空值类型
// 例2:a,b 同类型,a 为可空类型int?a=null;intb=10;intc=a??b;// 或者进行隐式转换floatc=a??b;// a??b 表达式的值为 int 型,隐式转换为 float 型错误示例:类型不匹配
// 例3:a,b 是不同类型,编译报错int?a=null;stringb="hello";stringc=a??b;// 错误:运算符"??"无法应用于"int?"和"string"类型的操作数规则 2:表达式类型与赋值兼容性
a ?? b表达式的值类型与a、b相同,因此:
c必须与a、b同类型,或者- 对
a ?? b表达式的值进行隐式转换或强制类型转换
正确示例:类型转换
// 示例 1:转换为字符串int?a=null;intb=10;stringc=(a??b).ToString();// 示例 2:强制类型转换objecta=null;objectb=10;intc=(int)(a??b);2.4 链式使用
双问号运算符支持链式调用,这在处理多层可能为null的值时非常方便:
stringresult=value1??value2??value3??"默认值";3. 实际应用场景
3.1 数据库字段处理
int?ageFromDb=GetAgeFromDatabase();// 可能返回 nullintage=ageFromDb??0;// 如果为 null,则使用默认值 03.2 配置项读取
stringconnectionString=ConfigurationManager.AppSettings["ConnectionString"]??"DefaultConnectionString";3.3 方法参数默认值
publicvoidProcessData(stringdata,string?fallback=null){stringactualData=data??fallback??"默认数据";// 处理 actualData}4. 总结
| 运算符 | 名称 | 用途 | 示例 |
|---|---|---|---|
? | 可空类型修饰符 | 声明值类型变量可以存储null | int? age = null; |
?? | 空值合并运算符 | 提供null时的默认值 | string name = input ?? "匿名"; |
关键要点:
- 问号(
?):让值类型具备存储null的能力 - 双问号(
??):简化null检查,提供优雅的默认值处理 - 类型安全:使用
??时需确保操作数类型兼容 - 链式调用:
??支持多级空值检查,代码更简洁
掌握这两个运算符能显著提升 C# 代码的健壮性和可读性,特别是在处理可能缺失的数据时。