Страницы

Поиск по вопросам

воскресенье, 2 февраля 2020 г.

C#7 - throw как выражение в тернарном операторе

#c_sharp


В версии C#7 и выше мы можем бросать исключения в одной из веток тернарного оператора:   

var a = 1 < 2 ? "true" : throw new Exception();


почему мы не можем таким же образом пробросить пойманное исключение дальше?  

Например:   

try
{
    var er = 1/0;
}
catch (Exception ex)
{
    var a = ex.InnerException == null ? ex.Message : throw;
}  


Я так понимаю, что в стандартном использовании throw используется некий неявный «контекст»
инструкции try-catch, откуда и достаётся информация об отловленном исключении. Почему
не используется тот же «контекст» в случае с тернарным оператором?

Аналогично, интересует ситуация и с null-coalescing оператором - ??.  



Вариант с явным указанием пойманного исключения в качестве аргумента для throw не
годится - работать будет, но в этом случае стек-трейс будет утерян.   

try
{
    var er = 1/0;
}
catch (Exception ex)
{
    var a = ex.InnerException == null ? ex.Message : throw ex;
}

    


Ответы

Ответ 1



Судя по обсуждению на гитхабе, о таком варианте просто не подумали. Однако, в языке есть другая конструкция который подойдет в подобных случаях: try { var er = 1/0; } catch (Exception ex) when (ex.InnerException == null) { var a = ex.Message; } Ведь если исключение не ловить - то не придется его кидать обратно.

Ответ 2



Если проблема именно в сохранении предыдущего стектрейса в throw ex и записи в одну строчку, то можно начудить как-нибудь так: using System.Runtime.Serialization; public static class ExceptionHelper { public static Exception PreserveStackTrace(this Exception e) { var streamingContext = new StreamingContext(StreamingContextStates.CrossAppDomain); var objectManager = new ObjectManager(null, streamingContext); var serializationInfo = new SerializationInfo(e.GetType(), new FormatterConverter()); e.GetObjectData(serializationInfo, streamingContext); objectManager.RegisterObject(e, 1, serializationInfo); objectManager.DoFixups(); return e; } public static object Throw(this Exception ex) => throw ex; } class Program { static void Main(string[] args) { try { try { throw new Exception("exception"); } catch (Exception ex) { ex.PreserveStackTrace(); Console.WriteLine(ex.StackTrace); var a = ex.InnerException != null ? ex.Message : ex.PreserveStackTrace().Throw(); } } catch (Exception ex) { Console.WriteLine(ex.StackTrace); } Console.ReadLine(); } } Но на самом деле, какая-то мышиная возня, не совсем понятно чем предыдущий ответ не устраивает.

Комментариев нет:

Отправить комментарий