不鼓励简单地抓住System.Exception.相反,只应捕获"已知"异常.
现在,这有时会导致不必要的重复代码,例如:
try
{
WebId = new Guid(queryString["web"]);
}
catch (FormatException)
{
WebId = Guid.Empty;
}
catch (OverflowException)
{
WebId = Guid.Empty;
}
Run Code Online (Sandbox Code Playgroud)
我想知道:有没有办法捕获两个异常并且只WebId = Guid.Empty调用一次呼叫?
给出的例子相当简单,因为它只是一个GUID.但是想象一下你多次修改一个对象的代码,如果其中一个操作以预期的方式失败,你想要"重置"它object.但是,如果出现意外异常,我仍然希望将其提高.
这篇文章包括这段代码:
public static string SerializeDTO(DTO dto) {
try {
XmlSerializer xmlSer = new XmlSerializer(dto.GetType());
StringWriter sWriter = new StringWriter();
xmlSer.Serialize(sWriter, dto);
return sWriter.ToString();
}
catch(Exception ex) {
throw ex;
}
}
Run Code Online (Sandbox Code Playgroud)
本文的其余部分看起来很合理(对于菜鸟),但是try-catch-throw会抛出一个WtfException ... 这不完全等同于根本不处理异常吗?
人机工程学:
public static string SerializeDTO(DTO dto) {
XmlSerializer xmlSer = new XmlSerializer(dto.GetType());
StringWriter sWriter = new StringWriter();
xmlSer.Serialize(sWriter, dto);
return sWriter.ToString();
}
Run Code Online (Sandbox Code Playgroud)
或者我错过了C#中错误处理的基本内容?它与Java几乎相同(减去已检查的异常),不是吗?......也就是说,他们都改进了C++.
Stack Overflow问题重新抛出无参数捕获和不执行任何操作之间的区别?似乎支持我的观点,即try-catch-throw是一个无操作.
编辑:
只是为了总结未来发现这个主题的人...
不要
try {
// Do stuff that might throw an …Run Code Online (Sandbox Code Playgroud) 我有一个问题,源于我的伙伴以不同于我的方式做事.
这样做更好:
try
{
...
}
catch (Exception ex)
{
...
throw;
}
Run Code Online (Sandbox Code Playgroud)
或这个:
try
{
...
}
catch (Exception ex)
{
...
throw ex;
}
Run Code Online (Sandbox Code Playgroud)
他们做同样的事情吗?这个比那个好吗?
捕获异常并重新抛出异常时需要考虑哪些最佳实践?我想确保保留Exception对象InnerException和堆栈跟踪.以下代码块在处理此方式时是否存在差异?
try
{
//some code
}
catch (Exception ex)
{
throw ex;
}
Run Code Online (Sandbox Code Playgroud)
VS:
try
{
//some code
}
catch
{
throw;
}
Run Code Online (Sandbox Code Playgroud) 我有这个代码
try
{
//AN EXCEPTION IS GENERATED HERE!!!
}
catch
{
SqlService.RollbackTransaction();
throw;
}
上面的代码在此代码中调用
try
{
//HERE IS CALLED THE METHOD THAT CONTAINS THE CODE ABOVE
}
catch (Exception ex)
{
HandleException(ex);
}
作为参数传递给方法"HandleException"的异常包含堆栈跟踪中"throw"行的行号,而不是生成异常的实际行.任何人都知道为什么会发生这种情况?
编辑1 好的,谢谢大家的答案.我更改了内部捕获
catch(Exception ex)
{
SqlService.RollbackTransaction();
throw new Exception("Enrollment error", ex);
}
现在我在堆栈跟踪上有正确的行,但我不得不创建一个新的异常.我希望找到更好的解决方案:-(
EDIT2 也许(如果你有5分钟)你可以尝试这种情况,以检查你是否得到相同的结果,而不是很复杂的重新创建.
我有许多方法正在调用Delegate.DynamicInvoke.其中一些方法会进行数据库调用,我希望能够捕获一个SqlException而不是TargetInvocationException通过它的内部捕获并查找实际出错的方法.
我正在使用此方法重新抛出但它清除了堆栈跟踪:
try
{
return myDelegate.DynamicInvoke(args);
}
catch(TargetInvocationException ex)
{
Func<TargetInvocationException, Exception> getInner = null;
getInner =
delegate(TargetInvocationException e)
{
if (e.InnerException is TargetInvocationException)
return getInner((TargetInvocationException) e.InnerException);
return e.InnerException;
};
Exception inner = getInner(ex);
inner.PreserveStackTrace();
throw inner;
}
Run Code Online (Sandbox Code Playgroud)
这个PreserveStackTrace方法是我通过另一个帖子修复的扩展方法(我不知道它实际上做了什么).但是,这似乎不会保留跟踪:
public static void PreserveStackTrace(this Exception e)
{
var ctx = new StreamingContext(StreamingContextStates.CrossAppDomain);
var mgr = new ObjectManager(null, ctx);
var si = new SerializationInfo(e.GetType(), new FormatterConverter());
e.GetObjectData(si, ctx);
mgr.RegisterObject(e, 1, si);
mgr.DoFixups();
}
Run Code Online (Sandbox Code Playgroud) c# exception-handling stack-trace targetinvocationexception inner-exception
重复:在C#中,如何在不丢失堆栈跟踪的情况下重新抛出InnerException?
我有一些操作,我在后台线程上异步调用.有时,事情变坏了.当发生这种情况时,我倾向于得到一个TargetInvocationException,这在适当的时候是没用的.我真正需要的是TargetInvocationException的InnerException,如下所示:
try
{
ReturnValue = myFunctionCall.Invoke(Target, Parameters);
}
catch (TargetInvocationException err)
{
throw err.InnerException;
}
Run Code Online (Sandbox Code Playgroud)
这样,我的调用者就会发生真正的异常.问题是,throw语句似乎重置了堆栈跟踪.我想基本上重新抛出内部异常,但保留它最初的堆栈跟踪.我怎么做?
澄清: 我只想要内部异常的原因是这个类试图"抽象"这些函数(由调用者提供的委托)在其他线程上运行的事实.如果存在异常,则可能与在后台线程上运行无关,并且调用者真的希望堆栈跟踪进入其委托并找到真正的问题,而不是我调用的调用.
我有一个方法调用SQLServer函数对表执行自由文本搜索.该函数有时会在第一次调用时导致SQLException:"全文查询字符串的单词分解超时".所以我通常想重试该请求,因为它会在后续请求中成功.构造重试逻辑的好方法是什么.目前我有以下内容:
var retryCount = 0;
var results = new List<UserSummaryDto>();
using (var ctx = new UsersDataContext(ConfigurationManager.ConnectionStrings[CONNECTION_STRING_KEY].ConnectionString))
{
for (; ; )
{
try
{
results = ctx.SearchPhoneList(value, maxRows)
.Select(user => user.ToDto())
.ToList();
break;
}
catch (SqlException)
{
retryCount++;
if (retryCount > MAX_RETRY) throw;
}
}
}
return results;
Run Code Online (Sandbox Code Playgroud) 我们有一项服务,它将在应用程序域级别(通过Log4net)记录未处理的异常.
我们记录了:
2014-01-28 16:49:19,636 ERROR [49] FeedWrapperService - 未处理的System.NullReferenceException:未将对象引用设置为对象的实例.
此异常没有堆栈跟踪.如果不对异常对象做一些疯狂的事情,这怎么可能呢?
我们的处理代码:
AppDomain.CurrentDomain.UnhandledException += LogAnyExceptions;
private void LogAnyExceptions(object sender, UnhandledExceptionEventArgs e)
{
log.Error("unhandled", (Exception)e.ExceptionObject);
throw (Exception)e.ExceptionObject;
}
Run Code Online (Sandbox Code Playgroud)
在我看来,重新抛出这一点毫无意义,因为AppDomain无论如何都会随着进程而下降,但我认为它不会影响我们的情况.
Windows应用程序事件查看器也只显示此null ref异常并且没有跟踪.
我已经测试了异常处理程序日志记录,它成功记录了堆栈跟踪和任何内部异常.如果它被我们的代码抛出,我们会看到堆栈跟踪.如果它被第三方c#库抛出,那么,我们再次看到至少一个方法的堆栈跟踪(无论是否是重新抛出的异常).在这里,我们看到一个没有堆栈跟踪的托管异常.我不知道这是怎么可能的.
查看反编译的第三方库,它与非托管代码进行对话,引发此异常的事件可能在非托管域中,但是如果没有堆栈跟踪,这种情况怎么会导致托管的空引用异常?
这个问题的原因是间歇性的.我们已经将这段代码在生产中运行了几个月,并且看过它曾经这样做过.这非常怪异.
普遍的共识是,应该将负责此类问题的系统推送到子进程中,这样我们就可以处理问题并安全地自动重启,但知道发生了什么事情会很好.
编辑以包含以下评论信息:
我的异常不是标准的重新抛出,因为堆栈跟踪是null或空.它没有重新投掷方法的名称.进一步挖掘,Exception类可以从序列化信息构造,看起来序列化信息可能包含堆栈跟踪的空字符串,并且可能创建它而不会导致其他错误.我想它可能来自那里,但我不知道它是如何起源的.
我想动态调用一个MethodInfo对象,并且从它内部抛出的任何异常向外传递,就像它被正常调用一样.
我看来有两种选择.它们概述如下.
选项1保持抛出的异常的类型MyStaticFunction,但是StackTrace因为它而被破坏throw.
选项2维护StackTrace异常,但异常的类型始终如此TargetInvocationException.我可以提取InnerException它的类型,但这意味着我不能写这个例子:
try { DoDynamicCall(); }
catch (MySpecialException e) { /* special handling */ }
Run Code Online (Sandbox Code Playgroud)
选项1:
void DoDynamicCall()
{
MethodInfo method = /*referencing MyClass method void MyStaticFunction(int x)*/;
try
{
method.Invoke(null, new object[] { 5 });
}
catch (TargetInvocationException e)
{
throw e.InnerException;
}
}
Run Code Online (Sandbox Code Playgroud)
选项2:
void DoDynamicCall()
{
MethodInfo method = /*referencing MyClass method void MyStaticFunction(int x)*/;
method.Invoke(null, new …Run Code Online (Sandbox Code Playgroud) c# ×10
.net ×4
exception ×4
stack-trace ×3
try-catch ×2
linq ×1
reflection ×1
rethrow ×1
sql ×1