使用空合并运算符抛异常后,变量仍为可空string?的原因咨询
问题解答
核心原因在于C#空合并运算符??的类型推断规则:它的结果类型由左右操作数的公共可兼容静态类型决定,不会基于运行时逻辑做智能修正。
你的场景里,左侧表达式dict?["key"]的静态类型是string?——一方面字典本身是可空类型(Dictionary<string, string?>?),另一方面字典的值类型就是可空字符串,所以索引访问的结果必然被推断为string?。而右侧的throw new Exception()属于throw表达式,它的底层类型是Never(一种可隐式转换为任意类型的特殊类型)。
当??进行类型推断时,会取左右操作数的公共类型:由于Never能兼容所有类型,最终结果类型会以左侧的string?为准。哪怕throw语句会确保程序不会返回null,编译器也不会通过运行时逻辑去修改静态类型推断的结果。
解决办法
- 使用空宽恕运算符
!:直接告知编译器该值不会为null,强制转为非可空类型:string value = (dict?["key"] ?? throw new Exception())!; - 显式类型转换:直接将表达式结果强制转为
string:string value = (string)(dict?["key"] ?? throw new Exception()); - 换用更严谨的字典访问逻辑:比如用
TryGetValue从根源规避可空类型问题:if (dict == null || !dict.TryGetValue("key", out var value)) { throw new Exception(); } string nonNullableValue = value!;
内容的提问来源于stack exchange,提问作者Moffen
相关产品推荐
相关产品推荐

