2009-01-06 10 views
23

Tengo problemas con FxCop warning CA1006, Microsoft.Design "DoNotNestGenericTypesInMemberSignatures". Específicamente, estoy diseñando una clase ReportCollection<T> que hereda de ReadOnlyCollection<Report<T>>, y su constructor public toma un IList<Report<T>> como parámetro.¿Hay alguna solución para FxCop warning CA1006?

La sugerencia para la fijación de esta advertencia no es muy útil:

"Para el montaje de una violación de esta regla, cambiar el diseño para eliminar el argumento de tipo anidado". Hay dos maneras en que puedo ver lo que va a cambiar el diseño como se sugiere:

  1. hacer que el constructor internal. Esto no funciona en mi caso. El constructor debe ser public porque esta clase de colección necesita ser instanciable por código fuera del ensamblado.
  2. Haga que el constructor tome Report<T>[] en lugar de IList<Report<T>>. Esto no es óptimo porque el código externo debe tener la flexibilidad de usar estructuras de datos de tamaño dinámico como List<T> en lugar de matrices de tamaño fijo.

En este punto, he renunciado y suprimido esta advertencia. ¿Hay una mejor solución?

Respuesta

20

Estoy de acuerdo, otro buen momento para hacer caso omiso de esta regla es cuando se necesita decir:

Func<IEnumerable<T>> 

, por supuesto, se puede utilizar el IEnumerable no genérico, pero entonces cualquier tipo se puede utilizar siempre y cuando implementa IEnumerable (no genérico). El objetivo de los genéricos (en parte) es restringir los tipos que son permisibles para un conjunto determinado de tipos.

Creo que esta regla es muy estúpida. solo lo necesita si tiene múltiples tipos genéricos anidados. una capa de anidación es más que segura.

Por cierto, creo que muchos de las funciones nido LINQ tipos genéricos, así, así que si lo hace MS, podemos también :)

+3

No pondría ningún límite al nivel "seguro" de anidación. Los tipos genéricos deben anidarse sin importar qué tan profunda sea la semántica. Las limitaciones en el soporte de interfaces para covarianza y contravarianza significan que el código que espera, p. un 'IDictionary >' no podrá aceptar un 'IDictionary >', pero cuando los genéricos anidados son semánticamente correctos, preferiría usarlos en lugar de tratar de evitarlos. – supercat

30

Tomaría las advertencias de FxCop como si fueran sugerencias de un compañero de trabajo extremadamente atento al anal. Está perfectamente bien ignorar (suprimir) algunas de las cosas que sugiere.

+2

+1 también es una advertencia de diseño, así que a veces estos realmente pueden ser clasificados como estética, especialmente si no está diseñando una API pública –

4

Estoy de acuerdo que se puede ignorar la advertencia CA1006 en el caso de

Func<IEnumerable<T>> 

también se puede simplificar el código mediante el uso de delegados y evitar la 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 problema con el uso de delegados en lugar de 'Func <>' es que Visual Studio no le dará una pista sobre la definición de un delegado personalizado en la misma ventana emergente que la firma de la función principal, mientras que 'Func' es fácil inferir un lambda para. Por supuesto, esto es un problema IDE en lugar de un problema de idioma. – Dai

Cuestiones relacionadas