启用C# 8可空引用类型后,非可空字符串仍需空检查吗?
问题
笔者阅读了多篇介绍C# 8中启用可空引用类型优势的文章,了解到其主要由编译器实现,编译器会阻止将非可空字符串设为null。现给出如下带验证逻辑的简单方法:
public static string DoSomethingWithFileName(string filename) { ArgumentNullException.ThrowIfNull(filename); if(filename == string.Empty) throw new ArgumentException(nameof(filename)); }
请问:尽管filename是非可空类型,我们仍需对其进行空检查吗?如果需要,在启用可空引用类型的情况下,filename为何会变为null?
回答
1. 必须保留空检查
答案是肯定的,哪怕启用了可空引用类型,这个空检查也绝对不能省。
2. 非可空参数仍会被传入null的原因
可空引用类型本质是编译时的静态分析机制,并非CLR层面的强制约束,所以有很多场景会让非可空参数拿到null:
- 调用方主动绕过检查:调用者可以用
!空宽恕运算符强行给非可空参数传null,比如DoSomethingWithFileName(null!);,这种写法会让编译器跳过警告,但运行时确实会传入null。 - 不受编译器管控的调用场景:如果通过反射、非托管代码调用这个方法,或者从没有启用可空引用类型的旧项目代码中调用,编译器的检查完全覆盖不到,很可能传入null。
- 编译器分析有局限性:编译器的静态分析不是万能的,某些复杂的赋值逻辑、第三方库返回值等场景,编译器可能无法准确判断是否为null,导致实际运行时出现null值。
内容的提问来源于stack exchange,提问作者Joshua Duxbury
相关产品推荐
相关产品推荐

