Основной код метода полностью внутри try/catch: это плохая практика?

Обычно я помещаю весь мой код метода Main внутри блока try/catch следующим образом:

public static void Main(string[] args)
{
   try
   {
      // code
   }
   catch (Exception e)
   {
      // code
   }
}

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

Считаете ли вы, что это плохая практика?

Ответ 1

Обертка любого фрагмента кода в блоке try/catch без уважительной причины - это плохая практика.

В модели программирования .NET исключения должны быть зарезервированы для действительно исключительных случаев или условий. Вы должны только пытаться поймать исключения, о которых вы действительно можете что-то сделать. Кроме того, вам вряд ли стоит когда-либо улавливать базовый класс System.Exception (но скорее предпочитайте поймать более конкретные, производные классы исключений, которые вы можете обрабатывать). И если во время выполнения вашей программы должно произойти поистине неожиданное исключение, вам действительно нужно сработать.

Очевидно, что "правильный" ответ должен выполняться в каждом конкретном случае, в зависимости от того, что происходит внутри этого // code заполнителя в вашем блоке catch. Но если вы просите об общем правиле или "лучшей практике", вы всегда должны иметь определенную причину, чтобы ловить исключения, а не просто переносить весь свой код в гигантский блок try/catch, как само собой разумеющееся не думая об этом.

Обратите внимание, что если вы просто пытаетесь поймать любые необработанные исключения, которые могут возникнуть для целей регистрации или сообщения об ошибках, вы должны использовать AppDomain.UnhandledException. Это событие только для уведомлений, поэтому оно не позволяет вам обрабатывать эти исключения, но это подходящее место для реализации ваших функций регистрации журналов или сообщений об ошибках после сбоя приложения.


РЕДАКТИРОВАТЬ: Как я догонял свое чтение замечательного блога Раймонда Чена, "The Old New Thing" , я заметил, что недавно он опубликовал статью по аналогичной теме. Это специфично для COM, а не для .NET Framework, но общие концепции обработки ошибок одинаково применимы к обеим средам. Я думал, что поделился бы несколькими драгоценными камнями из статьи здесь, в поддержку моего [явно противоречивого] ​​мнения.

Исторически, COM помещал гигантскую попытку/кроме ваших методов сервера. Если ваш сервер столкнулся с тем, что обычно является необработанным исключением, гигантский try/except может его поймать и превратить в ошибку RPC_E_SERVERFAULT. Затем он отмечал исключение, которое обрабатывалось, так что сервер оставался в рабочем состоянии, тем самым "повышая надежность, поддерживая работу сервера, даже когда он столкнулся с проблемой".

Помните, это на самом деле было плохим сервисом.

Тот факт, что произошло необработанное исключение, означает, что сервер находился в неожиданном состоянии. Улавливая исключение и говоря: "Не волнуйтесь, все хорошо", вы в конечном итоге оставите поврежденный сервер.

[., ]

Захват всех исключений и продолжение процесса продолжает предполагать, что сервер может восстановиться после неожиданного сбоя. Но это абсурдно. Вы уже знаете, что сервер неустранимо тост: он разбился!

Намного лучше позволить серверу сбой, чтобы свалка сбоя могла быть захвачена в момент сбоя. Теперь у вас есть шанс сразиться с тем, что происходит.

Вы можете [и должны] прочитать всю статью здесь в своем блоге: Как отключить обработчик исключений, который COM "помогает" обернуть вокруг вашего сервера.

Ответ 2

Если вы делаете самую умную вещь, вы можете с ошибкой, это хорошая практика. Это то, что пытается/поймать.

Если вы просто отбрасываете ошибку (или регистрируете ее и отбрасываете), особенно если вы делаете это независимо от типа исключения - это считается плохой практикой.

Это может поднять вопрос: что, если самая разумная вещь - занести в журнал и выбросить? Я хочу сказать, что это был бы исключительный случай. Но на практике мой код будет утверждать иначе. Полагаю, я предаюсь много плохой практике.

Ответ 3

Я общаюсь с 90% того, что говорит Коди. Есть некоторые ситуации, похожие на пример pluggin, где вы можете захотеть поймать системные исключения. Ниже приведен пример использования веб-службы WCF.

Цель: используйте службу и удалите ее, даже если возникла ошибка. Разрешить ошибку пузыря.

public static bool DoRemoteWebServiceWork()
{
    bool result;
    RemoteWebServiceClient client = new RemoteWebServiceClient();
    try
    {
        result = client.DoWork();
        client.Close();
    }
    catch (Exception)
    {
        client.Abort(); //dispose
        throw;//This service is critical to application function. The application should break if an exception is thrown.
        //could log end point and binding exceptions to avoid ignoring changes to the remote service that require updates to our code.
    }
    return result;
}

Цель: используйте службу и удалите ее, даже если возникла ошибка. Не допускайте появления пузырьков.

public static bool DoRemoteWebServiceWork()
{
    bool result;
    RemoteWebServiceClient client = new RemoteWebServiceClient();
    try
    {
        result = client.DoWork();
        client.Close();
    }
    catch (Exception)
    {
        client.Abort(); //dispose
        //throw; //This service is auxiliary to the applications primary function. We have no influence over the service and therefore cannot fix it.
        //could log end point and binding exceptions to avoid ignoring changes to the remote service that require updates to our code.
    }
    return result;
}

Ответ 4

Определенно, да, это плохая практика, чтобы использовать класс Exception

Вы должны заботиться о типах исключений, а не обрезать все исключения в блоке catch, чтобы они не сообщали системе об ошибке.

Класс исключений - это базовый класс, и исключение верхнего уровня можно уловить в коде. Используйте наиболее конкретные исключения в блоке catch, в частности, только те, которые вы создаете код в блоке try {...} catch {...}, и только если он может быть эффективно разрешен на определенном уровне (в функция, где try.. catch block объявлен)

Ответ 5

Это зависит от того, что вы делаете, если поймаете ошибку. Если вы просто поймаете все ошибки, чтобы они обработали их изящно - плохая практика. Я бы сказал, что это плохая практика, даже если вы только заходите туда - лог локально.

Если вы действительно что-то сделаете, чтобы восстановить ошибку (например, вы бросили ее сами и знаете, что с ней делать) - я бы проголосовал "ОК":)