web-dev-qa-db-fra.com

C # imbriqué Essayez des instructions ou des méthodes Catch?

Simple question de bonne pratique.

Si vous nidifiez, essayez les instructions catch ou utilisez simplement des méthodes.

Par exemple, si une méthode qui ouvre un fichier fonctionne et ferme le fichier, l'ouverture et la fermeture se feraient en dehors de la capture try, ou plutôt de la fermeture dans le bloc finally.

Maintenant, si votre méthode ouverte échoue, la méthode affirmerait juste? Alors, faut-il envelopper cela dans un bloc catch try ou faut-il l'appeler depuis une autre méthode, qui à son tour est un bloc catch catch?

17
ghost

Dans le contexte d'une méthode qui ouvre un fichier, j'utiliserais une instruction using vs un try catch. L'instruction using garantit que Dispose est appelé en cas d'exception.

using (FileStream fs = new FileStream(file, FileMode.Open))
{
    //do stuff
}

fait la même chose que:

FileStream fs;
try
{
     fs = new FileStream(file, FileMode.Open);
     //do Stuff
 }
 finally
 {
        if(fs!=null)
           fs.Dispose();
 }
15
cgreeno

Maintenant que nous avons lambdas, des inférences de types et d'autres éléments, il existe un idiome courant dans d'autres langages qui a maintenant beaucoup de sens en C #. Votre exemple visait à ouvrir un fichier, à y remédier, puis à le fermer. Eh bien, maintenant, vous pouvez créer une méthode d’aide qui ouvre un fichier et s’assure également de fermer/supprimer/nettoyer, mais appelle un lambda que vous fournissez pour la partie "faire des choses". Cela vous aidera à mettre les trucs compliqués d’essai/attraper/finalement jeter/nettoyer à un endroit précis, puis à les utiliser encore et encore.

Voici un exemple:

public static void ProcessFile(string filePath, Action<File> fileProcessor)
{
  File openFile = null;

  try
  {
    openFile = File.Open(filePath); // I'm making this up ... point is you are acquiring a resource that needs to be cleaned up after.

    fileProcessor(openFile); 
  }
  finally
  {
    openFile.Close(); // Or dispose, or whatever.
  }
}

Désormais, les appelants de cette méthode n'ont pas à s'inquiéter de la façon d'ouvrir le fichier ou de le fermer/en disposer. Ils peuvent faire quelque chose comme ça:

Helpers.ProcessFile("C://somefile.txt", f => 
 {
   while(var text = f.ReadLine())
   {
     Console.WriteLine(text);
   }
 });
11
Charlie Flowers

C’est une question de style, mais j’essaie de ne jamais avoir plus d’un niveau d’essay/attrape/finalement dans une seule méthode. Au moment où vous frappez un essai imbriqué, vous avez presque certainement violé le principe 1 fonction = 1 et vous devez utiliser une deuxième méthode.

7
JaredPar

Cela dépend de ce que vous essayez de faire, mais dans la plupart des cas, les tentatives imbriquées imbriquées sont le signe d'une fonction trop complexe (ou d'un programmeur qui ne sait pas trop comment fonctionnent les exceptions!).

Dans le cas du fichier ouvert, j'utiliserais un titulaire IDisposable et une clause using, et j'éviterais ainsi la nécessité de tout essai/blocage explicite.

4
Pontus Gagge

Et si vous avez un code associé qui n'appartient pas nécessairement à une fonction distincte de son droit? Serait-ce alors correct?

try
{
  // Part 1 Code Here

  try
  {
    // Part 2 Code Here
  }
  catch (Exception ex)
  {
    // Error from Part 2
  }
}
catch (Exception ex) 
{
  // Error from Part 1
} 
3
Sean

La plupart du temps, je divisais les blocs try/catch imbriqués en fonctions. Mais j'ai parfois écrit du code pour capturer et consigner toutes les exceptions non capturées générées par mon application. Mais que se passe-t-il si le code de connexion échoue? Donc, j'ai encore un autre essai/attraper autour de cela juste pour empêcher l'utilisateur de voir la boîte de dialogue par défaut des exceptions non gérées .NET. Mais même ce code pourrait très facilement être transformé en fonctions au lieu de blocs try/catch imbriqués.

try
{
    try
    {
        DoEverything(); 
    }
    catch (Exception ex)
    {
        // Log the exception here
    }
}
catch (Exception ex)
{
    // Wow, even the log is broken ...
}
1
Brian Ensink
//create a switch here and set it to 0 
try
{
    DoChunk1(); 
    //looks good. set the switch to 1
}
catch (Exception ex)
{
    // Log the exception here
}

// vérifie le commutateur, s'il est toujours égal à zéro à ce stade, vous pouvez arrêter votre programme ici; sinon, remettez le commutateur à zéro et exécutez votre prochaine instruction try catch. totalement d'accord pour les décomposer comme mentionné ci-dessus

try {DoChunk2 (); //Cela semble bon. positionnez le commutateur sur 1} catch (Exception ex) {// Enregistrez l'exception ici}

0
Ronan Masangcay