2009-04-07 7 views

Répondre

2

Les éléments suivants sont effectivement les mêmes (dans les résultats):

catch (Exception e) 
{ 
    FunctionA(e); 
    FunctionB(e); 
} 

Mais ce n'est pas la même chose si vous faites ceci:

catch (ApplicationException e) 
{ 
    FunctionB(e); 
} 
catch (Exception e) 
{ 
    FunctionA(e); 
} 

C'est parce que FunctionB se tapée à ApplicationException au moment de la compilation , où l'appel à FunctionA va toujours réduire le paramètre à Exception. Selon votre implémentation de FunctionB, cela peut ne pas importer, mais il y a des cas où cela peut faire la différence. Je dirais qu'en règle générale, si votre implémentation de méthode n'a pas besoin de l'implémentation générique, ne l'utilisez pas.

Voici quelques exemples de cas où il serait question:

public T AddSomeContextToThisException<T>(T ex) where T : Exception 
{ 
    ex.Data.Add("Some key", "Some context message"); 
    return ex; 
} 

public T ThisIsABadIdeaForExceptionsButMaybeAGoodIdeaForOtherTypes<T>(T ex) where T : Exception, new() 
{ 
    // do something with ex 

    return new T(); 
} 

L'exemple suivant a besoin d'un code supplémentaire pour le contexte, donc voir le code dessous:

private readonly Bar bar = new Bar(); 

public void HandExceptionOffToSomethingThatNeedsToBeStronglyTyped<T>(T ex) where T : Exception 
{ 
    ICollection<T> exceptions = bar.GetCollectionOfExceptions<T>(); 
    exceptions.Add(ex); 

    // do other stuff 
} 

public class Bar 
{ 
    // value is object, because .net doesn't have covariance yet 
    private Dictionary<Type, object> listsOfExceptions = new Dictionary<Type, object>(); 

    public ICollection<T> GetCollectionOfExceptions<T>() 
    { 
     if (!listsOfExceptions.ContainsKey(typeof(T))) 
     { 
      listsOfExceptions.Add(typeof(T), new List<T>()); 
     } 
     return listsOfExceptions[typeof(T)] as List<T>; 
    } 
} 
+0

Si ApplicationException était une sous-classe d'Exception, ne seraient-ils pas toujours les mêmes? Essaie/Attrape les blocs que je comprends; Cependant, je suis plus préoccupé par s'il y a des différences ou des avantages entre les deux. – JamesEggers

+0

Si vous ne pouvez pas voir un avantage dans la mise en œuvre, alors il n'y a aucun avantage et très peu de différence. Voir la réponse de @ Samuel et mon commentaire à ce sujet pour certains cas où cela est important. –

+0

Je comprends maintenant. Merci. – JamesEggers

2

A l'intérieur des fonctions, il serait pas de différence. La différence vient de l'extérieur. Si vous utilisez la fonction générique, vous pouvez renvoyer le même type d'exception au code appelant au lieu de la base Exception. Dans la plupart des cas, c'est un point discutable.

+0

Les questions relatives au type de retour, ainsi qu'à la création d'objets génériques dans l'implémentation elle-même. En outre, si les contraintes génériques contiennent un "nouveau()", alors aussi pour créer de nouvelles instances de T. Vous avez raison de dire que cela n'est pas pertinent dans la plupart des cas, cependant. –

+0

Compte tenu de ses deux définitions, il n'y a aucune différence à l'intérieur de la méthode. Il ne peut pas faire d'autres suppositions en plus d'être de type Exception. Mais cela ne l'empêche pas de retourner le type générique. – Samuel

1

Il n'y a pas beaucoup d'un avantage que FunctionB a plus fonctionn. Cependant, il existe une différence nette entre les deux. Avec FunctionA, vous pouvez transmettre tout type dérivé d'une (ou d'une) exception dans la fonction. Avec FunctionB, vous pouvez transmettre tout type dérivé de T (qui doit provenir de ou être une exception) dans la fonction. Cela signifie qu'en fonction du type de T, vous aurez un paramètre plus spécialisé qui limitera les types que vous pouvez lui passer, car le paramètre sera tapé T, pas Exception. Maintenant, si T est une exception, alors ce n'est pas grave, les fonctions sont les mêmes. Cependant, si T est une exception InvalidOperationException, seules les instances de InvalidOperationException (et les classes qui en dérivent) sont autorisées.

Ceci est généralement ce que vous voulez quand vous voulez assurer la spécialisation d'un type sans avoir à recourir à des classes de base qui ne fournissent pas le niveau de spécialisation dont vous avez besoin.

Questions connexes