Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C# re-throwing exception outside of scope

Tags:

c#

.net

exception

I am fully aware that what I am about to ask is not good practice... but:

Let's say I have a class containing a function that I want to always return a value, but store any exceptions that might occur for later processing. Something Like:

public Exception _error { get; set; }

public bool IsValid()
{
    try
    {
        //do something here to cause exception                

        return true;
    }
    catch (Exception ex)
    {
        _error = ex;
        return false;
    }
}

Now that I have stored the exception, is it at all possible to throw the exception from an outside method while maintaining both the original stack trace and exception type?

throw _error; //lose stack trace

throw new Exception("", _error) //lose type

Thanks for looking or answering.

EDIT:

Thanks to some additional points, I realize that the below idea only takes away information and doesn't really add or simplify the situation. Thanks again to everyone.

After pondering Pieter's answer and comments, I'm now wondering if making a wrapper Exception class like the below could be a partial solution. This overrides as much of the exception as possible to make the New exception look like its innerexception, including the stacktrace.. dirty I know, but interesting:

public class ExceptionWrapper : Exception
{
    private Exception _innerException;

    public ExceptionWrapper(Exception ex) : base("", ex)
    {
        _innerException = ex;
        this.Source = ex.Source;
        this.HelpLink = ex.HelpLink;
    }

    public override string StackTrace
    {
        get
        {
            return _innerException.StackTrace;
        }
    }

    public override System.Collections.IDictionary Data
    {
        get
        {
            return _innerException.Data;
        }
    }

    public override string Message
    {
        get
        {
            return _innerException.Message;
        }
    }

    public new Exception InnerException
    {
        get
        {
            return _innerException.InnerException;
        }
    }
}

like image 305
Andrew Hanlon Avatar asked Dec 29 '22 02:12

Andrew Hanlon


2 Answers

No, this is not possible.

However, you normally solve this is by wrapping the exception in a new exception:

throw new MyException("Wrapper", _error);

This does maintain the stack trace of _error, but you do get a new exception. Your solution in your second example is the correct way of handling these cases.

like image 73
Pieter van Ginkel Avatar answered Jan 03 '23 08:01

Pieter van Ginkel


Consider using reflection to create a wrapper exception of the correct type (Activator.CreateInstance) and calling the constructor that will accept the inner exception you have stored.

For example:

[Test]
public void test()
{
    Exception ex = new ArgumentNullException();

    Exception wrapped = (Exception)Activator.
        CreateInstance(ex.GetType(), "wrapped", ex);

    Type expectedType = typeof(ArgumentNullException);

    Assert.IsInstanceOf(expectedType, wrapped, "Is ArgumentNullException.");

    Assert.AreEqual(ex, wrapped.InnerException, "Exception is wrapped.");
}

Update

In order to mitigate the constructor issue, you could consider using the default constructor (should be there for an exception that follows design guidelines, but not mandatory) and then patching up the new instance by setting its fields via reflection.

I agree the approach is highly "meh" it's more an exploration of an idea. I wouldn't recommend it.

The exception design guidelines require a default constructor, so this sort of behaviour may go on in the framework somewhere anyway. Perhaps for some sort of icky serialization\deserialization of exceptions across some sort of communications boundary?

like image 38
Tim Lloyd Avatar answered Jan 03 '23 07:01

Tim Lloyd