我正在看关于可序列化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;
    }
}

文章的其余部分看起来理智而合理(对于新手来说),但是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++。

堆栈溢出问题重新抛出无参数catch和什么都不做之间的区别?这似乎支持了我的观点,试着接球是不行的。


编辑:

只是为了给将来找到这条线索的人做个总结…

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

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

DO

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#参考)


当前回答

使用catch-throw的一个可能原因是禁用堆栈较深处的任何异常过滤器(随机旧链接)。当然,如果这是他们的意图,肯定会有评论这么说。

其他回答

我使用如下代码的主要原因:

try
{
    //Some code
}
catch (Exception e)
{
    throw;
}

是我可以在catch中有一个断点,它有一个实例化的异常对象。在开发/调试时,我经常这样做。当然,编译器会对所有未使用的e给出警告,理想情况下,应该在发布版本之前删除它们。

不过,在调试过程中它们很好用。

虽然许多其他答案提供了很好的示例,说明为什么您可能希望捕获重抛出异常,但似乎没有人提到“最终”场景。

举个例子,你有一个方法,你在其中设置了游标(例如一个等待游标),该方法有几个出口点(例如if () return;),你想确保游标在方法结束时被重置。

为此,您可以将所有代码包装在try/catch/finally中。在最后将光标设置回右光标。这样就不会隐藏任何有效的异常,在catch中重新抛出它。

try
{
    Cursor.Current = Cursors.WaitCursor;
    // Test something
    if (testResult) return;
    // Do something else
}
catch
{
    throw;
}
finally
{
     Cursor.Current = Cursors.Default;
}

这取决于您在catch块中所做的事情,以及您是否希望将错误传递给调用代码。

你可能会说Catch io。FileNotFoundExeption ex,然后使用替代文件路径或类似的,但仍然抛出错误。

同样,使用Throw而不是Throw Ex可以让你保持完整的堆栈跟踪。Throw ex从Throw语句重新启动堆栈跟踪(我希望这有意义)。

当您为库或dll编程函数时,这可能很有用。

此重抛出结构可用于有目的地重置调用堆栈,以便从函数本身获取异常,而不是从函数内部的单个函数中查看抛出的异常。

我认为这样做只是为了让抛出的异常更清晰,并且不会进入库的“根”。

使用catch-throw的一个可能原因是禁用堆栈较深处的任何异常过滤器(随机旧链接)。当然,如果这是他们的意图,肯定会有评论这么说。