2010-12-10 43 views

Répondre

7

Oui, en supposant que le problème pour lequel vous voulez le créer est en effet une situation exceptionnelle (c'est-à-dire devrait rarement se produire, si jamais). Si c'est une condition d'erreur normale (quelque chose que vous attendez se produira régulièrement et fait partie de l'utilisation normale de l'application), vous devriez le coder explicitement - dans ce cas, créer et lancer un exception personnalisée est une odeur de code.

De plus, créez uniquement une exception personnalisée si elle ajoute des informations (par rapport à celles intégrées).


Edit: (suite commentaires)

Utilisation gestion des exceptions comme une forme de contrôle du débit (ne fonction X complète correctement ou non) est à peu près toujours une mauvaise idée et est défini odeur de code.

+0

+1, à condition que vous attraper que si vous pouvez le manipuler :) – user7116

+0

Oded, Pouvez-vous ouvrir peut-être cela un peu plus; Ce que je voulais souligner ici, c'est abuser de l'exception d'une manière qui est facultative pour renvoyer d'autres informations à la place. Comme une alternative au type de retour réel de la méthode. Avez-vous eu mon sens? – pencilCake

+0

Ok! Maintenant, j'ai compris. Votre modification de votre réponse est plus claire pour moi maintenant. ;) Merci! – pencilCake

1

Vous devez créer vos propres exceptions personnalisées lorsque vous prévoyez d'effectuer une action en fonction du type d'exception levée. Si votre but est de montrer un message à l'utilisateur, le type d'exception renvoyé signifie très peu. Cependant, vous devez faire attention lorsque vous créez vos propres types d'exception car il existe déjà de très bons types d'exception dans la plate-forme .NET et vous devez en utiliser un en premier. Il est préférable d'avoir une exception FileNotFound par opposition à l'exception JoesBestFileNotFound.

+0

Je suggérerais le contraire: si une méthode 'DocumentLoad' lance une exception' DocumentFileNotFound' quand il ne parvient pas à charger un document, le code qui attrape cette exception peut savoir que le document n'a pas pu être chargé car le fichier * document * wasn pas trouvé.En revanche, si on se contentait de lancer 'FileNotFoundException', le code appelant ne sait pas si le fichier du document est introuvable ou si une DLL, un fichier de configuration ou un autre élément de ce type n'a pu être trouvé. – supercat

0

Généralement, vous ne devez pas utiliser d'exceptions pour la logique de programme normale. Il convient cependant de créer des exceptions pour les scénarios spécifiques à votre application. Il ya beaucoup de bons conseils là-bas pour la gestion des exceptions - prenez par exemple ce document MSDN exception design guidelines pour les débutants.

0

Si vous regardez le .NET FW, il existe de nombreux Exceptions pour spécifier certaines conditions. IndexOutOfBoundsException, NotImplementedException, etc ... Ils existent tous et sont dérivés de Exception pour traiter des cas exceptionnels (jeu de mots non prévu). Dessiner la ligne entre ce qu'il faut classer comme Exception par rapport à simplement retourner null par exemple peut souvent devenir gris. Utilisez votre meilleur jugement et essayez de rester constant au sein de l'équipe sur ce jugement.

1

Habituellement, vous pouvez vous débrouiller avec des exceptions standard. Si vous voulez fournir des informations de débogage plus utiles, les trucs de boost pourraient vous aider.

Vous souhaitez créer vos propres exceptions lorsque vous souhaitez fournir des informations qui vont au-delà de ce que vous offrent les autres options ou lorsque vous souhaitez que l'utilisateur puisse le gérer de manière unique. Si tout ce que vous faites est de mentionner qu'il y a une situation exceptionnelle alors utilisez simplement la roue qui est déjà là pour l'utiliser.

Je suggère toujours de hériter de std :: exception ou de l'une de ses dérivées.

1

Il est toujours préférable de coder sans possibilité de lancer des exceptions en premier lieu. Si vous avez besoin d'une raison: Ils sont lents. Quantifiablement plus lent que de coder autour d'eux de la manière la plus inélégante dans la plupart des cas. Cela étant dit, parfois, ils sont inévitables à cause du code que d'autres personnes ont écrit ou parce que vous voulez vraiment que le programme explose à la place de l'utilisateur (voir échec catastrophique). Ce n'est que dans ces deux cas que l'exception gère le chemin à parcourir.

Mais cela ne signifie pas que vous enveloppez tous IEnumerable<T>.First() dans un if(sequence.Count() > 0). Apprenez à bien structurer votre code, de sorte que vous n'appelez jamais le .First() sur une séquence vide en premier lieu. Le code élégant est la victoire.

j'ai écrit récemment une application rapide pour mon employeur à utiliser dans un système automatisé (où l'utilisateur ne siège pas au clavier) que doit demander à l'utilisateur d'entrer les informations de connexion dans args de ligne de commande (pensez fichier batch) ou un fichier de configuration sinon il explose intentionnellement dans leur visage, selon les spécifications. Dans ce cas, une exception est justifiée.

Tout le code ci-dessous démontre ma philosophie sur les exceptions. Un exemple de codage sans exception dans cette méthode d'extension que je viens d'écrire.

public static bool All<T>(this IEnumerable<T> list, Func<T, T, bool> func) 
    { 
     if (list.Count() < 2) 
      return true; 

     T first = list.First(); 

     return list.Skip(1).Aggregate(true, (i, k) => i && func(first,k)); 
    } 

avis ci-dessous, je traite des exceptions E/S dans le cadre de la méthode E/S, mais j'analysé les données contenues dans le fichier de configuration de telle sorte que ma logique ne sera jamais jeter une exception. Notez comment le .Count() est vérifié à 2 dans toutes les données. À ce stade, je peux être sûr que .First() et .Last() seront non seulement valables pour le compilier et ne pas jeter des exceptions, mais seront garanties pour donner des morceaux de données potentiellement valides (espaces non-blancs, valeurs différentes). C'est le genre de philosophie que je vous recommande d'adapter quand vous pensez à la gestion des exceptions ->Comment filtrer et contrôler mes données d'une manière référentielle transparente pour éliminer complètement les erreurs dans le cadre de la méthode?

public static class ConfigParser 
{ 
    public static Dictionary<string, string> PullFromConfigFile() 
    { 
     ParallelQuery<Tuple<string, string>> data; 

     try 
     { 
      TextReader tr = new StreamReader("config.cfg"); 

      data = tr.ReadToEnd() 
       .Split('\n') 
       .AsParallel() 

       .Select(i => new string(i.TakeWhile(k => k != '#').ToArray())) 
       .Where(i => !i.IsNullOrWhiteSpace()) 

       .Select(i => i.Split('\t') 
        .Where(k => !k.IsNullOrWhiteSpace()) 
        .Select(k => k.Trim()) 
       ) 
       .Where(i => i.Count() == 2) 
       .Select(i => new Tuple<string, string>(i.First(), i.Last())); 

      tr.Close(); 
     } 
     catch (IOException) 
     { 
      Logger.Bad("config.cfg file was not found"); 
      return new Dictionary<string, string>(); 
     } 
     return ConfigParser.ParseIntoDict(data); 
    } 

    private static Dictionary<string, string> ParseIntoDict(ParallelQuery<Tuple<string, string>> data) 
    { 
     var agg = new Dictionary<string, string>(); 
     foreach (var entry in data) 
     { 
      if (!agg.ContainsKey(entry.Item1)) 
       agg.Add(entry.Item1, entry.Item2); 
     } 

     var width = agg.Keys.Max(k => k.Length); 
     agg.ForAll(i => Logger.Log("Loaded Data: {0} {1}", 
      i.Key.SetWidth(width, '-'), i.Value)); 

     return agg; 
    } 
} 

extensions utilisées:

public static class Extensions 
{ 
    public static string SetWidth(this string item, int width, char padder, bool right = true) 
    { 
     if (item == null) 
      return new string(padder, width); 

     if (width > item.Length) 
      return right ? item.PadRight(width, padder) : item.PadLeft(width, padder); 
     return item.Substring(0, width); 
    } 
    public static bool IsNullOrWhiteSpace(this string str) 
    { 
     return string.IsNullOrWhiteSpace(str); 
    } 
}