C#: Эквивалентный из Python пробовать/ловить/еще блок

В Python существует этот полезный код обработки исключений:

try:
    # Code that could raise an exception
except Exception:
    # Exception handling
else:
    # Code to execute if the try block DID NOT fail

Я думаю, что полезно смочь разделить код, который мог повысить и исключение из Вашего нормального кода. В Python это было возможно как показано выше, однако я не могу найти ничего как он в C#.

Принятие функции или одной как она не существует, это общепринятая практика, чтобы вставить нормальный код try блок или после catch блок?

Причина, которую я спрашиваю, состоит в том, потому что у меня есть следующий код:

if (!IsReadOnly)
{
    T newobj;
    try
    {
        newobj = DataPortal.Update<T>(this);

        List<string> keys = new List<string>(BasicProperties.Keys);
        foreach (string key in keys)
        {
            BasicProperties[key] = newobj.BasicProperties[key];
        }
    }
    catch (DataPortalException)
    {
        // TODO: Implement DataPortal.Update<T>() recovery mechanism
    }
}

Который требует, чтобы нормальный код был в блоке попытки, потому что иначе, если исключение было повышено и впоследствии обработано, newobj был бы неприсвоенным, но это чувствует себя довольно неестественным, чтобы иметь это много кода в блоке попытки, который не связан с DataPortalException. Что сделать?

Спасибо

7
задан mjv 3 March 2010 в 23:22
поделиться

8 ответов

Я бы предпочел видеть остальную часть кода за пределами try / catch, чтобы было ясно, откуда исходит исключение, которое вы пытаетесь перехватить, и что вы не поймаете случайно исключение, которое не пытались уловить.

Я думаю, что наиболее близким эквивалентом Python try / catch / else является использование локальной логической переменной для запоминания того, было ли сгенерировано исключение.

bool success;

try
{
    foo();
    success = true;
}
catch (MyException)
{
    recover();
    success = false;
}

if (success)
{
    bar();
}

Но если вы делаете это, я бы спросил, почему вы либо не полностью восстанавливаетесь после исключения, чтобы можно было продолжить, как если бы оно было успешным, либо полностью прервать работу, вернув код ошибки или даже просто позволив исключение передается вызывающему.

9
ответ дан 6 December 2019 в 06:49
поделиться

Варварское решение: создайте класс Else, производный от Exception, выбросьте его экземпляр в конце блока try и используйте catch (Else ) {...} для обработки других вещей.

Я чувствую себя такой грязной.

7
ответ дан 6 December 2019 в 06:49
поделиться

Это может быть отклонено, но в C # нет goto (обратите внимание, что у меня почти нет знаний по C #, поэтому я понятия не имею, работает ли это).

как насчет чего-то вроде

try 
{ 
...
} 
catch(Exception ex) 
{ 
...
goto Jump_past_tryelse
} 
...//Code to execute if the try block DID NOT fail

Jump_past_tryelse:
...
3
ответ дан 6 December 2019 в 06:49
поделиться

В C# нет такой концепции, поэтому у вас остается только три варианта:

  • поместить код else внутри try.
  • поместить код else вне блока try catch, использовать локальную переменную для указания успеха или неудачи и блок if вокруг кода else.
  • поместите код else в блок finally, используйте локальную переменную для указания успеха или неудачи и блок if вокруг вашего кода else.
2
ответ дан 6 December 2019 в 06:49
поделиться

Позвольте мне повторить идею из похожего вопроса на StackOverflow. Вы не можете сделать это напрямую, но вы можете написать метод, который инкапсулирует нужное вам поведение. Посмотрите на исходный вопрос, чтобы увидеть, как реализовать метод (если вы не знакомы с лямбда-выражениями и Func делегатами). Использование может выглядеть следующим образом:

TryExceptRaise(() => { 
    // code that can throw exception
  }, (Exception e) => { 
    // code to run in case of an exception
    return (...); 
  }, () => {
    // code to run if there is no exception
    return (...);
  });
2
ответ дан 6 December 2019 в 06:49
поделиться

Вы можете сделать что-то вроде этого:

if (!IsReadOnly)
{
    T newobj = null;
    try
    {
        newobj = DataPortal.Update<T>(this);    
    }
    catch (DataPortalException)
    {
        // TODO: Implement DataPortal.Update<T>() recovery mechanism
    }
    if (newobj != null)
    {
        List<string> keys = new List<string>(BasicProperties.Keys);
        foreach (string key in keys)
        {
            BasicProperties[key] = newobj.BasicProperties[key];
        }
    }
}
0
ответ дан 6 December 2019 в 06:49
поделиться

, который будет пустым оператором, например hits

try 
{ 
    somethingThatCanThrow(); 
} 
catch(Exception ex) 
{ 
    LogException(ex); 
    return;
} 
ContinueFlow();
0
ответ дан 6 December 2019 в 06:49
поделиться

Просто поместите блок «else» перед уловкой. Затем он будет выполняться только в том случае, если выполнение кода достигнет этой точки:

try
{
    fee();
    fi();
    foe();
    fum();

    /// put your "else" stuff here. 
    /// It will only be executed if fee-fi-foe-fum did not fail.
}
catch(Exception e)
{
    // handle exception
}

Учитывая это, я не вижу использования try..catch ... else, если в описании OP отсутствует что-то жизненно важное.

2
ответ дан 6 December 2019 в 06:49
поделиться
Другие вопросы по тегам:

Похожие вопросы: