我有一个问题,源于我的伙伴以不同于我的方式做事.
这样做更好:
try
{
...
}
catch (Exception ex)
{
...
throw;
}
Run Code Online (Sandbox Code Playgroud)
或这个:
try
{
...
}
catch (Exception ex)
{
...
throw ex;
}
Run Code Online (Sandbox Code Playgroud)
他们做同样的事情吗?这个比那个好吗?
我通过反射调用一种可能导致异常的方法.如何在没有包装器反射的情况下将异常传递给调用者?
我正在重新抛出InnerException,但这会破坏堆栈跟踪.
示例代码:
public void test1()
{
// Throw an exception for testing purposes
throw new ArgumentException("test1");
}
void test2()
{
try
{
MethodInfo mi = typeof(Program).GetMethod("test1");
mi.Invoke(this, null);
}
catch (TargetInvocationException tiex)
{
// Throw the new exception
throw tiex.InnerException;
}
}
Run Code Online (Sandbox Code Playgroud) 在保持我同事的代码甚至是自称是高级开发人员的人的同时,我经常看到以下代码:
try
{
//do something
}
catch
{
//Do nothing
}
Run Code Online (Sandbox Code Playgroud)
或者有时他们将日志信息写入日志文件,如下面的try catch块
try
{
//do some work
}
catch(Exception exception)
{
WriteException2LogFile(exception);
}
Run Code Online (Sandbox Code Playgroud)
我只是想知道他们所做的是最佳做法吗?这让我感到困惑,因为在我看来,用户应该知道系统会发生什么.
请给我一些建议.
有什么区别
try { ... }
catch{ throw }
Run Code Online (Sandbox Code Playgroud)
和
try{ ... }
catch(Exception e) {throw new Exception(e.message) }
Run Code Online (Sandbox Code Playgroud)
无论第二个显示消息?
这是一个后续问题,"throw"和"throw ex"之间有区别吗?
有没有办法提取新的错误处理方法而不重置堆栈跟踪?
[编辑] 我将尝试"内部方法"和Earwicker提供的另一个答案,看看哪一个可以更好地标记答案.
我想知道将异常从一种方法传递给另一种方法的正确方法是什么.
我正在开发一个分为Presentation(web),Business和Logic层的项目,并且需要在链中传递错误(例如SqlExceptions)以在出现问题时通知Web层.
我见过3种基本方法:
try
{
//error code
}
catch (Exception ex)
{
throw ex;
}
Run Code Online (Sandbox Code Playgroud)
(只是重新抛出)
try
{
//error code
}
catch (Exception ex)
{
throw new MyCustomException();
}
Run Code Online (Sandbox Code Playgroud)
(抛出自定义异常,以便不传递对数据提供程序的依赖关系)
然后简单地说
//error code
Run Code Online (Sandbox Code Playgroud)
(根本不做任何事情,让错误自己冒出来)
当然,catch块中也会发生一些日志记录.
我更喜欢3号,而我的同事使用方法1,但我们都不能真正激励为什么.
使用每种方法有哪些优点/缺点?有一种我不知道的更好的方法吗?有没有被接受的最佳方式?
在C#中,throw ex几乎总是错误的,因为它会重置堆栈跟踪.
我只是想知道,这有什么现实世界吗?我能想到的唯一原因是隐藏你的封闭库的内部,但这是一个非常薄弱的原因.除此之外,我从未在现实世界中遇到过.
编辑:我的意思是throw ex,就像抛出完全相同的异常,但是使用空堆栈跟踪,就像完全错误一样.我知道throw ex必须作为一种语言结构存在,以允许抛出一个不同的异常(throw new DifferentException("ex as innerException", ex)),并且只是想知道是否存在一个throw ex没有错误的情境.
我们有一项服务,它将在应用程序域级别(通过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类可以从序列化信息构造,看起来序列化信息可能包含堆栈跟踪的空字符串,并且可能创建它而不会导致其他错误.我想它可能来自那里,但我不知道它是如何起源的.
我发现如果我捕获异常e,e.innerException可能为null.
在catch块的任何可能情况下,e.StackTrace也可能为null吗?
try {
}
catch(Exception e)
{
//can e.StackTrace be null here?
}
Run Code Online (Sandbox Code Playgroud) internal static string ReadCSVFile(string filePath)
{
try
{
...
...
}
catch(FileNotFoundException ex)
{
throw ex;
}
catch(Exception ex)
{
throw ex;
}
finally
{
...
}
}
//Reading File Contents
public void ReadFile()
{
try
{
...
ReadCSVFile(filePath);
...
}
catch(FileNotFoundException ex)
{
...
}
catch(Exception ex)
{
...
}
}
Run Code Online (Sandbox Code Playgroud)
在上面的代码示例中,我有两个函数ReadFile和ReadCSVFile.
在ReadCSVFile中,我得到FileNotFoundExexoon类型的异常,它被catch(FileNotFoundException)块捕获.但是当我抛出此异常以捕获ReadFile()函数的catch(FileNotFoundException)时,它会捕获catch(Exception)块而不是catch(FileNotFoundException).而且,在调试时,ex的值表示为Object Not Initialized.如何将调用函数的异常抛出到调用函数的catch块而不丢失内部异常或至少发出异常消息?