编译器在打开枚举后抱怨未分配的变量
本文关键字:分配 变量 枚举 编译器 | 更新日期: 2023-09-27 18:20:01
我有以下枚举器:
enum Foo { Bar, Baz };
在以下代码中,编译器中止并返回错误:
使用未分配的局部变量"str"
代码:
string str;
Foo foo = Foo.Bar;
switch (foo)
{
case Foo.Bar: str = "a"; break;
case Foo.Baz: str = "b"; break;
}
str.ToLower();
switch
涵盖了枚举器的所有可能值。但是编译器仍然认为str
可能是未赋值的。为什么?当然,我可以在其中放入default
案例,但这是错误的,因为在编译时不会发现错误。例如,如果稍后修改Foo
枚举并添加新值,则会出现编译器错误。如果我使用default
的情况,那么在重新编译时不会捕捉到错误。
我想没有办法让编译器在没有default
大小写的情况下接受switch
,并且如果稍后扩展Foo
,会引发错误?
我想如果以后扩展Foo,就没有办法让编译器接受没有默认情况的开关并引发错误?
这是正确的。长话短说,编译器这样做的原因是,通过类型转换int
,可以为foo
分配一个不是有效enum Foo
值之一的值,从而可以绕过switch
的所有情况。
我在这种情况下使用的解决方案是添加一个断言:
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);
}
枚举是静态类型化的,并进行类型检查。但检查并没有扩展到确保枚举值只采用已定义的值。事实上,对于Flags
,枚举变量通常不采用任何单个定义的值。
比如:
Foo f = (Foo)1234; //valid
这就是为什么switch
可以在运行时选择default
的情况,而str
最终可能在未初始化的状态下使用。
有些语言具有比.NET枚举更强的构造,如Haskell和F#。
枚举本质上是一个int,任何int值都可以分配给它。这通常不会发生,但这就是为什么你需要处理默认情况,或者简单地用默认值(如null)声明字符串
当然,我可以把默认情况放在那里,但这将是错误的
这将符合良好做法。您的枚举仍然可以包含其他数值,因为C#中的枚举只是底层数值表示之上的编译时层——想想const
字段。Foo f = (Foo)int.MaxValue;
仍将编译和运行,但现在您没有用于它的切换案例
根据您的接口,您可以在其中放置带有异常的默认大小写,也可以用null或空字符串定义str
。
您的最佳选择是在第一行中使用空字符串初始化str。编译器不能(或不会)尝试对切换逻辑进行深入分析。