1

我有一个简短的设计问题要问大家。我有一个必须尽快执行的方法,但它还必须提供有关异常发生的错误的信息。

可能会在一个循环中调用函数一千次,但很少会发生异常(<1% 的值会导致错误)。该函数仅计算非常简单的数学运算,不调用任何方法,使用 LINQ 或其他方法。

好的,到目前为止的情况,下面描述了我必须解决这个方法的两个场景。

我自己的解决方案是最常用的方法,在计算前检查每个参数(防止在ramaining方法中出现异常):

int FastMethod(int number)
{
    if (number <= 0)
    {
        throw new ArgumentOutOfRangeException();
    }
    // (...) more parameter validations

    // do some operations with the number here
}

向我推荐的另一个解决方案是,遇到错误并且只重新抛出捕获的异常:

int FastMethod(int number)
{
    try
    {
        // do some operations with the number here
    }
    catch (Exception ex)
    {
        throw (ex);
    }
}

那么你会推荐什么?

第二种情况不需要调用所有这些可能会提高性能的 if 语句,但在我看来,它的设计看起来很糟糕。愿你能教我:)

4

2 回答 2

1

如果我正确理解您的问题,您是在问:我应该(1)允许发生异常,还是(2)我应该积极主动地测试输入变量(想想:防御性驾驶)?

我的想法

  1. 如果可能,您应该尝试尽快检测错误数据。调用链中的第一个方法应该处理该问题。
  2. 如果FastMethod方法是面向外的(例如公共 API 上的方法),那么我肯定会测试输入参数(数字)
  3. [项目符号不相关]
  4. 不要陷入过早优化的陷阱。性能真的是个问题吗?
  5. 正如 michaelb958 指出的那样,您的第二个示例没有做任何事情。更糟糕的是,您只需捕获并重新抛出异常,就会不必要地增加额外的时钟周期。

如果没有更多信息,我会说: - 使用场景 1:测试输入参数以确保它在范围内

附加阅读

更新 1LibFoo::WiggleBar()正如 MSalters 在他的评论 中正确指出的那样:参数检查应该放在调用链的最低级别。一般来说,我会以这种方式实现我的代码。感谢 MSalters 让我直截了当。

我最初的想法是:第 1 条是:如果性能确实是一个问题,那么获得回时钟周期的一种方法是避免不必要地添加到调用堆栈中。

@Tim Krüger:除非您 100% 确定性能将成为一个问题......我会专注于编写可维护 + 易于阅读 + 无错误的代码。

更新 2 删除了项目符号 3。

于 2013-04-19T13:16:25.260 回答
0

另一种选择是将 catch 块移动到调用者的一个级别之上,因此不会为每次迭代再次设置 try/catch 块。当然,只有当您不想在异常后继续循环时才有效。

一般性能建议:将所有内容移出并非绝对需要的循环。可能与尽早发现错误的规则相冲突,但这是权衡。

于 2013-04-19T15:48:22.363 回答