C# 编译器在打开枚举后抱怨未分配变量

C# 编译器在打开枚举后抱怨未分配变量,c#,enums,switch-statement,C#,Enums,Switch Statement,我有下列统计员: enum Foo { Bar, Baz }; 在以下代码中,编译器将中止并显示错误: use of unassigned local variable 'str' 开关覆盖枚举数的所有可能值。但是编译器仍然认为str可能是未赋值的。为什么呢?当然,我可以在那里放一个default大小写,但那是错误的,因为在编译时不会捕获错误。例如,如果以后修改了Fooenum并添加了一个新值,那么最好得到一个编译器错误。如果我使用默认值案例,则在重新编译时不会捕获错误 我想如果以后扩展了Fo

我有下列统计员:

enum Foo { Bar, Baz };
在以下代码中,编译器将中止并显示错误:

use of unassigned local variable 'str'
开关
覆盖枚举数的所有可能值。但是编译器仍然认为
str
可能是未赋值的。为什么呢?当然,我可以在那里放一个
default
大小写,但那是错误的,因为在编译时不会捕获错误。例如,如果以后修改了
Foo
enum并添加了一个新值,那么最好得到一个编译器错误。如果我使用
默认值
案例,则在重新编译时不会捕获错误


我想如果以后扩展了
Foo
,编译器就无法在没有
默认值的情况下接受
开关
,并引发错误?

枚举是静态类型并进行类型检查的。但检查并没有扩展到确保枚举值仅采用定义的值。事实上,对于
标志
枚举变量通常不采用任何单个定义值

就像这样:

Foo f = (Foo)1234; //valid
这就是为什么
开关
可以在运行时选择
默认
情况,并且
str
可能最终在未初始化状态下使用


有些语言的结构比.NET枚举(如Haskell和F#)更强。

最好的办法是在第一行中用空字符串初始化str。编译器不能(或不会)深入分析开关逻辑

我想如果以后扩展了Foo,那么没有办法让编译器接受没有默认大小写的开关并引发错误

这是正确的。长话短说,编译器之所以这样做,是因为可以通过键入
int
来分配
foo
一个不是有效
enum foo
s值之一的值,从而可以绕过
开关的所有情况

我在这种情况下使用的解决方案是添加断言:

switch (foo)
{
    case Foo.Bar: str = "a"; break;
    case Foo.Baz: str = "b"; break;
    default: Debug.Assert(false, "An enum value is not covered by switch: "+foo);
}

枚举本质上是一个int,任何int值都可以分配给它。这通常不会发生,但这就是为什么您需要处理默认情况,或者只需使用默认值(如null)声明字符串

当然,我可以在那里放一个默认案例,但那是错误的

这将符合良好做法。您的枚举仍然可以包含其他数值,因为C#中的枚举只是底层数值表示之上的编译时层—想想
const
字段<代码>Foo f=(Foo)int.MaxValue
仍将编译并运行,但现在您没有它的切换用例


根据您的界面,您可以将带有异常的默认大小写放在那里,用null定义
str
,或空字符串。

在这种情况下,断言看起来是最好的主意。您可以使用
Debug.Fail(…)
而不是
Debug.Assert(false)
。最后一个开关部分是如何进行的?您会给
str
break
分配一个伪值(如
null
)吗?或者你会抛出
?你不能“失败”;交换机段的端点必须不可访问。
switch (foo)
{
    case Foo.Bar: str = "a"; break;
    case Foo.Baz: str = "b"; break;
    default: Debug.Assert(false, "An enum value is not covered by switch: "+foo);
}