2012-09-30 9 views
0

我最近刚刚开始考虑例外情况及其使用的最佳做法,我不知道什么是这样做的正确方法:在方法抛出异常的说法重载

假设有多个参数的方法。这个方法有多个重载参数,通过提供默认值来调用主实现。

我是否验证每个超载中的所有参数?

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 
    // ... 
} 

还是我完全处于超负荷下降例外和try/catch块?

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>元素。)


我也知道这是一个小的话题,不过,我一直在想,每次我遇到这种情况(这实际上经常是)。

+1

可选参数以某种方式解决这个问题,只有一种方法: public string Translate(string text,string language =“english”) –

+0

哦,哇,我已经用C#编程了一年多了,而且我真的有不知道这是可能的。 – Lucius

+0

我写它作为答案,那么现在有点累了,并不真正知道它是否是你的问题的答案。 –

回答

3

Optional arguments解决这个的方式,那么你只有一个方法:

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

有一些quirks with optional arguments是很好的了解。

默认值被“烘焙成”调用代码。 这可能会导致暴露公共常量的问题相同 - 如果 您更改库中的默认值,但不重新编译 调用代码,则调用代码仍然会调用您的方法( s) 与旧的默认值。这绝对是您在使用可选参数设计API时需要考虑的因素。

+0

这绝对可以解决上述例子中的问题。不过,是否有可能想到一种情况,哪里不能使用可选参数?例如,如果一些额外的工作需要你有一个额外的方法。那么这个问题仍然是相关的。 – Lucius

+0

是的,这就是为什么我先写它作为评论,不知道你是否想为你的特定情况或一般情况提供解决方案。 –

0

其实这是一个传统的问题在什么在加密与所谓静态工厂方法为最好的做法得到认可 - 通常命名为getInstance() - 在你重构了很多问题到一个地方。 它试图通过你所得到的所有反应来讨论它,但从来不会抛弃异常,只是为了最终用例而大大简化,并且保持日志中的某些内容和快速失败,或者确保你是在学生的环境中。

2

让使你得到了,并决定这三个选项的利弊清单:

1.我确认所有的参数在每一个过载?

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

所以我会放弃这个想法。

2.不要我重新抛出异常?

优点:1)这是我个人最喜欢的,如果你一行一行,这是发生了什么。第二个函数被调用,并且引发异常并捕获调用函数的catch并完成其他一些工作。 2)使用throw关键字代替throw ex确保你的堆栈跟踪是完整的。 3)处理呼叫部分的异常是最佳做法。

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

3.还是我完全处于超负荷下降例外和try/catch块?

优点:尽量捕不调用函数中使用。不完全是一个优点,但呃,它减少了一些代码。 缺点:正确的处理不存在,最好的做法是我们应该在调用函数中处理异常。

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

也有一个链接我想和大家分享这是真正有用的

Best Practice : Code Project Link

请让我知道。

+0

谢谢你的回答。不过,我并不真正了解(1)中的缺点。至于(3):如果我不想对异常做任何事情,只是重新抛出它,使用try/catch似乎毫无意义。 – Lucius

0

我来不及回答在这里,但我想指出的是,如果你正在做正确的重载,这实在不应该是一个问题。超载到正确的方法是把所有的功能代码中接受所有可能的PARAMS的方法:

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

然后,你重载应填写失踪默认值PARAMS:基于

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为null。