Когда использовать блоки try/catch?

Я прочитал и понял, что делает блок Try/Catch, и почему это важно для его использования. Но я застрял в понимании, когда и где их использовать. Любой совет? Я отправлю образец моего кода ниже в надежде, что у кого-то есть время, чтобы сделать некоторые рекомендации для моего примера.

    public AMPFileEntity(string filename)
    {
        transferFileList tfl = new transferFileList();
        _AMPFlag = tfl.isAMPFile(filename);
        _requiresPGP = tfl.pgpRequired(filename);
        _filename = filename.ToUpper();
        _fullSourcePathAndFilename = ConfigurationSettings.AppSettings.Get("sourcePath") + _filename;
        _fullDestinationPathAndFilename = ConfigurationSettings.AppSettings.Get("FTPStagePath") + _filename;
        _hasBeenPGPdPathAndFilename = ConfigurationSettings.AppSettings.Get("originalsWhichHaveBeenPGPdPath");
    }


    public int processFile()
    {

        StringBuilder sb = new StringBuilder();
        sb.AppendLine(" ");
        sb.AppendLine("    --------------------------------");
        sb.AppendLine("     Filename: " + _filename);
        sb.AppendLine("     AMPFlag: " + _AMPFlag);
        sb.AppendLine("     Requires PGP: " + _requiresPGP);
        sb.AppendLine("    --------------------------------");
        sb.AppendLine(" ");

        string str = sb.ToString();
        UtilityLogger.LogToFile(str);
        if (_AMPFlag)
        {
            if (_requiresPGP == true)
            {
                encryptFile();
            }
            else
            {
                UtilityLogger.LogToFile("This file does not require encryption. Moving file to FTPStage directory.");
                if (File.Exists(_fullDestinationPathAndFilename))
                {
                    UtilityLogger.LogToFile(_fullDestinationPathAndFilename + " alreadyexists. Archiving that file.");
                    if (File.Exists(_fullDestinationPathAndFilename + "_archive"))
                    {
                        UtilityLogger.LogToFile(_fullDestinationPathAndFilename + "_archive already exists.  Overwriting it.");
                        File.Delete(_fullDestinationPathAndFilename + "_archive");
                    }
                    File.Move(_fullDestinationPathAndFilename, _fullDestinationPathAndFilename + "_archive");
                }
                File.Move(_fullSourcePathAndFilename, _fullDestinationPathAndFilename);
            }
        }
        else
        {
            UtilityLogger.LogToFile("This file is not an AMP transfer file. Skipping this file.");
        }

            return (0);
    }


    private int encryptFile()
    {

        UtilityLogger.LogToFile("This file requires encryption.  Starting encryption process.");


        // first check for an existing PGPd file in the destination dir.  if exists, archive it - otherwise this one won't save.  it doesn't overwrite.
        string pgpdFilename = _fullDestinationPathAndFilename + ".PGP";



        if(File.Exists(pgpdFilename))
        {
            UtilityLogger.LogToFile(pgpdFilename + " already exists in the FTPStage directory.  Archiving that file." );
            if(File.Exists(pgpdFilename + "_archive"))
            {
                UtilityLogger.LogToFile(pgpdFilename + "_archive already exists.  Overwriting it."); 
                File.Delete(pgpdFilename + "_archive");
            }
            File.Move(pgpdFilename, pgpdFilename + "_archive"); 
        }

        Process pProc = new Process();
        pProc.StartInfo.FileName = "pgp.exe";

        string strParams = @"--encrypt " + _fullSourcePathAndFilename + " --recipient infinata --output " + _fullDestinationPathAndFilename + ".PGP";

        UtilityLogger.LogToFile("Encrypting file.  Params: " + strParams);
        pProc.StartInfo.Arguments = strParams;
        pProc.StartInfo.UseShellExecute = false;
        pProc.StartInfo.RedirectStandardOutput = true;
        pProc.Start();
        pProc.WaitForExit();

        //now that it been PGPd, save the orig in 'hasBeenPGPd' dir
        UtilityLogger.LogToFile("PGP encryption complete.  Moving original unencrypted file to " +  _hasBeenPGPdPathAndFilename); 
        if(File.Exists(_hasBeenPGPdPathAndFilename + _filename + "original_which_has_been_pgpd"))
        {
            UtilityLogger.LogToFile(_hasBeenPGPdPathAndFilename + _filename + "original_which_has_been_pgpd already exists.  Overwriting it.");
            File.Delete(_hasBeenPGPdPathAndFilename + _filename + "original_which_has_been_pgpd");
        }
            File.Move(_fullSourcePathAndFilename, _hasBeenPGPdPathAndFilename + _filename + "original_which_has_been_pgpd");

        return (0);

    }
}

}

Ответ 1

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

Не поймайте исключение, если вы собираетесь регистрировать исключение и бросать его в стек. Он не содержит никакого смысла и не помещает код.

Улавливайте исключение, если ожидаете сбой в определенной части вашего кода, и если у вас есть резерв для него.

Конечно, вы всегда имеете дело с проверенными исключениями, которые требуют использования блоков try/catch, и в этом случае у вас нет другого выбора. Даже с проверенным исключением, убедитесь, что вы правильно записываете и обрабатываете как можно чище.

Ответ 2

Исключения и обработка исключений (Руководство по программированию на С#)

Исключения и обработка исключений (Руководство по программированию на С#) Обновленная ссылка (по MS), хотя другая все еще актуальна.

Обработка исключений (Руководство по программированию на С#)

Ответ 3

Мне научили использовать try/catch/finally для любых методов/классов, где могут возникать множественные ошибки и которые вы действительно можете обработать. Операции с базами данных, ввода-вывода FileSystem, потоковая передача и т.д. Основная логика обычно не требует try/catch/finally.

Большая часть про try/catch/наконец-то заключается в том, что вы можете иметь несколько уловов, чтобы вы могли создавать серию обработчиков исключений для обработки очень конкретной ошибки или использовать общее исключение, чтобы поймать любые ошибки, которые вы не видите,

В вашем случае вы используете File.Exists, который хорош, но их может быть другая проблема с диском, который может вызвать еще одну ошибку, которую File.Exists не может обработать. Да, это логический метод, но сказать, что файл заблокирован, и что произойдет, если вы попытаетесь написать ему? С уловом вы можете планировать редкий сценарий, но без try/catch/, наконец, вы можете подвергнуть код полностью непредвиденным условиям.

Ответ 4

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

Мой ввод короткий:
Когда использовать одно, равно или более важно, как правильно его использовать.

PS: "это" относится к "попыткам исключения".

Ответ 5

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

Для конкретных примеров File.Delete может выполнять ряд исключений, включая IOException, UnauthorizedAccessException, а также другие. Что бы вы хотели, чтобы ваше приложение было в таких ситуациях? Если вы попытаетесь удалить файл, но кто-то еще использует его, вы получите исключение IOException.

    try
    {    
        File.Delete(pgpdFilename + "_archive")
    }
    catch(IOException)
    {
        UtilityLogger.LogToFile("File is in use, could not overwrite.");
       //do something else meaningful to your application
       //perhaps save it under a different name or something
    }

Также имейте в виду, что если это не сработает, то файл File.Move, который вы делаете вне своего блока if, также будет терпеть неудачу (снова к IOException - поскольку файл не был удален, он все еще там, что приведет к перемещению для отказа).