2009-01-06 6 views
23

Mam problem z FxCop warning CA1006, Microsoft.Design "DoNotNestGenericTypesInMemberSignatures". W szczególności projektuję klasę ReportCollection<T>, która dziedziczy po ReadOnlyCollection<Report<T>>, a jej konstruktor public przyjmuje jako parametr IList<Report<T>>.Czy są jakieś dobre obejścia dla ostrzeżenia FxCop CA1006?

Sugestia do mocowania to ostrzeżenie nie jest bardzo przydatne:

„Aby naprawić naruszenie tej zasady, zmienić projekt, aby usunąć zagnieżdżony typ argumentu”. Istnieją dwa sposoby widzę tak daleko, aby zmienić wygląd jak sugeruje:

  1. Złóż konstruktora internal. To nie działa w moim przypadku. Konstruktor musi być public, ponieważ ta klasa kolekcji musi być możliwa do przypisania przez kod spoza zestawu.
  2. Zmodyfikuj konstruktora jako Report<T>[] zamiast IList<Report<T>>. Jest to nieoptymalne, ponieważ kod zewnętrzny powinien mieć elastyczność korzystania z dynamicznych struktur danych, takich jak List<T> zamiast macierzy o ustalonych rozmiarach.

W tym momencie podałem i ukryłem to ostrzeżenie. Czy istnieje lepsze rozwiązanie?

Odpowiedz

20

zgadzam, kolejny dobry czas, aby zignorować tę regułę jest, kiedy trzeba powiedzieć:

Func<IEnumerable<T>> 

oczywiście można użyć nierodzajową IEnumerable, ale potem każdy typ może być stosowany tak długo, jak implementuje IEnumerable (non-generic). Celem generycznych (w części) jest ograniczenie typów, które są dozwolone dla danego zestawu typów.

Myślę, że ta zasada jest bardzo głupia. potrzebujesz go tylko, jeśli masz wiele zagnieżdżonych typów ogólnych. jedna warstwa zagnieżdżania jest więcej niż bezpieczna.

BTW, myślę, że wiele z LINQ Funkcje gniazdo typy generyczne, tak więc jeśli MS robi, możemy też :)

+3

Nie wprowadziłbym żadnego ograniczenia "bezpiecznego" poziomu zagnieżdżenia. Typy ogólne powinny być zagnieżdżone, jednak dogłębnie wymagają tego semantyki. Ograniczenia w obsłudze interfejsów dla kowariancji i kontrawariancji oznaczają, że kod, który oczekuje np. 'IDictionary >' nie będzie w stanie zaakceptować 'IDictionary >', ale gdy zagnieżdżone generics są semantycznie poprawne, wolałbym raczej używać ich zamiast próbować obejść je. – supercat

30

Ostrzegałbym FxCop o ostrzeżeniach, tak jakby były sugestiami ze strony bardzo skupionego na analnie współpracownika. Można zignorować (ukryć) niektóre z rzeczy, które sugeruje.

+2

+1 jest to również ostrzeżenie projekt, więc czasami mogą one zostać zakwalifikowane jako bardzo estetyczny zwłaszcza jeśli nie są projektowaniu publiczny interfejs API. –

4

Zgadzam się, że można zignorować ostrzeżenie CA1006 w przypadku

Func<IEnumerable<T>> 

ponadto można uprościć swój kod za pomocą delegatów i uniknąć 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

Problem z używaniem delegatów zamiast "Func <>" polega na tym, że Visual Studio nie daje wskazówki co do definicji niestandardowego elementu delegowanego w tym samym wyskakującym okienku, co sygnatura funkcji nadrzędnej - podczas gdy funkcja 'Func' pozwala łatwo uzyskać lambda dla. To prawda, że ​​jest to problem IDE, a nie problem językowy. – Dai