5

Exception.ToString() を使用して例外を報告するテスト フレームワークを使用しています。

昨日、ネストされた例外の不完全なレポートに遭遇しました。Reflector を使用したいくつかの作業の後、.NET 4.0 では内部例外文字列表現の構成方法が壊れているという結論に達しました。

以下に例を示します。

public class MyException : Exception
{
  DateTime when;

  public MyException(DateTime when)
  {
    this.when = when;
  }

  public override string ToString()
  {
    var builder = new StringBuilder();
    builder.AppendFormat("Happened at: {0}\r\n", this.when);
    builder.Append(base.ToString());
    return builder.ToString();
  }
}

class Program
{
  private static void throws()
  {
    throw new Exception("bobby!", new MyException(DateTime.Now));
  }

  private static void catches()
  {
    try
    {
      throws();
    }
    catch (Exception e)
    {
      Console.WriteLine(e);
    }
  }

  static void Main(string[] args)
  {
    catches();
  }
}

ここでのコンソール出力には、カスタムの「Happened at」プレフィックスは含まれません。

MyException を別の例外にネストせずに直接スローする場合、カスタム文字列 rep が使用されることに注意してください。

その理由は、Exception.ToString() が内部例外の ToString() を呼び出すのではなく、プライベート メソッドの ToString(bool) を呼び出すためです。

// Exception
public override string ToString()
{
  return this.ToString(true);
}

private string ToString(bool needFileLineInfo)
{
  // yada yada

  if (this._innerException != null)
  {
    result += "some stuff " + this._innerException.ToString(needFileLineInfo) + " some more stuff";
                                                   ^^^^^^^^^^^^^^^^^^^^^^^^^^
  }

  // yada yada

  return result;
}

そのため、Exception.ToString() は内部例外の ToString() を呼び出さなくなったため、実装は内部例外のカスタマイズされた文字列表現の機会をショートサーキットしました。

.NET 2.0 では、オーバーライド可能な ToString() が期待どおりに呼び出されたため、これは途中で重大な変更となりました。

ドキュメントは変更されておらず、今でもそう主張しています。

ToString のデフォルトの実装は、現在の例外をスローしたクラスの名前、メッセージ、内部例外で ToString を呼び出した結果を取得します [...]

http://msdn.microsoft.com/en-us/library/system.exception.tostring.aspx

これは私以外の誰にとってもバグのように聞こえますか?

4

1 に答える 1