为什么在C#中捕获并重新抛出异常?

我正在查看可串行化DTO上的文章C# - 数据传输对象。

文章包含这段代码:

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

本文的其余部分看起来理智和合理(对于noob),但是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();
}

或者我错过了一些关于C#中错误处理的基础知识? 它几乎与Java相同(减去检查的异常),不是吗? ......也就是说,他们都精炼了C ++。

堆栈溢出问题重新抛出无参数捕获和不做任何事情之间的区别? 似乎支持我的观点,即尝试抛出是无效的。


编辑:

只是为了总结任何未来发现此线程的人...

不要

try {
    // Do stuff that might throw an exception
}
catch (Exception e) {
    throw e; // This destroys the strack trace information!
}

堆栈跟踪信息对于确定问题的根本原因至关重要!

try {
    // Do stuff that might throw an exception
}
catch (SqlException e) {
    // Log it
    if (e.ErrorCode != NO_ROW_ERROR) { // filter out NoDataFound.
        // Do special cleanup, like maybe closing the "dirty" database connection.
        throw; // This preserves the stack trace
    }
}
catch (IOException e) {
    // Log it
    throw;
}
catch (Exception e) {
    // Log it
    throw new DAOException("Excrement occurred", e); // wrapped & chained exceptions (just like java).
}
finally {
    // Normal clean goes here (like closing open files).
}

在较不具体的例外之前捕捉更具体的例外(就像Java一样)。


参考文献:

  • MSDN - 异常处理
  • MSDN - try-catch(C#参考)

  • 第一; 文章中的代码的做法是邪恶的。 throw ex会将异常中的调用堆栈重置为该throw语句的位置; 失去了关于实际创建异常的信息。

    第二,如果你正好赶上并重新抛出这样的,我看不出有任何的附加价值,代码示例上面会一样好(或者,考虑到throw ex位,甚至更好),而在try-catch。

    但是,有些情况下您可能想要捕捉并重新抛出异常。 记录可能是其中之一:

    try 
    {
        // code that may throw exceptions    
    }
    catch(Exception ex) 
    {
        // add error logging here
        throw;
    }
    

    不要这样做,

    try 
    {
    ...
    }
    catch(Exception ex)
    {
       throw ex;
    }
    

    你将失去堆栈跟踪信息...

    要么,

    try { ... }
    catch { throw; }
    

    要么

    try { ... }
    catch (Exception ex)
    {
        throw new Exception("My Custom Error Message", ex);
    }
    

    你可能想要重新抛出的原因之一是,如果你正在处理不同的例外情况,例如

    try
    {
       ...
    }
    catch(SQLException sex)
    {
       //Do Custom Logging 
       //Don't throw exception - swallow it here
    }
    catch(OtherException oex)
    {
       //Do something else
       throw new WrappedException("Other Exception occured");
    }
    catch
    {
       System.Diagnostics.Debug.WriteLine("Eeep! an error, not to worry, will be handled higher up the call stack");
       throw; //Chuck everything else back up the stack
    }
    

    C#(在C#6之前)不支持CIL“过滤的异常”,这是VB所做的,因此在C#1-5中,重新抛出异常的一个原因是您在catch()时没有足够的信息。以确定您是否想要实际发现异常。

    例如,在VB中你可以做

    Try
     ..
    Catch Ex As MyException When Ex.ErrorCode = 123
     .. 
    End Try
    

    ......它不会用不同的ErrorCode值处理MyExceptions。 在v6之前的C#中,如果ErrorCode不是123,则必须捕获并重新抛出MyException:

    try 
    {
       ...
    }
    catch(MyException ex)
    {
        if (ex.ErrorCode != 123) throw;
        ...
    }
    

    由于C#6.0可以像使用VB一样进行过滤:

    try 
    {
      // Do stuff
    } 
    catch (Exception e) when (e.ErrorCode == 123456) // filter
    {
      // Handle, other exceptions will be left alone and bubble up
    }
    
    链接地址: http://www.djcxy.com/p/14011.html

    上一篇: Why catch and rethrow an exception in C#?

    下一篇: How do I discover memory usage of my application in Android?