使用异常退出功能

时间:2015-04-02 08:45:40

标签: c# exception

我在编写解析器时遇到了问题。 以下函数都调用GetSymbol()函数。这些功能也可以互相调用。 Body()将调用Statement(),Statement()将调用Expression() 等等。

问题是,在任何函数中,符号列表都可以为空。我认为没有必要为每个函数添加额外的代码。相反,我在程序中添加了一个try catch。

以这种方式使用例外是不是错了 因为如果GetSymbol用完符号,则预期行为。

我应该避免抛出异常吗?

List<Symbol> symbols;

private void Term()
{...}
private void Expression()
{...}
private void Statement()
{...}
private void Body()
{...}

private Symbol GetSymbol()
{
    if (symbols.Count > 0)

    else
        throw new OutOfTokenException();
}

public void Program()
{
    try
    {
        while (Accept(Symbol.LBRACE))
            Body();
    }
    catch (OutOfTokenException ote)
    {
        Output("Unexpected end of file");
    }
}

}

4 个答案:

答案 0 :(得分:1)

异常表示一组用例的异常大小写,这是您的程序并不真正期望的,但可能发生,这是一种常见的情况,尤其是在处理用户输出时。

我不理解的是 符号列表如何为空?如果符合您规则的有效文本主体可以为空,那么您将需要满足这些方案而无例外。

另一方面,如果一组空的符号表示用户应该已经完成​​但没有完成的某些符号,如果没有它,您的应用程序将无法运行,那么,您应该抛出异常。

答案 1 :(得分:1)

你是对的 - 抛出异常以处理好的情况是不好的做法。这与使用一般分支和控制流的异常几乎相同,这是一种反模式(here is a Java related question解释它)。

如果没有找到符号,您的GetSymbol()方法应返回null - 除非您在没有符号时特别想要错误状态。

答案 2 :(得分:1)

尝试更改您的代码,这样您就有了一个点,您可以检查是否还有符号。像这样:

private Symbol GetSymbol()
{
    // just your logic to get symbol
}

private bool SymbolExists()
{
    return this.symbols.Count > 0;
}

并重写你调用代码:

public void Program()
{
        while (SymbolExists())
        {
            Accept(GetSymbol(Symbol.LBRACE)
            Body();
        }
}

还要考虑将代码转换为独立的单元/类,如SymbolReader等。这样,您可以将“symbols”集合作为参数传递,并在分配之前对其进行验证。并且你可以保留你原来的GetSymbol()实现,以确保在有人滥用你的代码时(通过在阅读之前不调用SymbolExists())抛出适当的异常。

答案 3 :(得分:0)

您的代码缺少某些背景信息,例如类声明,它将告诉该类的公共接口是什么。我假设GetSymbol(Symbol.LBRACE)调用是错误的,因为没有匹配签名的方法。

似乎类的前提条件允许它在任何时候调用Program,因此Program不应该抛出异常。请记住,每个方法都有前提条件和后置条件。当且仅当调用者违反前提条件时,应该抛出异常。

现在问题是:当没有符号可以获得时,是否可以拨打GetSymbol?答案决定了它是否应该抛出异常。

但是:使用try / catch会模糊你的意图。这足以摆脱它的理由。像Yura所建议的SymbolExists方法可以使你的意图完全清楚。

如果GetSymbol为空,则错误的解决方案是null返回symbols并检查null中的Accept。你仍然摆脱了try / catch,但它同样模糊了你的意图,因此同样糟糕(再次恕我直言)。