2009-03-19 8 views
17

Question sur les meilleures pratiques.C# imbriqué Essayez des instructions ou des méthodes Catch?

Si vous imbriquez, essayez des instructions catch ou utilisez simplement des méthodes. Par exemple, si vous avez une méthode qui ouvre un fichier fonctionne et ferme le fichier, vous auriez l'ouverture et la fermeture en dehors du try catch, ou plutôt la fermeture dans le bloc finally.

Maintenant, si votre méthode ouverte échoue, la méthode s'affirmerait? Donc, est-ce que votre enveloppe doit être dans un bloc catch ou doit-elle être appelée à partir d'une autre méthode, qui est elle-même un bloc try catch?

+0

exemple de code à illustrer votre question. – Alan

+0

tout échantillon (meilleur réel) code pour illustrer la question? – Kiquenet

Répondre

4

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

Dans le cas du fichier ouvert, j'utiliserais un détenteur IDisposable et une clause using, et ainsi renoncerais au besoin de tout essai/catch explicite.

7

Ceci est une question de style mais pour moi, j'essaie de ne jamais avoir plus d'un niveau d'essai/attraper/finalement imbriquer dans une seule méthode. Au moment où vous essayez un essai imbriqué, vous avez presque certainement violé le principe d'opération 1 function = 1 et devriez utiliser une seconde méthode.

+3

Je pense que dans beaucoup, sinon la plupart des développeurs, ce ne sera pas une question de style. Il s'agira de ne pas comprendre les exceptions dans .NET, et de penser qu'il faut saisir toutes les exceptions, comme dans Java. Dans la plupart des cas, il est préférable de laisser l'exception se propager. –

15

Dans le contexte d'une méthode qui ouvre un fichier, j'utiliserais une instruction using plutôt qu'une tentative try. L'instruction using garantit que Dispose est appelé si une exception se produit.

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(); 
} 
+3

Fermez, mais le code try/finally ne correspond pas tout à fait au code utilisé. Vous devez également l'inclure dans un bloc de portée anonyme. –

1

La plupart du temps, je briser les blocs try/catch imbriquées dans des fonctions. Mais j'ai parfois écrit du code pour attraper et consigner toutes les exceptions non interceptées lancées par mon application. Mais que faire si le code de journalisation échoue? J'ai donc encore un autre essai/catch autour de cela juste pour empêcher l'utilisateur de voir la boîte de dialogue d'exception .NET non gérée par défaut. Mais même ce code pourrait très facilement être refactorisé 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

Si votre journalisation est cassée, alors vous devriez laisser l'exception se propager afin que l'utilisateur puisse se plaindre que votre journalisation est cassée! –

+0

Je peux toujours afficher l'exception générée par le code de journalisation. C'est juste que je veux le faire au lieu de laisser apparaître la fenêtre d'erreur du framework. –

+0

un bon exemple de modèle utilisant l'action ? – Kiquenet

11

Maintenant que nous avons lambdas et l'inférence de type et d'autres choses, il y a un idiome qui est commun dans d'autres langues qui fait maintenant beaucoup de sens en C#. Votre exemple consistait à ouvrir un fichier, à faire quelque chose, puis à le fermer. Eh bien, maintenant, vous pouvez faire une méthode d'assistance qui ouvre un fichier, et prend également soin de s'assurer de fermer/éliminer/nettoyer, mais appelle à un lambda que vous fournissez pour la partie "faire des choses". Cela vous aidera à obtenir les trucs complexes essayer/attraper/éliminer/nettoyer en un seul endroit, puis l'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. 
    } 
} 

Maintenant, les appelants de cette méthode n'ont pas à se soucier de la façon d'ouvrir le fichier ou fermer/en disposer. Ils peuvent faire quelque chose comme ceci:

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

puis-je mettre "while" code dans une méthode d'une autre classe? – Kiquenet

+0

@alhambraeidos, si je vous comprends bien, oui, vous pouvez absolument. Vous pourriez faire une méthode appelée "ForEachLine", qui ouvre le fichier, fait une boucle while pour le lire ligne par ligne, et appelle la fonction que vous passez sur chaque ligne. –

+0

Comme ceci: MyHelperClass4Files.ForEachLine (f); ?? – Kiquenet

3

Que diriez-vous où vous avez le code associé qui ne lui appartient pas nécessairement dans une fonction séparée de son propre droit? Est-ce que ce serait 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 
} 
-2
try 
{ 
    ---- 
} 
catch 
{ 
    try 
     { 
      --- 
     } 
    catch 
     { 
     --- 
     } 
} 
+0

Pourquoi est-ce donné un vote négatif? –

0
//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érifier l'interrupteur, si elle est encore nul à ce point, alors vous pouvez arrêter votre programme ici; sinon, remettez le commutateur à zéro et exécutez votre instruction try catch suivante. totalement d'accord avec les décomposer comme mentionné ci-dessus

essayez { DoChunk2(); // a l'air bien. réglez le commutateur à 1 } catch (Exception ex) { // Connectez l'exception ici }

Questions connexes