2009-07-31 12 views
14

Tengo un método de un objeto que es algo así como una fábrica. Le das un tipo, crea una instancia y hace algunas otras cosas. Una forma elegante de hacerlo (en mi opinión) es la siguiente:Cómo pasar un tipo a un método - Tipo argumento vs genéricos

public T MagicMethod<T>() where T: SomeBaseClass 
{ 
    // Magic goes here 
} 

Pero esto trastorna FxCop que dice que este es un mal estilo - me sale un "CA1004: métodos genéricos deben proporcionar parámetro de tipo" advertencia. Algo sobre no ser para usar la inferencia y esas cosas. Por lo tanto, la única manera en que puedo pensar es algo como esto:

public SomeBaseClass MagicMethod(Type T) 
{ 
    // Same magic goes here 
} 

Creo que éste es inferior al primer método en muchas cuentas, pero la regla de estilo ... El artículo de MSDN sobre la advertencia incluso dice que no hay razón para suprimirlo.

¿Estoy haciendo las cosas bien por la supresión de esta advertencia después de todo?

+0

completamente entendido mal su pregunta así que he borré mi respuesta. –

+1

Está bien, ya que nunca vi su respuesta.:) –

Respuesta

3

FXCop son sólo eso - advertencias. Al igual que las advertencias de conversión implícitas, sirven para informarle que algo que está haciendo puede tener un comportamiento que no está anticipando, o puede no ser el que pretendía.

Una advertencia implícita de lanzamiento se soluciona mirando el código, determinando si de verdad tenía la intención de hacerlo y, de ser así, agregando un molde explícito.

Lo mismo con FXCop. Mire la advertencia, mire su código y determine si la advertencia es válida. Si es así, arreglarlo. Si no, suprímalo. Una supresión es el equivalente de un elenco explícito: "Sí, FXCop, estoy seguro de que quiero hacer esto".

Si realmente fue un error, probablemente sería un error del compilador.

+6

Sí, pero la página MSDN con los detalles de esta advertencia establece explícitamente que "no debe suprimir esta advertencia". Honestamente, ¿soy más inteligente que la sabiduría colectiva del equipo de FXCop? –

0

El segundo enfoque no es ni siquiera equivalente a la primera. En el segundo, literalmente se te da un tipo, pero no se puede crear una instancia de un objeto de ese tipo (a menos que uses Reflection --- eeek!) Y tienes que declarar explícitamente el tipo de devolución (que derrota el propósito de los genéricos para empezar con).

Ver this nota sobre la supresión de la misma. Parece que está bien suprimir.

EDITAR: Ahora, aquí hay otra idea. ¿Qué pasaría si lo cambiaras a un parámetro de "salida" y no lo devolvieras a través de la variable de devolución? ¿Eliminaría la advertencia entonces?

public void MagicMethod<T>(out T retVar) where T: SomeBaseClass 
{ 
    // Magic goes here 
} 
+0

Probablemente, pero eso no sería muy cómodo de usar. :) –

+0

Es cierto, no puedo culpar a eso. –

0

Personalmente me molestaría con la mayoría de las advertencias en Fxcop.

Parece saber lo que está haciendo, ¿por qué alguna pieza de software automatizado de conocer mejor?

Bueno, no puede, es una conjetura.

+1

Bueno, pensé que desarrolladores mucho más talentosos y experimentados que yo han escrito esa herramienta, y si dicen que no debería hacerlo, tal vez no debería hacerlo. :) –

15

creo que estés malentendido lo FxCop le está diciendo, probablemente debido a que su redacción es menos que ideal. Lo que significa es que un método genérico debería proporcionar un parámetro que es de ese tipo, no que un método genérico debe tener una sobrecarga no genérica que proporcione una instancia de tiempo de ejecución Type. Por ejemplo,

public void DoSomething<T>(T myParam); 

El myParam es el tipo de parámetro que se está refiriendo a. La razón por la que quiere esto es, como sugiere, para la inferencia. Esto le permite hacer algo como ...

string foo = "bar"; 

DoSomething(foo); 

en lugar de tener que escribir

DoSomething<string>(foo); 

En su caso, está bien suprimir la advertencia ya que desea el usuario para especificar explícitamente el tipo. Yo sugeriría, sin embargo (suponiendo que sus constructores no tengan parámetros) que cambie su where al where T : SomeBaseClass, new(). Esto significa que dirigirá al compilador para requerir que cualquier tipo que se transmita tenga un constructor sin parámetros. Esto también significa que puede hacer new T() en su código.

+0

Bueno ... en realidad, no es exactamente un constructor ... llama a otra biblioteca de terceros donde le doy el tipo como un simple parámetro Tipo, y que luego construye el objeto ... Pero esos son detalles innecesarios de todos modos . :) –

5

No tendría ningún problema para suprimir esta advertencia. Para empezar, el equivalente en propio código de MS es Activator.CreateInstance<T>()

public static T CreateInstance<T>() 

Esto implica que la regla de análisis debe considerar si el tipo de retorno del método está cubierto por el parámetro genérico ...

Ésta ha sido mencionado en muchos lugares antes:

Y ha habido errores anteriores en la regla, por ejemplo:

public static void GenericMethod<T>(List<T> arg); 

anteriormente daría lugar a que (fixed in 2005 SP1).

que sugieren la presentación de un error de conexión para su ejemplo específico

advertencias
+0

Phew. ¡Entonces no soy solo yo! :) –

0

En primer lugar, esa advertencia es solo para asegurarse de que los llamantes hagan todo a sabiendas. Es posible llamar a su método sin pasar ningún parámetro de tipo porque el compilador conoce el tipo de objeto de antemano. FxCop te está diciendo que lo dejes implícito para que la sintaxis para usar sobrecargas genéricas y no genéricas se vea idéntica (no estoy de acuerdo con ese principio, pero eso es personal y no relevante aquí).

En segundo lugar, su segundo método hará más daño de lo que puede pensar en este momento. No hay ningún tipo de tiempo de compilación comprobando allí, así que ten cuidado con las excepciones de lanzamiento no válidas en tiempo de ejecución si lo usas.

1

FxCop se disparará esa advertencia, incluso si usted hace uso del parámetro de tipo genérico en uno o más de los argumentos, si no se "despojó":

public void LinkedList<T> Slice<T>(LinkedList<T> collection, Predicate<T> match) 
{ 
    ... 
} 

Al menos regla 'CA1004' despedido "de error "aquí el otro día en un método con esta firma.

Para ser más inteligente que el equipo FxCop, no estoy seguro de que las reglas son capaces de determinar correctamente el código en todos los casos, eso es lo que el nivel de confianza es para :)

Cuestiones relacionadas