3

我有以下模式:

private void MyFunction()
{
    doStuff();

    if (problem())
    {
        cleanup();
        return;
    }

    doMoreStuff();

    if (otherProblem())
    {
        cleanup();
        return;
    }

    doYetMoreStuff();
}

错误清除代码重复。消除这种情况的明显方法是:

private void MyFunction()
{
    try {
        doStuff();

        if (problem()) throw new MyException();

        doMoreStuff();

        if (otherProblem()) throw new MyException();

        doYetMoreStuff();
    }
    catch (MyException)
    {
        cleanup();
        return;
    }
}

但是,错误情况并不是真正的例外 - 这是一个 ASP.Net 页面,查询字符串中的错误数据或没有数据将触发错误情况。异常似乎是对错误处理进行重复数据删除并将其与主代码分开的最明显方法,但据我了解,公认的最佳实践是不要对这样的控制流使用异常。

这样做的习惯方法是什么?

4

5 回答 5

3

在非异常情况下使用异常并不是一个好主意,尤其是当异常被抛出并在同一个方法中捕获时。更好的方法是使用一个布尔变量来指示需要清理,并在finally块内执行清理。

var needsCleanup = true;
try {
    doStuff();

    if (problem()) return;

    doMoreStuff();

    if (otherProblem()) return;

    doYetMoreStuff();

    needsCleanup = false;
} finally {
    if (needsCleanup) {
        cleanup;
    }
}
于 2012-07-05T13:38:24.123 回答
1

您可以使用 try .. finally 和提前返回。

private void MyFunction()
{
  try
  {
    doStuff();

    if (problem())
    {
        return;
    }

    doMoreStuff();

    if (otherProblem())
    {
        return;
    }

    doYetMoreStuff();
  }
  finally
  {
    cleanup();
  }
}
于 2012-07-05T13:40:15.483 回答
1

finally块将在执行离开该try块时执行,即使它离开该try块的原因是因为您调用了return. 所以,你可以这样做:

private void MyFunction()
{
    try
    {
        doStuff();
        if (problem()) return;

        doMoreStuff();
        if (otherProblem()) return;

        doYetMoreStuff();
    }
    finally
    {
        cleanup();
    }
}
于 2012-07-05T13:40:44.110 回答
0

Ifcleanup()实际上只是一个方法调用而不是重复

在这种情况下,我不会使用异常。您可以轻松地在谷歌上搜索详细描述为什么在正常流程中使用异常是一个坏主意的文章:主要是影响性能并且会搞砸性能计数器(“抛出的异常数”将毫无意义)。

于 2012-07-05T13:37:05.003 回答
0

当意外发生时应该抛出异常。

考虑你想在你的数据库中添加一个用户,但如果用户名已经存在,你只需要一个错误说明。现在,错误不一定是异常!

bool AddUser(string username)

现在流程看起来像这样:

if(AddUser(username)) {}
else
{
    // Notify the user that it didn't work
}

如果这里抛出异常,应该是软件无法连接数据库,而不是用户名已经存在。

像这样为流控制抛出和捕获异常会导致比需要更多的开销,因此您应该使用if/else来控制它。

于 2012-07-05T13:39:56.387 回答