何时使用try / catch块?

时间:2009-11-12 15:19:12

标签: c# .net exception-handling try-catch

我已完成阅读并了解Try / Catch块的功能以及使用它的重要性。但我坚持认识 when / where 来使用它们。有什么建议?我将在下面发布我的代码示例,希望有人有时间为我的示例提出一些建议。

    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 个答案:

答案 0 :(得分:72)

捕获例外的基本经验法则是捕获例外当且仅当你有一个有意义的处理方式

如果您只是记录异常并将其抛出堆栈,请不要捕获异常。它没有任何意义和杂乱的代码。

当您预计代码的特定部分出现故障时,会发现异常,如果您有后备的话。

当然,您总是遇到需要使用try / catch块的已检查异常的情况,在这种情况下您没有其他选择。即使检查了异常,也要确保正确记录并尽可能干净地处理。

答案 1 :(得分:7)

答案 2 :(得分:4)

就像其他一些人所说的那样,你想在代码中使用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
    }

还要记住,如果这确实失败了,那么你在if块之外执行的File.Move也将失败(再次发生IOException - 因为文件没有删除它仍然存在会导致移动失败)。

答案 3 :(得分:3)

我被教导使用try / catch / finally来处理可能发生多个错误的任何方法/类,以及你可以实际处理。数据库事务,FileSystem I / O,流等。核心逻辑通常不需要try / catch / finally。

关于try / catch / finally的重要部分是你可以拥有多个catch,这样你就可以创建一系列异常处理程序来处理非常特定的错误,或者使用一般异常捕获任何东西你看不到的错误。

在你的情况下,你正在使用File.Exists这是好的,但它们可能是磁盘的另一个问题,可能会抛出File.Exists无法处理的另一个错误。是的,它是一个布尔方法,但是说文件被锁定了,如果你试着写它会发生什么?有了catch,你可以计划一个罕见的场景,但是没有try / catch / finally,你可能会将代码暴露给完全不可预见的条件。

答案 4 :(得分:1)

其他人提供了很多好的指针和参考资料。

我的输入很简短:
何时使用它是一回事,同样或更重要的是如何正确使用它。

PS:“它”是对“试图捕捉异常”的反思。