在方法重载中抛出参数异常

时间:2012-09-30 00:14:23

标签: c# exception

我最近刚开始研究使用它们的异常和最佳实践,我想知道这样做的正确方法是什么:

假设有一个包含多个参数的方法。并且这个方法有多个重载,参数较少,通过提供默认值来调用主要实现。

我是否在每次重载中验证所有参数?

public string Translate(string text)
{
    if (String.IsNullOrEmpty(text))
        throw new ArgumentNullException();

    return Translate(text, "english");
}

public string Translate(string text, string language)
{
    if (String.IsNullOrEmpty(text))
        throw new ArgumentNullException();

    // Do the rest of the work
    // ...
}

我是否重新抛出异常?

public string Translate(string text)
{
    try
    {
        return Translate(text, "english");
    }
    catch
    {
        throw;
    }
}

public string Translate(string text, string language)
{
    if (String.IsNullOrEmpty(text))
        throw new ArgumentNullException();

    // Do the rest of the work
    // ...
}

或者我是否完全删除异常并在重载中尝试/捕获块?

public string Translate(string text)
{
    return Translate(text, "english");
}

public string Translate(string text, string language)
{
    if (String.IsNullOrEmpty(text))
        throw new ArgumentNullException();

    // Do the rest of the work
    // ...
}

另外,这两种方法的文档怎么样?

(使用C#XML注释。特别是在我放置<exception>元素的地方。)


我确实意识到这是一个次要的话题,但是,每当遇到这种情况时(我实际上经常这样),我一直在想。

4 个答案:

答案 0 :(得分:3)

Optional arguments在某种程度上解决了这个问题,那么你只有一种方法:

public string Translate(string text, string language="english")

有一些quirks with optional arguments值得了解。

  

默认值被“烘焙”到调用代码中。 [...]   这可能导致公共竞争的问题 - 如果   您更改库中的默认值,但不重新编译   调用代码,然后调用代码仍将调用您的方法   使用旧的默认值。这绝对是你需要的   在使用可选参数设计API时要考虑。

答案 1 :(得分:2)

让我们列出你所拥有的三个选项的优缺点并决定:

<强> 1。我是否在每次重载中验证所有参数?

优点:你知道字符串是否为空然后抛出异常。经典又好。 缺点:您在抛出异常后调用第二个函数,因为知道由于字符串为空而发生异常或为null。

所以我会放弃这个想法。

<强> 2。我是否会重新抛出异常?

优点:1)这是我个人的最爱,就像你一行一行,这就是发生的事情。调用第二个函数,抛出异常并捕获调用函数的catch并完成其他一些工作。        2)使用throw关键字而不是throw ex确保堆栈跟踪完好无损。        3)在呼叫部分处理异常是最佳做法。

缺点:请帮助我。我找不到任何。

第3。或者我是否完全删除异常并在重载中尝试/捕获块?

优点:尝试catch不在调用函数中使用。不完全是专业人士,但是,它减少了一些代码。 缺点:没有正确处理,最好的做法是说我们应该在调用函数处理异常。

我认为第二种选择是最好的选择。

还有一个我想分享的链接非常有帮助

Best Practice : Code Project Link

请告诉我。

答案 2 :(得分:0)

实际上这是一个传统的问题,在加密中已经被认为最好用所谓的静态工厂方法 - 通常命名为getInstance() - 在其中你将很多问题重构到一个地方。 它变得相当讨厌,试图躲过你得到的所有响应,但从不通过什么都不做而抛弃异常,只是为了最终用例而大大简化,要么在日志中保留一些东西,要么快速失败,要么确保你在学生环境。

答案 3 :(得分:0)

我在这里回答很晚,但我想指出,如果你正确地做过载,这真的不应该成为一个问题。重载的正确方法是将所有功能代码放在一个接受所有可能的参数的方法中:

public string Foo(string param1, string param2, string param3)
{
    // do work here, including throwing argument exceptions
}

然后,您的重载应使用默认值填充缺少的参数:

public string Foo(string param1)
{
    return Foo(param1, null, null);
}

public string Foo(string param1, string param2)
{
    return Foo(param1, param2, null);
}

基于此,您只需处理主要重载中的异常(实际执行内容的异常)。请记住,您的重载本身不应导致引发异常。例如,如果通过抛出param3强制ArgumentNullException被强制为非空,那么您不应该为该参数传递null,而是可以作为一个实际的字符串。默认值。

无论调用哪个重载,都会调用主重载(带有throws),并且它抛出的任何异常都会冒泡到原始代码。换句话说,你不需要做类似的事情:

public string Foo(string param1)
{
    if (param1 == null)
    {
        throw new ArgumentNullException(nameof(param1));
    }

    return Foo(param1, "param2 default", "param3 default");
}

因为主要重载已经具有该检查,并且如果param1为空则将抛出。