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

184
28 октября 2018, 18:40

В версии 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;
}
Answer 1

Судя по обсуждению на гитхабе, о таком варианте просто не подумали.

Однако, в языке есть другая конструкция который подойдет в подобных случаях:

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

Ведь если исключение не ловить - то не придется его кидать обратно.

Answer 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();
    }
}

Но на самом деле, какая-то мышиная возня, не совсем понятно чем предыдущий ответ не устраивает.

READ ALSO
Ошибка до загрузки формы

Ошибка до загрузки формы

При загрузке формы возникает ошибка вида

719
repositoryLookUpEdit для Devexpress

repositoryLookUpEdit для Devexpress

Суть проблемы в следующем: Я пишу приложение под WIN на C#Использую gridControl, в котором для поля GraidID хочу использовать ColumnEditor = repositoryLookUpEdit

170
C# Сортировка перечисления по периоду дат

C# Сортировка перечисления по периоду дат

Есть свойство типа IEnumerable в которое возвращает коллекцию типа TupleПример:

239
Связь один к одному

Связь один к одному

ModelВ таблицах указал

168