我只是好奇为什么这段代码......
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";
}
}
引发该错误。 t
不可能承担任何其他价值,是吗?编译器不应该足够聪明地弄明白吗?
答案 0 :(得分:30)
不,您可以使用转换为int
的任何Tile
值。试试这个:
Tile t = (Tile) 5;
string s = TileToString(t);
枚举是数字的一组名称,实际上......但是编译器和CLR都没有强制枚举类型的值具有名称。这是一种痛苦,但它就是......
我会建议投放ArgumentException
(或可能是ArgumentOutOfRangeException
)的默认案例。
答案 1 :(得分:23)
Jon当然完全正确,枚举可以具有其基础类型的任何值,因此切换不是详尽的,因此存在不返回的代码路径。 然而,这不是对问题的完整分析。 即使交换机是详尽无遗的,您仍然会收到错误。
试一试:
int M(bool b)
{
switch(b)
{
case true : return 123;
case false: return 456;
}
}
或者
int M(byte b)
{
switch(b)
{
case 0: case 1: case 2: ... all of them ... case 255: return 123;
}
}
在这两种情况下,您将获得相同的“非空方法中的可到达终点”错误。
这只是C#规范“可达性检查”部分的疏忽。如果switch语句的端点没有默认的section,则将它们的端点定义为可达。对于彻底消耗其输入的每个可能值的开关,没有特别的分配。这是语言设计师遗漏的一个极端案例,并且它的修复程度从未高度优先。
关于switch语句分析的其他三个有趣的事实,请参阅:
答案 2 :(得分:1)
这是因为如果你的t值与任何一个开关情况都不匹配,它就会掉出开关,因此你的方法不会返回一个值。但是,您声明它将返回一个字符串。您需要在交换机中添加默认值,或者返回null:
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";
}
return null;
}
答案 3 :(得分:1)
添加默认案例:
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";
default:
return ".";
}
}
答案 4 :(得分:0)
switch (t)
{
case Tile.Empty:
return ".";
case Tile.White:
return "W";
case Tile.Black:
return "B";
default: throw new NotSupportedException();
}
正如Jon指出的那样,值是积分的 - 枚举可以从任何积分值转换而来。您只需要处理默认值。