2009-01-06 5 views
23

J'ai des problèmes avec FxCop warning CA1006, Microsoft.Design "DoNotNestGenericTypesInMemberSignatures". Plus précisément, je conçois une classe ReportCollection<T> qui hérite de ReadOnlyCollection<Report<T>> et son constructeur public prend un IList<Report<T>> en tant que paramètre.Y a-t-il de bonnes solutions de contournement pour l'avertissement FxCop CA1006?

La suggestion de fixer cet avertissement est pas très utile:

« Pour corriger une violation de cette règle, modifier la conception pour supprimer l'argument de type imbriqué. » Il y a deux façons que je peux voir à ce jour pour changer la conception comme l'a suggéré:

  1. constructeur rendre le internal. Cela ne fonctionne pas dans mon cas. Le constructeur doit être public car cette classe de collection doit être instanciable par du code en dehors de l'assembly.
  2. Faites en sorte que le constructeur prenne un Report<T>[] au lieu d'un IList<Report<T>>. C'est sous-optimal car le code externe devrait avoir la flexibilité d'utiliser des structures de données de taille dynamique comme List<T> au lieu de tableaux de taille fixe.

À ce stade, j'ai abandonné et supprimé cet avertissement. Y a-t-il une meilleure solution?

Répondre

20

Je suis d'accord, un autre bon moment pour ignorer cette règle est lorsque vous devez dire:

Func<IEnumerable<T>> 

Vous pouvez bien sûr utiliser le IEnumerable, mais non générique alors tout type peut être utilisé aussi longtemps qu'il implémente IEnumerable (non générique). Le but des génériques (en partie) est de restreindre les types qui sont permis à un ensemble donné de types. Je pense que cette règle est très stupide. N'en avez besoin que si vous avez plusieurs types génériques imbriqués. une couche de nidification est plus que sûre.

BTW, je pense que beaucoup de types génériques nid Fonctions LINQ et, donc si MS fait, nous pouvons aussi :)

+3

Je ne mettrais aucune limite au niveau d'imbrication "sûr". Les types génériques devraient être imbriqués aussi profondément que la sémantique l'exige. Les limitations sur le support des interfaces pour la covariance et la contravariance signifient que le code qui attend par ex. un 'IDictionary >' ne sera pas en mesure d'accepter un 'IDictionary >', mais lorsque les génériques imbriqués sont sémantiquement corrects je préfère les utiliser plutôt que d'essayer de les contourner. – supercat

30

Je prendrais les avertissements de FxCop comme s'ils étaient des suggestions d'un collègue extrêmement rétentif anale. Il est parfaitement possible d'ignorer (supprimer) certaines des choses qu'il suggère.

+2

+1 Il est également un avertissement de conception, donc parfois ceux-ci peuvent vraiment être classés comme esthétique, surtout si vous n'êtes pas concevoir un API publique. –

4

Je suis d'accord que vous pouvez ignorer l'avertissement de CA1006 dans le cas de

Func<IEnumerable<T>> 

vous pouvez également simplifier votre code en utilisant les délégués et éviter le CA1006:

public delegate IEnumerable<T> ChildrenDel<T>(T parent); 

// was: GetDescendants<T>(this T item, Func< T, IEnumerable<T> > children) 

public static IEnumerable<T> GetDescendants<T>(this T item, ChildrenDel<T> children) 
{ 
    var stack = new Stack<T>(); 
    do { 
     children(item).ForEach(stack.Push); 

     if(stack.Count == 0) 
      break; 

     item = stack.Pop(); 

     yield return item; 
    } while(true); 
} 
+0

Un problème avec l'utilisation de délégués au lieu de 'Func <>' est que Visual Studio ne vous donnera pas un indice sur la définition d'un délégué personnalisé dans le même popup que la signature de fonction parente - alors que 'Func' est facile à déduire lambda pour. Certes, il s'agit d'un problème IDE plutôt que d'un problème de langue. – Dai

Questions connexes