psurikov
psurikov

Reputation: 3458

Result of Exception.ToString() is different in different projects

When I create nested exceptions in my test console application I'm getting the following result:

class Program
{
    static void Main(string[] args)
    {
        var innerException = new SomeException("Inner Error");
        var outerException = new Exception("Outer Error", innerException);
        var outerExceptionString = outerException.ToString();

        Console.WriteLine(outerExceptionString);
        Console.ReadKey();
    }
}

public class SomeException : Exception
{
    public SomeException(string message) : base(message) { }
    public SomeException(string message, Exception innerException) : base(message, innerException) { }

    public override string ToString()
    {
        return "BLABLABLA";
    }
}

Output:

System.Exception: Outer Error ---> BLABLABLA
   --- End of inner exception stack trace ---

The output contains the overridden string "BLABLABLA". However, If I now copy this code into my windows application, I'm getting a different result:

/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main(string[] args)
{
    var innerException = new SomeException("Inner Error");
    var outerException = new Exception("Outer Error", innerException);
    var outerExceptionString = outerException.ToString();
    MessageBox.Show(outerExceptionString);

    // ... lots of other code
}

public class SomeException : Exception
{
    public SomeException(string message) : base(message) { }
    public SomeException(string message, Exception innerException) : base(message, innerException) { }

    public override string ToString()
    {
        return "BLABLABLA";
    }
}

Output:

System.Exception: Outer Error ---> TestUtility.SomeException: Inner Error
   --- End of inner exception stack trace ---

As you see, it didn't include the overridden string "BLABLABLA" for some reason. I tried to test it in other windows applications but the result is the same as in console app. For some reason, I'm getting different behavior in one specific project. Is there anything that could affect the way the exception is formatted? All apps use .net framework 3.5.

Upvotes: 1

Views: 221

Answers (2)

psurikov
psurikov

Reputation: 3458

I found the problem. Even though I was using the same 3.5 .net framework, at runtime my projects were pointing to different versions of mscorlib.dll (for some reason). The Exception.cs in mscorlib 2.0 version makes the output with overridden string, while in mscorlib 4.0 the code seems to be different.

Here is the Exception.ToString() method in mscorlib version 2.0:

public override String ToString() {
        String message = Message;
        String s;
        if (_className==null) { 
            _className = GetClassName();
        } 

        if (message == null || message.Length <= 0) {
            s = _className; 
        }
        else {
            s = _className + ": " + message;
        } 

        if (_innerException!=null) { 
            s = s + " ---> " + _innerException.ToString() + Environment.NewLine + "   " + Environment.GetResourceString("Exception_EndOfInnerExceptionStack"); 
        }

        if (StackTrace != null)
            s += Environment.NewLine + StackTrace;

        return s;
    }

It directly calls _innerException.ToString(). But here is the Exception.ToString() method in mscorlib version 4.0:

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

private string ToString(bool needFileLineInfo, bool needMessage)
{
    string text = needMessage ? this.Message : null;
    string text2;
    if (text == null || text.Length <= 0)
    {
        text2 = this.GetClassName();
    }
    else
    {
        text2 = this.GetClassName() + ": " + text;
    }
    if (this._innerException != null)
    {
        text2 = string.Concat(new string[]
        {
            text2,
            " ---> ",
            this._innerException.ToString(needFileLineInfo, needMessage),
            Environment.NewLine,
            "   ",
            Environment.GetRuntimeResourceString("Exception_EndOfInnerExceptionStack")
        });
    }
    string stackTrace = this.GetStackTrace(needFileLineInfo);
    if (stackTrace != null)
    {
        text2 = text2 + Environment.NewLine + stackTrace;
    }
    return text2;
}

Now it calls some overridden method _innerException.ToString(bool, bool) and that is why it doesn't include the overridden version of ToString(). I think it will affect the old code where people were using ToString overrides. Also I don't know why at runtime I'm linked to different dll versions even though I have target framework set to 3.5 everywhere but this is a different problem.

Upvotes: 2

Matt Dillard
Matt Dillard

Reputation: 14853

Is it possible that you are accidentally instantiating a class SomeException from a different namespace than you are expecting? Your output indicates that the fully referenced type is TestUtility.SomeException.

To test this out, use a fully qualified namespace when instantiating innerException and see how that works for you.

Upvotes: 1

Related Questions