Когда использовать блоки try / catch? - PullRequest
31 голосов
/ 12 ноября 2009

Я прочитал и понял, что делает блок 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's 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);

    }
}

}

Ответы [ 5 ]

73 голосов
/ 12 ноября 2009

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

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

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

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

4 голосов
/ 12 ноября 2009

Как уже говорили некоторые другие, вы хотите использовать блок 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 next, также не будет работать (опять-таки в IOException - поскольку файл не был удален, он все ещетам, что приведет к провалу движения).

3 голосов
/ 12 ноября 2009

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

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

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

1 голос
/ 12 ноября 2009

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

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

PS: «это» означает «ловящие попытки исключения».

...