c#在设计用于处理异常和保留stacktrace的方法中重新抛出异常

c#在设计用于处理异常和保留stacktrace的方法中重新抛出异常,c#,exception,exception-handling,C#,Exception,Exception Handling,我想编写一个处理异常的方法,该方法将在catch块中调用。根据传递的异常的类型,该异常要么作为新异常的内部异常传递,要么只是重新抛出。如何在第二种情况下保留堆栈跟踪 例如: public void TestMethod() { try { // can throw an exception specific to the project or a .Net exception SomeWorkMethod() } catch(E

我想编写一个处理异常的方法,该方法将在
catch
块中调用。根据传递的异常的类型,该异常要么作为新异常的内部异常传递,要么只是重新抛出。如何在第二种情况下保留堆栈跟踪

例如:

public void TestMethod()
{
    try
    {
        // can throw an exception specific to the project or a .Net exception 
        SomeWorkMethod() 
    }
    catch(Exception ex)
    {
        HandleException(ex);
    }
}

private void HandleException(Exception ex)
{
    if(ex is SpecificException)
         throw ex; //will not preserve stack trace...
    else
         throw new SpecificException(ex);
}
我不想做的是,因为该模式在许多地方重复,并且不会进行因式分解:

try
{
    SomeWorkMethod();
}
catch(Exception ex)
{
    if(ex is SpecificException)
         throw;
    else
         throw new SpecificException(ex);
}

您需要使用
throw
而不指定异常来保留堆栈跟踪。这只能在
catch
块内完成。您可以从
HandleException
返回,而不引发原始异常,然后立即使用
throw

public void TestMethod()
{
    try
    {
        // can throw an exception specific to the project or a .Net exception 
        SomeWorkMethod() 
    }
    catch(Exception ex)
    {
        HandleException(ex);
        throw;
    }
}

private void HandleException(Exception ex)
{
    if(ex is SpecificException)
         return;
    else
         throw new SpecificException(ex);
}
只要您只使用
is
对异常进行分类,首选的方法是使用两个catch块:

public void TestMethod()
{
    try
    {
        // can throw an exception specific to the project or a .Net exception 
        SomeWorkMethod() 
    }
    catch (SpecificException)
    {
        throw;
    }
    catch(Exception ex)
    {
        throw new SpecificException(ex);
    }
}
使用C#6.0,您还可以在时使用
,以使异常得以解决:

public void TestMethod()
{
    try
    {
        // can throw an exception specific to the project or a .Net exception 
        SomeWorkMethod() 
    }
    catch(Exception ex) when (!(ex is SpecificException))
    {
        throw new SpecificException(ex);
    }
}

也许你可以试试这个

if(ex.Gettype() == typeof(SpecificException))

实际上,在.Net4.5中有一种非常好的方法可以使用:


为什么不使用“if(!HandleException(ex))throw;”之类的词呢。我知道这并不完全是您想要的,但它很简单,不像第二个示例那样重要。为什么不为
特定异常
单独设置一个捕获点呢
catch(specifiception e){throw;}
就我所见,这并没有真正解决这个问题。或者至少如果它真的这样做了,它可以做一些额外的解释来说明如何做。这在很多方面都是错误的。为什么要使用反射?如果
ex
继承自
SpecificException
?为什么不使用像
is
(哪个OP已经在做了)这样的常规语言结构呢?谢谢spender,你非常准确地回答了我的问题。然而,我并没有注意到有很多方法可以通过使用许多捕捉块来实现我所需要的(Sefe的第二个答案)。@SylvainB。的确公认的答案肯定更适合您的需要。你的问题提醒了我,我很久以前就看到过这个,所以它似乎值得分享。
void Main()
{
    try
    {
        throw new Exception(); //appears to be thrown from here
    }
    catch(Exception ex)
    {
        ThrowEx(ex);
    }

}
public void ThrowEx(Exception ex)
{
    if(someCondition)
    {
        //we're in the scope of a `catch` and the exception
        //is "active", so the exception with original stack-trace
        //can be re-thrown with
        ExceptionDispatchInfo.Capture(ex).Throw();
        //the following line is unreachable, but the compiler doesn't realise
        //so we can "tell" the compiler that this branch ends in an exception
        //and avoid having to return anything in the non-void case
        throw new Exception(); 
    }
}