切换枚举后,编译器会抱怨未分配的变量

时间:2014-08-30 13:16:37

标签: c# enums switch-statement

我有以下普查员:

enum Foo { Bar, Baz };

在以下代码中,编译器将中止错误:

use of unassigned local variable '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大小写,则重新编译时不会捕获错误。

我认为没有办法让编译器接受switch没有default案例如果稍后会延长Foo则会引发错误?

5 个答案:

答案 0 :(得分:2)

  

我想没有办法让编译器接受没有默认情况的开关,如果稍后扩展Foo会引发错误?

这是对的。简而言之,编译器执行此操作的原因是,通过对foo进行类型转换,可以为enum Foo分配一个不是有效int值的值,可以绕过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);
}

答案 1 :(得分:1)

枚举是静态类型和类型检查。但是检查不会延伸以确保枚举值仅假定定义的值。实际上,对于Flags枚举,变量通常不会假定任何单个定义的值。

就像那样:

Foo f = (Foo)1234; //valid

这就是为什么switch可以在运行时选择default案例而str最终可能会在未初始化状态下使用。

某些语言的构造比.NET枚举更强大,例如Haskell和F#。

答案 2 :(得分:1)

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

答案 3 :(得分:1)

  

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

根据良好做法。您的枚举仍然可以包含其他数值,因为C#中的枚举只是基础数字表示上方的编译时间层 - 请考虑const字段。 Foo f = (Foo)int.MaxValue;仍然会编译并运行,但现在你没有切换案例。

根据您的界面,您可以将默认情况设置为异常,使用null定义str或使用空字符串。

答案 4 :(得分:0)

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