1. ホーム
  2. c#

[解決済み】C#で例外をキャッチして再スローする理由とは?

2022-03-23 08:33:36

質問

記事を見ています C# - データ転送オブジェクト シリアライズ可能なDTOに

この記事には、こんなコードもあります。

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-catch-throwは無意味であるという私の主張を支持しているようです。


EDITです。

今後このスレッドを見つけた人のために要約すると...

禁止事項

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と同じ)。


参考文献

どのように解決するのですか?

まず、記事中のコードのやり方は邪道です。 throw ex を実行すると、例外のコールスタックがこのthrow文のあるところまでリセットされ、例外が実際にどこで生成されたかという情報が失われます。

次に、このようにキャッチして再スローするだけなら、何の付加価値もないと思いますし、上記のコード例でも十分です。 throw ex は、トライ・キャッチがなければ、さらに良い。

しかし、例外をキャッチして再スローしたいケースもあります。ロギングもその一つでしょう。

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