Я знаю, что иногда innerException имеет значение null
Таким образом, может произойти сбой:
repEvent.InnerException = ex.InnerException.Message;
Есть ли быстрый тернарный способ проверить, является ли innerException нулевым или нет?
Я знаю, что иногда innerException имеет значение null
Таким образом, может произойти сбой:
repEvent.InnerException = ex.InnerException.Message;
Есть ли быстрый тернарный способ проверить, является ли innerException нулевым или нет?
Это то, что вы ищете?
String innerMessage = (ex.InnerException != null)
? ex.InnerException.Message
: "";
Отличные ответы. На аналогичной, но различной ноте иногда бывает несколько уровней вложенных исключений. Если вы хотите получить корневое исключение, которое было изначально выбрано, вне зависимости от глубины, вы можете попробовать следующее:
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();
Что смешно, я не могу найти ничего плохого в Exception.GetBaseException()?
repEvent.InnerException = ex.GetBaseException().Message;
Простейшим решением является использование базового условного выражения:
repEvent.InnerException = ex.InnerException == null ?
null : ex.InnerException.Message;
Почему так много рекурсии в этих ответах?
public static class ExceptionExtensions
{
public static Exception GetOriginalException(this Exception ex)
{
while(ex.InnerException != null)ex = ex.InnerException;
return ex;
}
}
Кажется, это гораздо более прямой способ реализовать это.
Его старый вопрос, но для будущих читателей:
В дополнение к уже опубликованным ответам я думаю, что правильный способ сделать это (когда вы можете иметь более одного InnerException) Exception.GetBaseException Method
Если вам нужен экземпляр исключения, вы должны сделать это:
repEvent.InnerException = ex.GetBaseException();
Если вы ищете сообщение таким образом:
repEvent.InnerException = ex.GetBaseException().Message;
С С# 6.0 вы можете использовать:
string message = exception.InnerException?.Message ?? ""
;
Эта строка кода похожа на:
string message = exception.InnerException == null ? "" : exception.InnerException.Message
.
Иногда также 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;
}
С С# 6.0 вы можете сделать это в одной строке.
repEvent.InnerException = ex.InnerException?.Message;
для другой функции С# 6.0 нажмите здесь
Да:
if (ex.InnerException == null) {
// then it null
}
Вот еще одна возможная реализация, которая добавляет сообщения и трассировки стека, чтобы мы их заполнили:
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);
}
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;
}
}
}
С помощью этого кода вы будете уверены, что не потеряли никаких внутренних сообщений об исключении
catch (Exception exception)
{
Logger.Error(exception.Message);
while (exception.InnerException != null)
{
exception = exception.InnerException;
Logger.Error(exception);
}
}