views:

116

answers:

5

When C# throws an exception, it can have an inner exception. What I want to do is get the inner-most exception, or in other words, the leaf exception that doesn't have an inner exception. I can do this in a while loop:

while (e.InnerException != null)
{
    e = e.InnerException;
}

But I was wondering if there was some one-liner I could use to do this instead.

+2  A: 

Oneliner :)

while (e.InnerException != null) e = e.InnerException;

Obviously, you can't make it any simpler.

Draco Ater
+1 for a slick implementation
Brad
Thanks, just wanted to make sure that was the case.
Daniel T.
Still a loop, but I wouldn't know any other way. Nice and clean!
Willem
+2  A: 

You could use recursion to create a method in a utility class somewhere.

public Exception GetFirstException(Exception ex)
{
    if(ex.InnerExecption == null) { return ex; } // end case
    else { return GetFirstException(ex.InnerException); } // recurse
}

Use:

try
{
    // some code here
}
catch (Exception ex)
{
    Exception baseException = GetFirstException(ex);
}

The extension method suggested (good idea @dtb)

public static Exception GetFirstException(this Exception ex)
{
    if(ex.InnerExecption == null) { return ex; } // end case
    else { return GetFirstException(ex.InnerException); } // recurse
}

Use:

try
{
    // some code here
}
catch (Exception ex)
{
    Exception baseException = ex.GetFirstException();
}
Brad
This is just the while loop, with more code. The only upside is that it can be called from multiple places, but still, you can have the same function header with the while loop inside.
Wonko the Sane
I think if(ex.InnerExecption != null) should be if(ex.InnerExecption == null) :)
Goblin
Except should it not say if (ex.InnerException == null) { return ex; } :-)
WestDiscGolf
@Goblin/WestDiscGolf, good catch. I've corrected. @Wonko, you're right, it's still essentially a loop, but this is the only way to get what the OP wants.
Brad
+2  A: 

If you don't know how deep the inner exceptions are nested, there is no way around a loop or recursion.

Of course, you can define an extension method that abstracts this away:

public static class ExceptionExtensions
{
    public static Exception GetInnermostException(this Exception e)
    {
        if (e == null)
        {
            throw new ArgumentNullException("e");
        }

        while (e.InnerException != null)
        {
            e = e.InnerException;
        }

        return e;
    }
}
dtb
@dtb, the extension is a good idea :) I added it to my answer.
Brad
A: 

Sometimes you might have many inner exceptions (many bubbled exceptions). In which case you might want to do:

List<Exception> es = new List<Exception>();
while(e.InnerException != null)
{
   es.add(e.InnerException);
   e = e.InnerException
}
Ryan Ternier
A: 

Not quite one line but close:

        Func<Exception, Exception> last = null;
        last = e => e.InnerException == null ? e : last(e.InnerException);
Steve Ellinger