返回元组<bool,string =“”>而不是抛出异常()?</bool,>

时间:2012-03-21 18:03:47

标签: c# exception return-value

我有一个方法Foo()做了一些努力工作,在UI层我有一个按钮来调用该方法。
我想要做的就是调用方法并在Foo()方法出现问题时显示消息框。

我有两种选择来设计方法签名:

1.Tuple

Tuple<bool, string> Foo()  
{  
    if(!DoHardWorkA()) return Tuple.New(false, "cannot do hardwork A");  
    if(!DoHardWorkB()) return Tuple.New(false, "cannot do hardwork B");  

    return Tuple.New(true, String.Empty);
}

2.Exception

void Foo()
{
    if(!DoHardWorkA()) throw new ProgramSpecificException("cannot do hardwork A");
    if(!DoHardWorkB()) throw new ProgramSpecificException("cannot do hardwork B");

    return Tuple.New(true, String.Empty);
}

DoHardWorkA()和DoHardWorkB()都是我无法控制它们的外部方法,它们返回true / false表示结果。

从逻辑上讲,我认为我应该使用选项2,因为它们确实是例外;但为了保持一致性,我想选择选项1.

您更喜欢哪一个,为什么?

5 个答案:

答案 0 :(得分:3)

抛出异常并以一致的方式处理它会更好。

如果Foo由于任何其他原因而失败,那么它也将被处理。假设一个场景。

void UIMethod()
{
   Tuple<Result, Error> ret = Foo();
   if(ret.Error)
     MessageBox.Show(ret.Error);
}

现在由于需求的变化,你必须在Foo之前​​调用另一个方法,它也可以抛出异常。然后它变得复杂。

这样做要容易得多。

void UIMethod()
{
   try{  
       MethodBeforeFoo();
       var ret = Foo();
    }
   catch(Exception ex)
    {
       MessageBox.Show(ex.Message); 
    }

}

答案 1 :(得分:1)

这实际上取决于你的需要。像这样修改你的代码,它也会处理未处理的异常。

   Tuple<bool, string> Foo()  
{  
try
{
    if(!DoHardWorkA()) return Tuple.New(false, "cannot do hardwork A");  
    if(!DoHardWorkB()) return Tuple.New(false, "cannot do hardwork B");  

    return Tuple.New(true, String.Empty);
}
catch
{
  return Tuple.New(false, "cannot do hardwork A"); 
}

}

答案 2 :(得分:1)

如果您正在做的就是调用这些外部方法来完成一些工作,而您正在编写的这个方法是它们的包装,那么为什么抛出异常,“处理”方法中的问题并继续,抛出和处理例外很多很多次更贵

在你的特定情况下,你所做的只是做一些工作,并显示一个消息框来显示它是否正确执行,所以我选择了1

请注意,如果您只是捕获异常而不是展开堆栈,则成本相当低。当您展开堆栈时,它只是昂贵的,例如ex.ToString()ex.StackTrace

答案 3 :(得分:0)

我做过的一次是成功时返回null或失败时返回错误消息。异常是不合适的,因为失败是可能的,而其他开发人员喜欢运行“在抛出异常时中断”

String Foo()  
{  
    if(!DoHardWorkA()) return "cannot do hardwork A";
    if(!DoHardWorkB()) return "cannot do hardwork B";

    return null;
}

答案 4 :(得分:0)

使用异常有一个建议,即您可以(*)比建议的元组返回值更容易区分原因。要弄清楚在使用元组时出现什么样的错误,你必须解释字符串值,这很容易出错。使用异常,您可以根据异常的类型确定错误类型。

(*)取决于如何使用异常 - 如果你一直抛出一般的异常,它将不会有所不同

当然你可以在元组中使用一个整数来表示问题的类型,但是错误类型的数值不像Exception类型那样具有描述性(再次假设你没有使用一般类型,比如除外)。