2014-08-30 55 views
3

我有以下枚举:编译抱怨未赋值的变量开关后枚举

use of unassigned local variable 'str'

的代码:

enum Foo { Bar, Baz }; 

在下面的代码,编译器与错误中止

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扩展以后产生一个错误?

回答

2

I suppose there is no way to get the compiler to accept a switch without a default case and raise an error if Foo is extended later on?

这是正确的。长话短说,编译器这样做的原因是,可以通过类型化一个int来指定foo一个不是有效enum Foo s值的值,从而可以绕过所有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); 
} 
+0

断言在这种情况下看起来是最好的主意。 – 2014-08-30 13:46:25

+0

您可以使用'Debug.Fail(...)'而不是'Debug.Assert(false,...)'。最后一个开关部分如何继续?你会为'str'和'break'分配一个虚拟值(如'null')吗?或者你会抛出?你不能“跌倒”;交换机部分的端点必须无法访问。 – 2015-06-09 22:04:12

1

枚举是静态类型和类型检查。但是这种检查并没有扩展,以确保枚举值只能假定定义的值。实际上,对于Flags枚举变量通常不会假定任何单个定义的值。

就像是:

Foo f = (Foo)1234; //valid 

这就是为什么switch可以在运行时挑选default情况和str可能最终未初始化状态使用。

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

0

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

1

枚举本质上是一个int和任何int值可以被分配给它。这通常没有这将是根据良好做法发生,但就是为什么你需要处理默认情况下,或简单地声明了默认值(如空)字符串

1

Of course I could put a default case in there, but that would be wrong

。您的枚举仍然可以包含其他数值,因为C#中的枚举只是编译时间层的基础数字表示之上 - 请考虑const字段。 Foo f = (Foo)int.MaxValue;仍然会编译并运行,但现在你没有它的开关箱。

根据您的界面,您可以将默认情况设置为例外,使用空值或空字符串定义str