I'm just curious why this code...
enum Tile { Empty, White, Black };
private string TileToString(Tile t)
{
switch (t)
{
case Tile.Empty:
return ".";
case Tile.White:
return "W";
case Tile.Black:
return "B";
}
}
Throws that error. It's not possible for t
to take on any other value, is it? Shouldn't the compiler be clever enough to figure that out?
No, you can use any int
value converted to Tile
. Try this:
Tile t = (Tile) 5;
string s = TileToString(t);
An enum is a set of names for numbers, effectively... but neither the compiler nor the CLR enforces that a value of the enum type has a name. It's a pain, but there it is...
I would suggest a default case which threw ArgumentException
(or possibly ArgumentOutOfRangeException
).
Jon is of course entirely correct that an enum can have any value of its underlying type, and therefore the switch is not exhaustive, and therefore there is a code path that does not return. However, that is not a complete analysis of the issue. Even if it were the case that the switch was exhaustive, you'd still get the error.
Try it:
int M(bool b)
{
switch(b)
{
case true : return 123;
case false: return 456;
}
}
Or
int M(byte b)
{
switch(b)
{
case 0: case 1: case 2: ... all of them ... case 255: return 123;
}
}
In both these cases you'll get the same "reachable end point in non-void method" error.
This is simply an oversight in the "reachability checking" section of the C# specification. We define the end point of a switch statement as being reachable if it doesn't have a default section, period. There is no special dispensation for switches that exhaustively consume every possible value of their input. It's a corner case that the language designers missed, and it's never been nearly a high enough priority to fix it.
For three other interesting facts about analysis of switch statements, see:
http://ericlippert.com/2009/08/13/four-switch-oddities/
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With