Switch + Enum =并非所有代码路径都返回一个值

时间:2010-09-02 08:14:34

标签: c#

我只是好奇为什么这段代码......

    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不可能承担任何其他价值,是吗?编译器不应该足够聪明地弄明白吗?

5 个答案:

答案 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语句分析的其他三个有趣的事实,请参阅:

http://ericlippert.com/2009/08/13/four-switch-oddities/

答案 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指出的那样,值是积分的 - 枚举可以从任何积分值转换而来。您只需要处理默认值。