Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/285.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 有太多尝试捕捉的问题_C#_.net_C# 4.0 - Fatal编程技术网

C# 有太多尝试捕捉的问题

C# 有太多尝试捕捉的问题,c#,.net,c#-4.0,C#,.net,C# 4.0,是否可以编写类似outType的方法?TryDo(func,out exception,params)调用func(arg1,arg2,arg3,…)哪个参数包含arg1,arg2,arg3,…,然后返回func返回值,如果发生任何异常,返回null并设置异常 通过另一个函数签名可以更好地实现这一点吗 比如我有 stringfoo1(inti){return i.ToString()} voidfoo2(int[]a){抛出新异常();} 然后打电话 string t=TryDo(Foo1,ou

是否可以编写类似
outType的方法?TryDo(func,out exception,params)
调用
func(arg1,arg2,arg3,…)
哪个参数包含
arg1,arg2,arg3,…
,然后返回func返回值,如果发生任何异常,返回null并设置异常

通过另一个函数签名可以更好地实现这一点吗

比如我有
stringfoo1(inti){return i.ToString()}

voidfoo2(int[]a){抛出新异常();}

然后打电话

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);
是的,有可能


但是为什么要以这种方式返回可能的异常呢?您可以进一步抛出并在需要的位置进行处理。

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

以下是一段引用自:

避免使用out或reference参数。

使用定义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; } }
}
class CallResult,其中T:class{
public CallResult(T result){result=result;}
公共调用结果(异常异常){Exception=Exception;}
公共T结果{get;私有集;}
公共异常异常{get;private set;}
公共布尔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);
CallResult-TryDo(Func-action,params-Object[]args),其中T:class{
试一试{
返回新的CallResult(操作(args));
}
捕获(例外情况除外){
返回新的CallResult(ex);
}
}
你可以这样称呼它:

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);
var callResult=TryDo(Foo1,4,2,new OtherClass());
如果(!callResult.IsSuccessful)
检查(callResult.Exception);

但是,如果您打算在
Examine
方法中重新显示异常,并取消stacktrace,您应该重新考虑您的方法

是的,但您为什么要这样做

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; }
}

您提出的问题表明您误解了应如何处理异常。到处使用try/catch可能会产生不希望的结果,并使应用程序更难调试

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

  • 您可以处理异常并返回承诺的结果
  • 捕获特定于层的异常,并将其替换为更一般的异常(
    SqlException
    ->
    DataSourceException
  • 在顶层,一切都可以
  • 线程中的“全部捕获”是正常的(因为线程中未捕获的异常将使应用程序崩溃)
  • 更多信息请访问我的博客:

    更新


    请不要使用
    抛出ex
    。您正在销毁原始调用堆栈,因此隐藏了异常最初引发的位置<代码>抛出是你的小狗。无论何时何地使用它。

    如果您有太多的try…catch(我不明白为什么),您可以使用AOP来集中异常处理

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


    如果代码中的try/catch块太多,很可能是做错了什么。您应该只捕获实际可以处理的异常,并让所有其他异常传播。+1@Brian Rasmussen。另外,请注意,如果处理来自单个方法的多个异常,则捕获不必嵌套。例如:
    尝试{/*file i/o*/}catch(AccessDenied ex){}catch(FileNotFound ex){}catch(IOException ex){}//etc
    (如果你在做某种类型的i/o,如果稳健性很重要,你总是会有很多错误处理)@brian:如果我确定异常应该在那之后传播,我会再次抛出它,不要试图通过删除它来回答问题。@HPT:你能给我们一个问题中“太多尝试捕捉”的例子吗?它只返回int!一个返回字符串或类的函数怎么样?d没有
    Invoke()
    它有
    DynamicInvoke()
    通常是的。
    bool测试(参数,输出结果)模式几乎是我在C#中所知道的唯一一个具有out参数的行之有效的最佳实践。@马丁:这里只有你一个人试图解决这个问题!tnx,如果这里没有更好的解决方案,马丁:为什么要避免使用out参数?
    out
    参数在用户空间中很容易出错,通常不遵循行业标准的C#代码设计指南。使用泛型类型
    System对Func编译错误。Func
    需要1个类型参数如果需要,我会记录异常调试。
    抛出当前在上下文中引发异常,而不重置调用堆栈。这在许多调试场景中非常有用。@HPT:当然可以。记录异常是获取调试信息的一种方法。但是,如果您在任何地方都尝试/捕获/重试,那么很可能会多次记录相同的异常。随着应用程序的增长,调试它将变得越来越困难。