尝试捕获的问题太多了

时间:2010-12-20 13:17:08

标签: c# .net c#-4.0

是否可以编写outType? TryDo(func, out exception, params)方法,调用func(arg1,arg2,arg3,...),其中params包含arg1,arg2,arg3,...,然后返回func返回值,如果发生任何异常,则返回null并设置异常?

这可以通过其他功能签名更好地完成吗?

例如我有 string Foo1(int i) { return i.ToString()}

void Foo2(int[] a) {throw new Exception();}

然后致电

string t = TryDo(Foo1, out ex, {i});

TryDo(Foo2, out ex, {});

-----------编辑------------------

        string t;
        SomeClass c;
        try
        {
            t = Foo1(4, 2, new OtherClass());
        }
        catch (Exception ex)
        {
            Log(ex);
            if (/*ex has some features*/)
                throw ex;
        }

        try
        {
            Foo2();
        }
        catch (Exception ex)
        {
            Log(ex);
            if (/*ex has some features*/)
                throw ex;
        }
        .
        .
        .

我想这样做。

        string t = TryDo(Foo1, out ex, {4, 2, new OtherClass());
        Examine(ex);
        SomeClass c = TryDo(Foo2, out ex, {});
        Examine(ex);

5 个答案:

答案 0 :(得分:3)

您所询问的内容表明您误解了应如何处理异常。在任何地方使用try / catch都会产生不希望的结果,并使您的应用程序更难调试。

简而言之,仅在以下情况下处理异常:

  1. 您可以处理异常并返回承诺的结果
  2. 捕获图层特定的例外情况并将其替换为更常见的例外情况(SqlException - > DataSourceException
  3. 在顶层抓住一切正常
  4. 在线程中捕获一切正常(因为线程中未捕获的异常会使您的应用程序崩溃)
  5. 我的博客中的更多信息:http://blog.gauffin.org/2010/11/do-not-catch-that-exception/

    <强>更新

    不要使用throw ex。您正在销毁原始调用堆栈,因此隐藏了最初抛出异常的位置。 throw;是你的小狗。随时随地使用它。

答案 1 :(得分:2)

是的,这是可能的。

但是你为什么要以这种方式返回一个可能的例外?你可以进一步投入并在需要的地方进行处理。

答案 2 :(得分:2)

除非绝对必要,否则我会避免使用out参数。

以下是Design Guidelines for Developing Framework Libraries

的引用
  

避免使用或引用参数。

     

使用定义out或reference参数的成员需要开发人员理解指针,值类型和引用类型之间的细微差别,以及out和reference参数之间的初始化差异。

您可以创建一个包含通话结果的返回类型:

class CallResult<T> where T : class {
  public CallResult(T result) { Result = result; }
  public CallResult(Exception exception) { Exception = exception; }
  public T Result { get; private set; }
  public Exception Exception { get; private set; }
  public Boolean IsSuccessful { get { return Exception == null; } }
}

您的方法可以像这样实现:

CallResult<T> TryDo<T>(Func<Object[], T> action, params Object[] args) where T : class {
  try {
    return new CallResult<T>(action(args));
  }
  catch (Exception ex) {
    return new CallResult<T>(ex);
  }
}

您可以这样称呼它:

var callResult = TryDo<String>(Foo1, 4, 2, new OtherClass());
if (!callResult.IsSuccessful)
  Examine(callResult.Exception);

但是,如果您打算在Examine方法中重新抛出异常而忽略堆栈跟踪,那么您应该重新考虑您的方法

答案 3 :(得分:0)

是的,但你为什么要这样呢?

int? TryDo(delegate d, out Exception e, params object[] par)  
{
   try
   {
      int res = d.Invoke(par);
      e = null;
      return res;
   }  
   catch(Exception ex) { e = ex; return null; }
}

答案 4 :(得分:0)

如果你有太多尝试... catch(我不明白为什么)你可以去AOP集中处理异常。

您可以在下面找到解释如何使用它的链接:

http://www.codeproject.com/KB/architecture/ExceptionHandlingWithAOP.aspx