C#集合索引操作中!、!?运算符的含义及运行时行为是什么?
C# 空容忍运算符与条件访问组合使用相关解答
以下解答基于C# 8及以上版本的可空引用类型上下文环境,你提供的代码默认开启了可空引用类型检查。
1. 集合后、索引前!运算符的含义
这里的!是空容忍(null-forgiving)运算符,属于编译期静态分析用的后缀运算符。作用是显式告诉编译器:你确定当前修饰的表达式(这里是testList)在运行时一定不为null,要求编译器跳过对该表达式的空值警告检测。
无论后面是否接?运算符,!的作用范围都仅限于它前面紧邻的表达式(这里就是testList本身),不会影响后续的索引访问逻辑。
2. 编译器对!?组合的解析规则
!?并不是C#定义的独立组合运算符,编译器会按照后缀运算符优先级从高到低拆分解析:
- 后缀
!(空容忍运算符)的优先级高于后缀?[](条件索引访问运算符) - 因此
testList!?[3]会被编译器解析为(testList!)?[3]- 第一步先处理
testList!:将原本可能标记为可空的List<int>?类型的testList,标记为非空的List<int>类型 - 第二步对第一步得到的非空
List<int>执行条件索引访问?[3],最终返回值类型为int?,和你观察到的变量y的类型一致。
- 第一步先处理
3. 空容忍运算符的运行时行为与空值触发结果
- 空容忍运算符是纯编译期特性,运行时会被完全忽略,不会注入任何额外的检查或处理逻辑,仅用于抑制编译器的空值警告。
- 若运行时
testList实际为null:- 对于
testList![4]:等价于直接对null执行索引访问,会抛出NullReferenceException异常 - 对于
testList!?[3]:等价于对null执行条件索引访问,?[]检测到左操作数为null时会直接返回null,不会抛出异常,最终y的取值为null。
- 对于
4. !?与?的运行时等价性判断
是的,二者运行时行为完全等价。
因为!在运行时没有任何实际作用,testList!?[3]的运行时逻辑和testList?[3]完全一致。二者的区别仅存在于编译期:加!会抑制编译器对testList可能为null的警告输出,不加则会在testList被标记为可空时触发编译警告。
内容的提问来源于stack exchange,提问作者Abhijith C R
相关产品推荐
相关产品推荐

