C# 使用异常退出函数

C# 使用异常退出函数,c#,exception,C#,Exception,我在编写解析器时遇到了一个问题。 以下函数都在调用GetSymbol()函数。这些函数也相互调用。 Body()将调用Statement(),Statement()将调用Expression() 等等 问题是,在任何函数中,符号列表都可能为空。我认为没有必要为每个函数添加额外的代码。相反,我在程序中添加了一个try-catch 这样使用异常不是不对吗 因为如果GetSymbol用完了符号,这是预期的行为 我应该避免抛出异常吗 List<Symbol> symbols; privat

我在编写解析器时遇到了一个问题。 以下函数都在调用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");
    }
}
列出符号;
专用无效期限()
{...}
私有void表达式()
{...}
私人无效声明()
{...}
私人机构()
{...}
私有符号GetSymbol()
{
如果(符号数>0)
其他的
抛出新的OutOfTokenException();
}
公共空间计划()
{
尝试
{
while(接受(Symbol.LBRACE))
身体();
}
捕获(超出tokenexception注释)
{
输出(“意外的文件结尾”);
}
}
}

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

我不明白的是,你的符号列表怎么可能是空的?如果与规则匹配的有效文本体可以为空,则您需要毫无例外地满足该场景

另一方面,如果一组空符号表示用户应该做但没有做的事情,并且没有它,应用程序就无法运行,那么,您应该抛出异常。

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

我不明白的是,你的符号列表怎么可能是空的?如果与规则匹配的有效文本体可以为空,则您需要毫无例外地满足该场景

另一方面,如果一组空符号表示用户应该做但没有做的事情,并且没有它,应用程序就无法运行,那么,您应该抛出异常。

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

我不明白的是,你的符号列表怎么可能是空的?如果与规则匹配的有效文本体可以为空,则您需要毫无例外地满足该场景

另一方面,如果一组空符号表示用户应该做但没有做的事情,并且没有它,应用程序就无法运行,那么,您应该抛出异常。

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

我不明白的是,你的符号列表怎么可能是空的?如果与规则匹配的有效文本体可以为空,则您需要毫无例外地满足该场景


另一方面,如果一组空符号表示用户应该做但没有做的事情,没有它应用程序就无法运行,那么,您应该抛出异常。

您是对的-抛出异常来处理好的情况是不好的做法。这几乎等同于对一般分支和控制流使用异常,这是一种反模式(解释了这一点)


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

您是对的-抛出异常以处理正常情况是不好的做法。这几乎等同于对一般分支和控制流使用异常,这是一种反模式(解释了这一点)


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

您是对的-抛出异常以处理正常情况是不好的做法。这几乎等同于对一般分支和控制流使用异常,这是一种反模式(解释了这一点)


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

您是对的-抛出异常以处理正常情况是不好的做法。这几乎等同于对一般分支和控制流使用异常,这是一种反模式(解释了这一点)


如果找不到符号,则您的
GetSymbol()
方法应返回null,除非您特别希望在没有符号时出现错误状态。

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

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之类。通过这种方式,您可以将“符号”集合作为参数传递,并在赋值之前对其进行验证。您可以保持GetSymbol()实现的原始状态,以确保在有人误用您的代码时(通过在读取之前不调用SymbolExists())引发正确的异常。

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

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之类。通过这种方式,您可以将“符号”集合作为参数传递,并在assig之前对其进行验证