调整null case位置消除CS8509警告,是否为C#穷举检查BUG?
可空枚举switch表达式的CS8509警告问题
问题场景
首先定义枚举类型:
public enum Test { Yes, No }
针对可空Test?变量编写switch表达式,第一种写法会触发CS8509警告:
Test? test = null; var result = test switch { null => "Null", Test.Yes => "Yes", Test.No => "No", };
但将null分支移至末尾后,警告消失:
Test? test = null; var result = test switch { Test.Yes => "Yes", Test.No => "No", null => "Null", };
项目配置如下:
<PropertyGroup> <TargetFramework>net6.0</TargetFramework> <LangVersion>10.0</LangVersion> <ImplicitUsings>enable</ImplicitUsings> <Nullable>enable</Nullable> <TreatWarningsAsErrors>true</TreatWarningsAsErrors> <NoWarn>8524</NoWarn> </PropertyGroup>
结论:这不是BUG
这是C#编译器对switch表达式穷举性检查的规则导致的,具体原因如下:
- 对于可空值类型的switch表达式,当先匹配
null分支后,编译器要求剩余分支覆盖所有非null的可能值。 - 枚举类型本质是整数类型,允许被强制转换为任意整数值(比如
(Test)2),即便这些值不在枚举定义范围内。因此编译器会判定,除Yes和No外还存在其他合法非null枚举值,第一种写法的分支未覆盖这些情况,触发CS8509警告。 - 当
null分支放在最后时,编译器会将前面的枚举值分支视为覆盖了所有「预期合法枚举值」,最后用null分支覆盖空值场景,此时判定已覆盖所有预期情况,因此不再触发警告。
消除第一种写法的警告
若要保留null分支在前的写法同时消除警告,可添加默认分支覆盖所有未明确列出的情况:
Test? test = null; var result = test switch { null => "Null", Test.Yes => "Yes", Test.No => "No", _ => throw new ArgumentOutOfRangeException(nameof(test), "无效的Test枚举值"), };
内容的提问来源于stack exchange,提问作者Xiaoguo Ge
相关产品推荐
相关产品推荐

