说,我有以下枚举和代码测试枚举:
enum Flag
{
On,
Off
}
string GetMessage(Flag flag) =>
flag switch
{
Flag.On => "State is ON",
Flag.Off => "State is OFF"
};
Run Code Online (Sandbox Code Playgroud)
但是,我收到警告:
警告 CS8509 switch 表达式无法处理其输入类型的所有可能值(并非详尽无遗)。例如,不包括模式“(ConsoleApp.Flag)2”。
为什么当我列出所有枚举的值时它不是详尽无遗的?什么是(ConsoleApp.Flg)2
枚举值?
war*_*ies 12
好消息!在 Roslyn 编译器的最新版本中,此警告(例如,(ConsoleApp.Flag)2
未覆盖模式)已被赋予新代码 CS8524。
原始警告代码 CS8509 现在仅适用于缺少命名的枚举值。
因此,我们现在可以告诉编译器忽略 CS8524,我们认为为未命名枚举值编写一个包罗万象的处理程序是不必要的代码膨胀,但仍然希望捕获我们忘记处理命名值的情况(或者我们添加新的命名值到现有的枚举)。
另外,如果之前我们告诉编译器忽略 CS8509 以避免编写_ => throw ...
处理程序,那么我们现在可能希望将其更改为忽略 CS8524,这样我们就可以在我们确实想要警告的情况下获得 CS8509 警告!
背景: Roslyn 的更改是在dotnet/roslyn#47066中进行的,我在阅读dotnet/csharplang#2671 的评论时发现了这一点(枚举上的 switch 表达式的可耗尽性应该不那么严格)。
V0l*_*dek 11
反例:
string Foo()
{
return GetMessage((Flag)42);
}
Run Code Online (Sandbox Code Playgroud)
不幸的是,C# 枚举不如 Haskell 或其他具有更好 FP 功能的语言中的代数数据类型(或变体类型,无论您喜欢如何称呼它们)健壮。它实际上只是围绕整数数值(int
默认情况下)的一些元数据,因此类型系统中没有任何内容阻止您传递与有效枚举值不对应的值。编译器会告诉你,使用(Flag)2
一个可能的值。要解决这个问题,添加一个标准的包罗万象的:
string GetMessage(Flag flag) =>
flag switch
{
Flag.On => "State is ON",
Flag.Off => "State is OFF",
_ => throw new ArgumentOutOfRangeException(nameof(flag)),
};
Run Code Online (Sandbox Code Playgroud)