Лучший способ проверить внутреннее исключение?

Я знаю, что иногда innerException имеет значение null

Таким образом, может произойти сбой:

 repEvent.InnerException = ex.InnerException.Message; 

Есть ли быстрый тернарный способ проверить, является ли innerException нулевым или нет?

Ответ 1

Это то, что вы ищете?

String innerMessage = (ex.InnerException != null) 
                      ? ex.InnerException.Message
                      : "";

Ответ 2

Отличные ответы. На аналогичной, но различной ноте иногда бывает несколько уровней вложенных исключений. Если вы хотите получить корневое исключение, которое было изначально выбрано, вне зависимости от глубины, вы можете попробовать следующее:

public static class ExceptionExtensions
{
    public static Exception GetOriginalException(this Exception ex)
    {
        if (ex.InnerException == null) return ex;

        return ex.InnerException.GetOriginalException();
    }
}

И при использовании:

repEvent.InnerException = ex.GetOriginalException();

Ответ 3

Что смешно, я не могу найти ничего плохого в Exception.GetBaseException()?

repEvent.InnerException = ex.GetBaseException().Message;

Ответ 4

Простейшим решением является использование базового условного выражения:

repEvent.InnerException = ex.InnerException == null ? 
    null : ex.InnerException.Message;

Ответ 5

Почему так много рекурсии в этих ответах?

public static class ExceptionExtensions
{
    public static Exception GetOriginalException(this Exception ex)
    {
        while(ex.InnerException != null)ex = ex.InnerException;
        return ex;
    }
}

Кажется, это гораздо более прямой способ реализовать это.

Ответ 6

Его старый вопрос, но для будущих читателей:

В дополнение к уже опубликованным ответам я думаю, что правильный способ сделать это (когда вы можете иметь более одного InnerException) Exception.GetBaseException Method

Если вам нужен экземпляр исключения, вы должны сделать это:

repEvent.InnerException = ex.GetBaseException();

Если вы ищете сообщение таким образом:

repEvent.InnerException = ex.GetBaseException().Message;

Ответ 8

Иногда также InnerException имеет InnerException, поэтому вы можете использовать для него рекурсивную функцию:

public string GetInnerException(Exception ex)
{
     if (ex.InnerException != null)
     {
        return string.Format("{0} > {1} ", ex.InnerException.Message, GetInnerException(ex.InnerException));
     }
   return string.Empty;
}

Ответ 9

С С# 6.0 вы можете сделать это в одной строке.

repEvent.InnerException = ex.InnerException?.Message; 

для другой функции С# 6.0 нажмите здесь

Ответ 10

Да:

if (ex.InnerException == null) {
    // then it null
}

Ответ 11

Вот еще одна возможная реализация, которая добавляет сообщения и трассировки стека, чтобы мы их заполнили:

private static Tuple<string, string> GetFullExceptionMessageAndStackTrace(Exception exception)
{
    if (exception.InnerException == null)
    {
        if (exception.GetType() != typeof(ArgumentException))
        {
            return new Tuple<string, string>(exception.Message, exception.StackTrace);
        }
        string argumentName = ((ArgumentException)exception).ParamName;
        return new Tuple<string, string>(String.Format("{0} With null argument named '{1}'.", exception.Message, argumentName ), exception.StackTrace);
    }
    Tuple<string, string> innerExceptionInfo = GetFullExceptionMessageAndStackTrace(exception.InnerException);
    return new Tuple<string, string>(
    String.Format("{0}{1}{2}", innerExceptionInfo.Item1, Environment.NewLine, exception.Message),
    String.Format("{0}{1}{2}", innerExceptionInfo.Item2, Environment.NewLine, exception.StackTrace));
}


[Fact]
public void RecursiveExtractingOfExceptionInformationOk()
{
    // Arrange
    Exception executionException = null;
    var iExLevelTwo = new NullReferenceException("The test parameter is null");
    var iExLevelOne = new ArgumentException("Some test meesage", "myStringParamName", iExLevelTwo);
    var ex = new Exception("Some higher level message",iExLevelOne);

    // Act 
    var exMsgAndStackTrace = new Tuple<string, string>("none","none");
    try
    {
        exMsgAndStackTrace = GetFullExceptionMessageAndStackTrace(ex);
    }
    catch (Exception exception)
    {
        executionException = exception;
    }

    // Assert
    Assert.Null(executionException);

    Assert.True(exMsgAndStackTrace.Item1.Contains("The test parameter is null"));
    Assert.True(exMsgAndStackTrace.Item1.Contains("Some test meesage"));
    Assert.True(exMsgAndStackTrace.Item1.Contains("Some higher level message"));
    Assert.True(exMsgAndStackTrace.Item1.Contains("myStringParamName"));

    Assert.True(!string.IsNullOrEmpty(exMsgAndStackTrace.Item2));

    Console.WriteLine(exMsgAndStackTrace.Item1);
    Console.WriteLine(exMsgAndStackTrace.Item2);
}

Ответ 12

class MyException : Exception
{
    private const string AMP = "\r\nInnerException: ";
    public override string Message
    {
        get
        {
            return this.InnerException != null ? base.Message + AMP + this.InnerException.Message : base.Message;
        }
    }

    public override string StackTrace
    {
        get
        {
            return this.InnerException != null ? base.StackTrace + AMP + this.InnerException.StackTrace : base.StackTrace;
        }
    }
}

Ответ 13

С помощью этого кода вы будете уверены, что не потеряли никаких внутренних сообщений об исключении

catch (Exception exception)
{
   Logger.Error(exception.Message);
   while (exception.InnerException != null)
   {
       exception = exception.InnerException;
       Logger.Error(exception);
   }
}