Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Output exception messages including all inners with LINQ

Tags:

c#

linq

Is it possible to output all error messages of thrown exception including inners via LINQ?

I implemented the functionality without LINQ, but I would like to have more concise code. (Isn't the purpose of the LINQ?)

My code without LINQ follows:

try {
    ...
} catch (Exception ex) {
    string msg = "Exception thrown with message(s): ";
    Exception curEx= ex;
    do {
        msg += string.Format("\n  {0}", curEx.Message);
        curEx = curEx.InnerException;
    } while (curEx != null);
    MessageBox.Show(msg);
}
like image 409
sergtk Avatar asked Dec 28 '22 12:12

sergtk


2 Answers

Linq works on sequences, ie., collections of objects. The exception.InnerException hierarchy is instead nested instances of single objects. What you are doing algorithmically is not inherently a sequence operation, and would not be covered by Linq approaches.

You could define a method that explores the hierarchy and returns (yields) a sequence of objects as they are found, but this ultimately is going to be the same algorithm you're currently using to explore the depths, although you could then choose to apply a sequence operation (Linq) on the results.

like image 102
Anthony Pegram Avatar answered Jan 15 '23 03:01

Anthony Pegram


To follow up on @Anthony Pegram's answer, you could define an extension method to get a sequence of the inner exceptions:

public static class ExceptionExtensions
{
    public static IEnumerable<Exception> GetAllExceptions(this Exception ex)
    {
        List<Exception> exceptions = new List<Exception>() {ex};

        Exception currentEx = ex;
        while (currentEx.InnerException != null)
        {
            currentEx = currentEx.InnerException;
            exceptions.Add(currentEx);
        }

        return exceptions;
    }   
}

then you would be able to use LINQ on the sequence. If we have a method that throws nested exceptions like this:

public static class ExceptionThrower {
    public static void ThisThrows() {
        throw new Exception("ThisThrows");
    }

    public static void ThisRethrows() {
        try {
            ExceptionThrower.ThisThrows();
        }
        catch (Exception ex) {
            throw new Exception("ThisRetrows",ex);
        }
    }
}

here's how you can use LINQ with the little extension method we created:

try {
    ExceptionThrower.ThisRethrows();
} 
catch(Exception ex) {
    // using LINQ to print all the nested Exception Messages
    // separated by commas
    var s = ex.GetAllExceptions()
    .Select(e => e.Message)
    .Aggregate((m1, m2) => m1 + ", " + m2);

    Console.WriteLine(s);
}
like image 43
Paolo Falabella Avatar answered Jan 15 '23 01:01

Paolo Falabella