当你知道你正在调用的方法会抛出相同的东西时,你会抛出异常吗?

时间:2010-11-04 19:21:59

标签: .net language-agnostic exception exception-handling

说我有这样的方法*:

public T GetItem(int index)
{
    if (index < 0 || index >= _privateList.Count)
    {
        throw new ArgumentOutOfRangeException("index");
    }

    return _privateList[index];
}

您是否会将throw包括在内或将其遗漏?一方面,我觉得立即处理无效输入是件好事,因为这样可以让您在编写实际实现代码时对所处理的内容更有信心。但在这种情况下,如果省略了边界检查,最终结果将大致相同( list 将抛出ArgumentOutOfRangeException而不是封闭类型。)

此外,由于上面的代码正在检查我的内容,开发人员知道无论如何都会被检查(在_privateList[index]的调用中),似乎我正在制作代码执行的工作比上面需要的多,基本上执行完全相同的两组比较。

对此主题的任何指导都将不胜感激。

*具体来说,我在谈论.NET(C#),但我想可以提出许多不同语言/框架的相同或类似问题 - 因此是“与语言无关”的标签。

4 个答案:

答案 0 :(得分:5)

我尽量不添加噪音(没有值的代码)。如果我的异常对我更有用,那么我会抛出异常,但如果它完全相同则代码的清晰度优先。

答案 1 :(得分:3)

在.net 4中我定义了这个条件的代码契约。在早期的.net版本中,我通常不会手动抛出这样的异常。

IMO在库代码和应用程​​序代码之间存在很大差异。在库代码中,我对定义良好的错误行为更加小心,并且在应用程序代码中抛出了正确的异常。

答案 2 :(得分:2)

这是您在.NET框架中找到的代码。在那里非常重要,源代码是不可用的。如果未包含参数检查,则会出现难以诊断的异常。它轰炸了隐形代码,得出结论参数错误并不容易。

这对您编写的代码不太关心。但不是缺席,这取决于谁将成为代码的最终用户。如果那是你,并且你维护代码,那么你在诊断原因时几乎没有问题。如果是其他人,那么他们也可以随时访问源代码的准确副本。如果这完全混乱,那么请不要犹豫,包括支票。

另一个考虑因素是在部署代码的Release版本时会发生什么。如果没有throw语句,很可能会内联此特定代码。换句话说,您不会在堆栈顶部看到GetItem()方法。这可以使查找异常的真正来源变得更加困难,尤其是因为释放堆栈跟踪没有行号。

然后费用是相关的。在这种情况下它非常低,如果Count属性足够便宜,可能是纳秒或两个。但该方法所做的实际工作也非常便宜。您的测试使其容易减慢20%。这种方法可以很好地嵌套在程序的关键路径上。方法越多,额外测试的相关性就越低。

答案 3 :(得分:1)

我永远不会抛出被调用方法引发的异常。

但是我会(并且做!)抛出提供更多信息的异常 - 为错误提供一些上下文。

诊断随机异常可能有些困难,特别是因为经常缺少信息......就像堆栈跟踪本身一样。

略微修改您的示例:

public OrderLine GetOrderLineint index)
{
    if (index < 0 || index >= _privateList.Count)
    {
        throw new ArgumentOutOfRangeException(
            "index",
            "No OrderLine available at index " + index.ToString());
    }

    return _privateList[index];
}

通过这种方式,您仍然可以获得足够的调试信息。