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:当然可以。记录异常是获取调试信息的一种方法。但是,如果您在任何地方都尝试/捕获/重试,那么很可能会多次记录相同的异常。随着应用程序的增长,调试它将变得越来越困难。