簡體   English   中英

何時使用 try/catch 塊?

[英]When to use try/catch blocks?

我已經閱讀並理解了 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);

    }
}

}

捕獲異常的基本經驗法則是當且僅當您有一種有意義的方法來處理異常時才捕獲異常

如果您只想記錄異常並將其拋出堆棧,請不要捕獲異常。 它沒有任何意義並且使代碼混亂。

當你在你的代碼的特定部分期待一個失敗不要捕獲異常,如果你有這方面的后備。

當然,您總是會遇到需要使用 try/catch 塊的檢查異常情況,在這種情況下,您別無選擇。 即使有已檢查的異常,請確保正確記錄並盡可能干凈地處理。

就像其他人所說的那樣,您希望在代碼周圍使用 try-catch 塊,這些代碼可以拋出您准備處理的Exception和代碼。

關於您的特定示例, File.Delete可以拋出許多異常,例如IOExceptionUnauthorizedAccessException 在這些情況下,您希望您的應用程序做什么? 如果您嘗試刪除該文件但其他人正在使用它,您將收到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 next 也將失敗(再次出現IOException - 由於文件沒有被刪除,它仍然存在,這將導致移動失敗)。

我被教導將 try/catch/finally 用於任何可能發生多個錯誤並且您可以實際處理. 數據庫事務、文件系統 I/O、流等。核心邏輯通常不需要 try/catch/finally。

try/catch/finally 最重要的部分是您可以有多個捕獲,以便您可以創建一系列異常處理程序來處理非常具體的錯誤或使用一般異常來捕獲您看不到的任何錯誤。

在您的情況下,您使用的是 File.Exists,這很好,但它們可能是磁盤的另一個問題,可能會引發 File.Exists 無法處理的另一個錯誤。 是的,這是一個布爾方法,但是如果文件被鎖定,如果您嘗試寫入它會發生什么? 有了 catch,您可以為罕見的情況做計划,但如果沒有 try/catch/finally,您可能會將代碼暴露在完全無法預料的情況下。

其他人給出了很多很好的指示和參考。

我的輸入很簡短:
何時使用它是一回事,同樣或更重要的是如何正確使用它。

PS:“它”是對“嘗試捕獲異常”的引用。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM