web-dev-qa-db-fra.com

Quand utiliser les blocs try / catch?

J'ai fait ma lecture et je comprends ce que fait un bloc Try/Catch et pourquoi il est important d'en utiliser un. Mais je suis coincé à savoir quand/où pour les utiliser. Aucun conseil? Je posterai un échantillon de mon code ci-dessous dans l'espoir que quelqu'un ait le temps de faire des recommandations pour mon exemple.

    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

La règle de base pour intercepter les exceptions est de intercepter les exceptions si et seulement si vous avez un moyen significatif de les gérer.

N'attrapez pas une exception si vous allez seulement enregistrer l'exception et la jeter dans la pile. Il ne sert à rien et encombre le code.

Attrapez une exception lorsque vous vous attendez à un échec dans une partie spécifique de votre code, et si vous avez une solution de rechange.

Bien sûr, vous avez toujours le cas d'exceptions vérifiées qui vous obligent à utiliser des blocs try/catch, auquel cas vous n'avez pas d'autre choix. Même avec une exception vérifiée, assurez-vous de vous connecter correctement et de gérer le plus proprement possible.

81
Yuval Adam
7
Philip Wallace

Comme d'autres l'ont dit, vous voulez utiliser try catch block around du code qui peut lever une exception ET que vous êtes prêt à gérer.

Pour vous des exemples particuliers, File.Delete peut lever un certain nombre d'exceptions, y compris IOException, UnauthorizedAccessException ainsi que d'autres. Que voudriez-vous que votre application fasse dans ces situations? Si vous essayez de supprimer le fichier mais que quelqu'un d'autre l'utilise, vous obtiendrez une 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
    }

Gardez également à l'esprit que si cela échoue, le fichier File.Move que vous faites en dehors de votre bloc if échouera également (encore une fois à une exception IOException - puisque le fichier n'a pas été supprimé, il est toujours là, ce qui entraînera l'échec du déplacement) .

5
Ryan Elkins

On m'a appris à utiliser try/catch/enfin pour toutes les méthodes/classes où plusieurs erreurs pouvaient se produire et que vous pouvez réellement gérer. Transactions de base de données, E/S FileSystem, streaming, etc. La logique de base ne nécessite généralement pas try/catch/enfin.

La grande partie de try/catch/enfin est que vous pouvez avoir plusieurs captures afin de pouvoir créer une série de gestionnaires d'exceptions pour traiter très erreur spécifique ou utiliser une exception générale pour intercepter toutes les erreurs que vous faites vois pas venir.

Dans votre cas, vous utilisez File.Exists, ce qui est bien, mais c'est peut-être un autre problème avec le disque qui peut générer une autre erreur que File.Exists ne peut pas gérer. Oui, c'est une méthode booléenne, mais disons que le fichier est verrouillé et que se passe-t-il si vous essayez d'écrire dessus? Avec le catch, vous pouvez planifier un scénario rare, mais sans essayer/catch/enfin, vous pouvez exposer le code à des conditions complètement imprévues.

3
osij2is

Les autres gars ont donné un bon nombre de bons pointeurs et références.

Ma contribution est courte:
Quand l'utiliser est une chose, tout aussi ou plus important est de savoir comment l'utiliser correctement.

PS: "il" fait référence aux "exceptions qui tentent d'attraper".

0
o.k.w