2009-07-31 11 views
14

Ho un metodo di un oggetto che è qualcosa come una fabbrica. Gli dai un tipo, crea un'istanza e fa alcune altre cose. Un modo elegante per farlo (a mio parere) è come questo:Come passare un tipo a un metodo - Tipo argomento vs generici

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

Ma questo sconvolge FxCop che dice che questo è un cattivo stile - ricevo un "CA1004: metodi generici dovrebbero fornire parametro di tipo" warning. Qualcosa sul non usare l'inferenza e cose del genere. Quindi, l'unico altro modo mi viene in mente è qualcosa di simile:

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

Credo che questo sia inferiore al primo metodo su molti conti, ma la regola di stile ... L'articolo di MSDN sul sistema di allarme, dice ancora che non c'è motivo per sopprimerlo.

Sto facendo bene sopprimendo questo avviso, dopo tutto?

+0

completamente frainteso la tua domanda così ho cancellata la mia risposta. –

+1

Va bene, visto che non ho mai visto la tua risposta.:) –

risposta

3

FxCop avvertimenti sono solo che - avvertimenti. Proprio come gli avvertimenti impliciti del cast, servono a farti sapere che qualcosa che stai facendo può avere un comportamento che non stai anticipando, o potrebbe non essere quello che intendi.

Un cast di avviso implicito viene esaminato esaminando il codice, determinando se si è realmente intenzionati a farlo e, in tal caso, aggiungendo un cast esplicito.

Stessa cosa con FXCop. Guarda l'avviso, guarda il tuo codice e determina se l'avviso è valido. Se lo è, aggiustalo. Se no, sopprimilo. Una soppressione è l'equivalente di un cast esplicito: "Sì, FXCop, sono sicuro di volerlo fare".

Se fosse davvero un errore, probabilmente sarebbe un errore del compilatore.

+6

Sì, ma la pagina MSDN con i dettagli di questo avviso indica esplicitamente che "non si dovrebbe sopprimere questo avviso". Onestamente, sono più intelligente della saggezza collettiva della squadra FXCop? –

0

Il secondo approccio non è nemmeno equivalente al primo. Nella seconda, ti viene dato letteralmente un tipo ma non puoi istanziare un oggetto di quel tipo (a meno che non usi Reflection --- eeek!) E devi dichiarare esplicitamente il tipo restituito (che sconfigge lo scopo dei generici iniziare con).

Vedere la nota this per sopprimerlo. Sembra che sia ok per sopprimere.

MODIFICA: Ora ecco un'altra idea. Cosa succede se lo hai modificato in un parametro 'out' e non lo hai restituito tramite la variabile return? Rimuoverà l'avvertimento allora?

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

Probabilmente, ma non sarebbe molto comodo da usare. :) –

+0

Vero, non posso criticarti. –

0

Personalmente mi preoccuperei con la maggior parte degli avvisi in Fxcop.

Ti sembra di sapere cosa si sta facendo, perché avrebbe qualche pezzo automatizzata di software conoscere meglio?

Beh, non posso, è una supposizione.

+1

Beh, ho pensato che molti sviluppatori più talentuosi ed esperti di me hanno scritto quello strumento, e se dicono che non dovrei farlo, forse non dovrei. :) –

15

Credo che stai incomprensione quello FxCop vi sta dicendo, probabilmente perché la sua formulazione è proprio l'ideale. Ciò significa che un metodo generico dovrebbe fornire un parametro che è di tipo, non che un metodo generico debba avere un overload non generico che fornisce un'istanza di runtime Type. Ad esempio,

public void DoSomething<T>(T myParam); 

Il myParam è il tipo di parametro si riferisce a. La ragione per cui vuole questo è, come lei suggerisce, per inferenza. Questo permette di fare qualcosa di simile ...

string foo = "bar"; 

DoSomething(foo); 

invece di dover scrivere

DoSomething<string>(foo); 

Nel tuo caso, è bene per eliminare l'avviso dal momento che si desidera all'utente di specificare esplicitamente la genere. Vorrei comunque suggerire (supponendo che i costruttori non siano parametrici) di cambiare il tuo where in where T : SomeBaseClass, new(). Ciò significa che dirigerà il compilatore a richiedere che qualsiasi tipo venga passato abbia un costruttore senza parametri. Questo significa anche che puoi fare new T() nel tuo codice.

+0

Beh ... in realtà, non è esattamente un costruttore ... chiama in un'altra libreria di terze parti dove do il tipo come parametro Type semplice, e quindi costruisce l'oggetto ... Ma questi sono comunque dettagli non necessari . :) –

5

Non avrei alcun problema con la soppressione di questo avviso. Per cominciare l'equivalente in proprio codice di MS è Activator.CreateInstance<T>()

public static T CreateInstance<T>() 

Ciò implica che la regola di analisi dovrebbe valutare se il tipo ritorno del metodo è coperto dal parametro generico ...

Questo è stato citato in molti luoghi prima:

E ci sono stati errori precedenti nella regola, ad esempio:

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

precedenza sarebbe innescare (fixed in 2005 SP1).

suggerisco deposito di un bug di connessione per il vostro esempio specifico

+0

Phew. Quindi non sono solo io! :) –

0

Prima di tutto, questo avviso è solo per assicurarsi che i chiamanti facciano tutto consapevolmente. È possibile chiamare il metodo senza passare alcun parametro di tipo perché il compilatore conosce il tipo dell'oggetto prima della mano. FxCop ti sta dicendo di lasciarlo implicito in modo che la sintassi per l'utilizzo di overload generici e non generici sia identica (non sono d'accordo con questo principio, ma è personale e non pertinente qui).

In secondo luogo, il tuo secondo metodo farà più danni di quanto tu possa pensare in questo momento. Non vi è alcun tipo di controllo in fase di compilazione, quindi tieni presente le eccezioni di cast non valide durante l'esecuzione se lo utilizzi.

1

FxCop sparerà questo avvertimento, anche se si utilizza il parametro di tipo generico in uno o più degli argomenti, se non è "spogliato":

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

Almeno regola 'CA1004' licenziato "in errore "qui l'altro giorno su un metodo con questa firma.

Per essere più intelligente rispetto alla squadra FxCop, non sono sicuro che le regole sono in grado di determinare correttamente il codice in tutti i casi, questo è ciò che il livello di confidenza è per :)

Problemi correlati