2009-07-15 14 views
25

Un collega mi ha fatto una domanda interessante oggi - la parola chiave/operatore C# "è" considerata come riflessione?C# "è" operatore - è quella riflessione?

object tmp = "a string"; 
if(tmp is String) 
{ 
} 

Come viene implementato questo operatore dietro le quinte? Richiede riflessione o introspezione? Oppure a causa della natura fortemente tipizzata del linguaggio, il tipo dell'oggetto è immediatamente accessibile come attributo di primo livello dell'oggetto in memoria?

MSDN precisa che:

noti che l'operatore is considera solo le conversioni di riferimento, conversioni boxe e conversioni unboxing. Altre conversioni, come le conversioni definite dall'utente, non sono considerate dall'operatore is.

La possibilità di considerare conversioni in scatola e non in scatola sembra implicarmi una sorta di introspezione.

+0

correlato http://stackoverflow.com/questions/57701/che cosa-are-il-performance-caratteristiche-di-is-reflection-in-c?lq=1 – nawfal

risposta

31

Referencing ECMA-335, l'operatore is genera il isinst oggetto del modello di istruzioni IL (partizione III §4.6), che fa parte delle istruzioni di base impostato invece di essere parte della libreria riflessione (partizione IV §5.5).

Modifica: L'operatore is è estremamente efficiente rispetto alla libreria di riflessione. Si potrebbe eseguire fondamentalmente lo stesso test molto più lentamente attraverso la riflessione:

typeof(T).IsAssignableFrom(obj.GetType()) 

Edit 2: Non sei corretto circa l'efficienza dei castclass e isinst istruzioni (che ora che hai a cura fuori del post). Sono altamente ottimizzati in ogni pratica implementazione VM. L'unico problema di prestazioni reale è il potenziale per castclass di generare un'eccezione, che si evita utilizzando l'operatore C# as e un test per null (per i tipi di riferimento) o l'operatore is seguito da un cast (per i tipi di valore).

+0

Non ho modificato nulla, ma forse dovrei chiarire cosa intendo per "costoso". Non so molto dell'efficienza dell'IL, ma FxCop ha un avvertimento se il tuo codice di creazione che emette sia un'istruzione isinst sia una istruzione castclass poiché lo considerano inefficiente o "costoso". –

+2

Come ho menzionato nella seconda modifica, dovresti usare 'as' seguito da un controllo' null' per i tipi di riferimento. Hai invece usato 'is' seguito da un cast, che è ciò a cui FxCop ti sta avvisando. –

+2

Per quello che vale, su Compact Framework, IL che deve controllare esplicitamente RTTI (come 'isinst' e' castclass') è lento come il riflesso, mentre callvirt è altamente ottimizzato. La morale: cerca di evitare l'uso di costrutti di tipo maiuscolo in cui i metodi virtuali/astratti possono funzionare. –

5

L'operatore is determina essenzialmente se un cast è possibile, ma invece di generare un'eccezione quando il cast è impossibile restituisce false. Se consideri il riflesso del cast, questo è anche un riflesso.

EDIT:

Dopo alcune ricerche ho scoperto che un cast viene eseguita in IL på istruzioni castclass mentre i is mappe operatore alle istruzioni isinst. FxCop ha un rule che ti avvisa se stai facendo lanci non necessari usando prima l'isinst e poi l'istruzione castclass. Anche se le operazioni sono efficienti, hanno ancora un costo in termini di prestazioni.

+0

'is' l'operatore restituisce vero/falso e non nullo. – SolutionYogi

+1

Penso che stai pensando all'operatore "as" – Matt

+0

Quello che hai descritto è l'operatore 'as'. L'operatore 'is' è essenzialmente la stessa operazione, solo con un valore di ritorno diverso. – Charlie

1

In altri linguaggi le informazioni sul tempo di esecuzione sono sufficienti per supportare la trasmissione dinamica e tuttavia nulla che possa essere descritto come riflessione (il C++ è un esempio ovvio).

Quindi la riflessione si riferisce a funzionalità aggiuntive oltre alla semplice scoperta del tipo di un oggetto. "Riflettere" su un oggetto implica la capacità di camminare per i suoi membri, ad esempio.

+0

Sarebbe * più * corretto dire che la riflessione sta analizzando i membri di una classe rispetto a quelli di un oggetto, dal momento che non è necessario avere un'istanza viva. Inoltre, la riflessione consente di "scoprire" quali classi si hanno in un assembly, non solo i membri e altre informazioni di una classe. –

+0

@Danny Varod - Non tutte le lingue hanno classi o assiemi. –

+0

C++ ha classi e librerie, Java ha classi e pacchetti. La programmazione orientata agli oggetti definisce la differenza tra un oggetto e una classe. –