Compiling all Exception messages into a string Below is a recursive function I've written that's responsible for compiling a string consisting of a Exception's message, and also each of that Exception's InnerException messages.

I've tried to condense everything to one line, but am unsure if this is the most efficient way of approaching this problem.

public static string GetExceptionMessages(Exception exception, int msgCount = 1)
{
    return exception != null ? string.Format("{0}: {1}\n{2}", msgCount, exception.Message, GetExceptionMessages(exception.InnerException, ++msgCount)) : string.Empty;
}


And here is code showing the above method in action:

public static void Main(string[] args)
{
    try
    {
        Throw1();
    }
    catch (Exception e)
    {
        string messages = GetExceptionMessages(e);
        Console.WriteLine(messages);
    }
    Console.ReadLine();
}
public static void Throw1()
{
    try
    {
        Throw2();
    }
    catch (Exception e)
    {
        throw new Exception("Throw1", e);
    }
}
public static void Throw2()
{
    throw new Exception("Throw2");
}
public static string GetExceptionMessages(Exception exception, int msgCount = 1)
{
    return exception != null ? string.Format("{0}: {1}\n{2}", msgCount, exception.Message, GetExceptionMessages(exception.InnerException, ++msgCount)) : string.Empty;
}
Readability first


  I've tried to condense everything to one line, but am unsure if this is the most efficient way of approaching this problem.


Your primary goal when writing code is readability and maintainability and not squeezing everything into single lines.



Can you read this?


return exception != null ? string.Format("{0}: {1}\n{2}", msgCount, exception.Message, GetExceptionMessages(exception.InnerException, ++msgCount)) : string.Empty;



I cannot. This line is way too long even on my large monitor.

How about this? A little bit better, but still, the third line is too long even with string interpolation instead of string.Format

return
    exception is null
        ? string.Empty
        : $"{messageCount}: {exception.Message}{Environment.NewLine}{GetExceptionMessages(exception.InnerException, ++messageCount)}";




Separation

We need to change the strategy because your method is doing two things at a time:


it's looking for exceptions and
it's building a string


We need to separate them by implementing an extension that will enumerate exceptions:

public static IEnumerable&lt;Exception&gt; DescendantsAndSelf(this Exception exception)
{
    do
    {
        yield return exception;
        exception = exception.InnerException;
    } while (!(exception is null));
}


Then we rewrite the string building method as an extension of the first one:

public static string StringifyMessages(this IEnumerable&lt;Exception&gt; exceptions)
{
    var messages = exceptions.Select((e, i) =&gt; $"{i + 1}: {e.Message}")
    return string.Join(Environment.NewLine, messages);
}


So, finally you can chain them like this:

catch (Exception e)
{
    Console.WriteLine(e.DescendantsAndSelf().StringifyMessages());
}




Advantages

This means more code now but this code is testable, modular and can be reused for other things and extensions.