web-dev-qa-db-ja.com

いつ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'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);

    }
}

}

35
fieldingmellish

例外をキャッチするための基本的な経験則は、例外をキャッチであり、かつ例外を処理する意味のある方法がある場合です。

例外をログに記録してスタックにスローするだけの場合は、例外をキャッチしない。それは意味をなさず、コードを散らかします。

Doコードの特定の部分で障害が発生すると予想され、フォールバックがある場合は、例外をキャッチします。

もちろん、常にチェック例外のケースがあり、try/catchブロックを使用する必要があります。この場合、他に選択肢はありません。チェックされた例外がある場合でも、適切にログに記録し、できるだけきれいに処理するようにしてください。

81
Yuval Adam
7
Philip Wallace

他の人が言ったように、例外をスローする可能性があり、対処する準備ができているコードの周りで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が発生します-ファイルが削除されていないため、ファイルがまだそこにあるため、移動が失敗します)。 。

5
Ryan Elkins

複数のエラーが発生する可能性のあるすべてのメソッド/クラスおよび実際に処理できるに対してtry/catch/finallyを使用するように教えられました。データベーストランザクション、FileSystem I/O、ストリーミングなど。コアロジックは通常、try/catch/finallyを必要としません。

Try/catch/finallyの優れた点は、複数のキャッチを使用できるため、一連の例外ハンドラーを作成してvery特定のエラーを処理するか、一般的な例外を使用して、発生しないエラーをキャッチできることです。来ない。

あなたの場合、あなたはFile.Existsを使用していますが、これはディスクに関する別の問題であり、File.Existsが処理できない別のエラーをスローする可能性があります。はい、それはブール方式ですが、ファイルがロックされていると言い、それに書き込もうとするとどうなりますか?キャッチを使用すると、まれなシナリオを計画できますが、try/catch/finallyを使用しないと、コードを完全に予期しない状況にさらす可能性があります。

3
osij2is

他の連中はかなりの数の良い指針と参考文献を与えてきた。

私の入力は短いものです:
いつ使用するかが重要であり、同等またはそれ以上に重要なのは、それを適切に使用する方法です。

PS:「それ」は「試行錯誤の例外」を意味します。

0
o.k.w