Reputation: 51840
I have the following enumerator:
enum Foo { Bar, Baz };
In the following code, the compiler aborts with the error:
use of unassigned local variable 'str'
The code:
string str;
Foo foo = Foo.Bar;
switch (foo)
{
case Foo.Bar: str = "a"; break;
case Foo.Baz: str = "b"; break;
}
str.ToLower();
The switch
covers all the possible values of the enumerator. But the compiler still thinks that str
might be unassigned. Why is that? Of course I could put a default
case in there, but that would be wrong, since errors are not caught at compile-time. For example, if the Foo
enum is modified later on and a new value added, then it would be nice to get a compiler error. If I use a default
case, then the error is not caught when recompiling.
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?
Upvotes: 3
Views: 721
Reputation: 10947
Of course I could put a default case in there, but that would be wrong
That would be according to good practices. Your enum can still contain other numeric values, because enums in C# are only compile time layer above the underlying numeric representation - think const
fields. Foo f = (Foo)int.MaxValue;
will still compile and run, but now you don't have a switch case for it.
Depending on your interface, you may either put a default case with an exception there, define str
with null, or an empty string.
Upvotes: 1
Reputation: 29073
The enum is essentially an int and any int value could be assigned to it. This usually doesn't happen but is why you need to handle the default case or simply declare the string with a default value (like null)
Upvotes: 1
Reputation: 726559
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?
This is correct. Long story short, the reason why the compiler does this is that it is possible to assign foo
a value that is not one of a valid enum Foo
s values by typecasting an int
, making it possible to bypass all cases of the switch
.
The solution that I use in situations like this is to add an assertion:
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);
}
Upvotes: 3
Reputation: 2942
your best bet is to just initialize str with an empty string in your first line. the compiler can't (or won't) try to analyse the switch logic that deeply.
Upvotes: 0
Reputation: 171178
Enums are statically typed and type checked. But the checking does not extend to ensure that enum values only assume defined values. In fact, for Flags
enums variables often do not assume any single defined value.
Like that:
Foo f = (Foo)1234; //valid
And that's why the switch
can pick the default
case at runtime and str
could end up being used in an uninitialized state.
Some languages have stronger constructs than .NET enums such as Haskell and F#.
Upvotes: 1