2010-08-06 5 views
4

J'essaie d'éviter de retourner une valeur incorrecte lorsque dans la prise, mais je vais avoir du mal à trouver une meilleure solution que celle-ci:meilleures pratiques pour Try Catch Error Handling

private SecurityLevel ApiGetSecurityLevel() 
    { 
     try 
     { 
      return _BioidInstance.GetSecurityLevel(); 
     } 
     catch 
     { 
      return SecurityLevel.High; 
     } 
    } 

Y at-il une meilleure façon de Ce faisant, je ne retourne pas de valeurs incorrectes? Je ne peux pas changer l'enum de SecurityLevel.

+0

Une petite explication de ce qu'est une "valeur correcte" en cas d'exception, s'il vous plaît? –

+0

Est-il possible que votre niveau de sécurité dans _BioidInstance soit défini sur autre chose que ce qui est dans l'énumération SecurityLevel? – duraz0rz

+1

Ceci est une routine fail-mortelle. Il devrait être failsafe: retourner SecurityLevel.None; –

Répondre

12

Ne pas attraper l'exception. Autoriser l'exception à "bulle" pour forcer l'appelant/les appelants à gérer la définition de la valeur de sécurité par défaut.


Si vous voulez vraiment retourner une valeur ou utilisez Nullable<SecurityLevel>SecurityLevel?.

private SecurityLevel? ApiGetSecurityLevel() { 
    try { 
     return _BioidInstance.GetSecurityLevel(); 
    } 
    catch { 
     return null; 
    } 
} 

Ensuite, utilisez comme:

if (ApiGetSecurityLevel().HasValue == false) { 
    // use default security level 
} 
+0

supposé qu'il veut mettre en cache le retour avant de valider sa valeur dans un if, sinon il devrait le réexécuter pour récupérer la valeur qui pourrait signifier un autre coup de DB. –

+0

@Jimmy Hoffa, ne comprends pas votre commentaire. Quel DB a frappé? Quelle indication vous donne l'impression que OP veut mettre en cache le retour? – AMissico

+0

S'il ne voulait pas mettre en cache le retour de la méthode, il ferait retourner la méthode true ou false au lieu d'une valeur identifiable. –

1

Vous pourriez ne rien retourner. Et faites que votre fonction regarde le résultat comme si non ApiGetSecurityLevel() est rien

+0

Oui. Ceci est une mauvaise utilisation d'un bloc catch. Ils servent à attraper des exceptions spécifiques. MAIS, essayez d'utiliser IsNot au lieu de Not object IsNothing. – StingyJack

+0

Il dit SecurityLevel est une énumération, donc Nothing ('null' en C#) n'est pas une valeur valide. – Justin

+0

Pepin a une bonne idée pour cette limitation. – StingyJack

6

Est-il possible que c'est un cas où la demande devrait échouerait? C'est-à-dire, si le SecurityLevel ne peut pas être déterminé, l'utilisateur ne devrait pas pouvoir continuer?

Si oui, pourquoi ne pas simplement relancer et laisser l'interface utilisateur le gérer (ou le laisser se connecter, mais votre boutique fonctionne)?

Si l'application doit pouvoir continuer, choisissez (et documentez) une valeur par défaut et faites exactement ce que vous faites.

1

Vous pourriez laisser l'exception monter en flèche.

+0

Ou, mieux, l'attraper et le relancer en tant qu'exception interne d'une "AuthorizationException". De toute façon, échouer avec une exception, pas une valeur de retour. –

0

Vous pouvez l'envelopper dans une de vos propres énumérations et les traduire vers la vôtre. Alors le vôtre pourrait contenir un niveau de sécurité "invalide" et vous éviteriez d'utiliser des types blackboxed.

1

En plus de la réponse de Matt, quoi de mal à laisser l'exception se produire? S'il y a une invalidité d'état ou d'accès dans votre application, il vaudrait probablement mieux le tuer.

2

Si vous pouvez changer le type de retour de la fonction, je vais le changer en une énumération Nullable et retourner null dans le catch.

private SecurityLevel? ApiGetSecurityLevel() 
{ 
    try 
    { 
     return _BioidInstance.GetSecurityLevel(); 
    } 
    catch 
    { 
     return null; 
    } 
} 
+0

Tout cela ne fait que pousser l'exception vers le haut: elle va lancer quand elle déréférencera la valeur. –

5

Tout d'abord, il n'y a aucune raison pour que try/catch aussi longtemps que GetSecurityLevel retourne un SecurityLevel. Le compilateur va attraper tous les problèmes là-bas. Deuxièmement, ce n'est pas une bonne utilisation d'essayer/attraper. Try/catch ne doit jamais être utilisé pour un flux de contrôle normal, seulement dans des cas exceptionnels.

Si, pour une raison quelconque, GetSecurityLevel() ne retourne pas un type SecurityLevel enum:

private SecurityLevel ApiGetSecurityLevel() 
    { 
     object securityLevel = _BioidInstance.GetSecurityLevel(); 
     if (securityLevel is SecurityLevel) 
     { 
      return _BioidInstance.GetSecurityLevel(); 
     } 
     else 
     { 
      throw new Exception("Invalid SecurityLevel"); 
     } 
    } 
0
public class BioId { public SecurityLevel SecLevel { get; set; } } 

private bool ApiGetSecurityLevel(BioId bioId) 
{ 
    try 
    { 
     bioIdSecLevel = bioId.GetSecurityLevel(); 
     return true; 
    } 
    catch (PossibleException) 
    { 
     return false; 
    } 
} 

utiliser ensuite avec un si et si elle retourne false, puis laisser le code de manutention décider de la securitylevel par défaut pour son BioId.Bien que je sois d'accord avec tout le monde, en pratique, vous voulez juste laisser la bulle d'exception et laisser les niveaux supérieurs les gérer. Bien que parfois il y ait des normes pour ne pas laisser les exceptions bouillonner parce que chaque couche qu'elles traversent peut apparemment frapper la performance, mais à cela je dis que vous ne devriez pas avoir trop de calques de toute façon, les oignons sont complexes, comme les ogres.

+0

Des exceptions ne sont faites que dans des circonstances exceptionnelles, c'est-à-dire pas très souvent. Par conséquent, ils n'ont aucun impact sur les performances lorsqu'ils sont utilisés de manière appropriée. –

+0

De toute façon, il s'agit d'une non-réponse, car ils doivent retourner ce niveau, pas un booléen. Peut-être voulez-vous en faire un paramètre de sortie et utiliser une métaphore Try. –

0

Si vous pouvez ajouter une énumération Nothing/NotSet à SecurityLevel, vous pouvez la renvoyer à partir du bloc catch. Retourner des privs escaladés quand vous ne pouvez pas les déterminer est un choix vraiment étrange.

Vous pouvez également renvoyer SecurityLevel sous la forme d'une énumération Nullable.

private SecurityLevel? ApiGetSecurityLevel() 
{ 
    try 
    { 
     return _BioidInstance.GetSecurityLevel(); 
    } 
    catch 
    { 
     return null; 
    } 
} 
0
SecurityLevel sec = _BioidInstance.GetSecurityLevel(); 
return (Enum.IsDefined(Typeof(SecurityLevel), sec) ? sec : SecurityLevel.High); 

Il retournera le niveau de sécurité dans _BioidInstance si elle est définie dans le ENUM, sinon elle retournera SecurityLevel.High.

Si c'était moi, si je savais que le niveau de sécurité ne peut pas être en dehors de ce qui est défini dans l'énumération, je ferais juste sans try-catch et je l'abandonnerais s'il y arrivait. De cette façon, je sais que quelque chose d'autre s'est mal passé et je peux y remédier.

0

Dans ce cas, la sécurité devient binaire.

Pour utiliser un exemple de composé sécurisé, quelqu'un peut entrer ou non à la porte. S'ils ne parviennent pas à obtenir un niveau de sécurité, cette personne ne devrait pas passer à travers la porte.

Si la méthode GetSecurityLevel() lève une exception, quelque chose a été refusé à la porte. Accorder ensuite un niveau de sécurité arbitraire et les autoriser à passer n'est pas une bonne idée.

Je abolirait cette méthode complètement, et le remplacer par quelque chose de plus proche de

private bool HasSecurityLevel(SecurityLevel securityLevel) 
{ 
    try 
    { 
     return _BioidInstance.GetSecurityLevel() == securityLevel; 
    } 
    catch 
    { 
     return false; 
    } 
} 

puis vérifier pour chaque niveau de sécurité sur une base selon les besoins. La raison pour cela est que le contrôle doit être fait à un certain point, peut aussi bien le rendre aussi proche de la source (au premier niveau de sécurité) que possible.