2009-07-02 6 views
10

Ho un gestore eventi che deve determinare un tipo ed eseguire codice se corrisponde a un tipo specifico. Inizialmente lo abbiamo lanciato su un oggetto e se non era nullo abbiamo eseguito il codice, per accelerarlo ho usato il reflection e in realtà lo ho rallentato e non capisco perché.Perché la trasmissione è più veloce della riflessione in .NET?

ecco un esempio di codice

Trace.Write("Starting using Reflection"); 
if (e.Item.GetType() == typeof(GridDataItem)) 
{ 
     bool isWatch = Convert.ToBoolean(e.Item.OwnerTableView.DataKeyValues[e.Item.ItemIndex]["IsWatch"]); 
     if (isWatch) 
     { 
      e.Item.Style["Font-Weight"] = "bold"; 
     } 
} 
Trace.Write("Ending using Reflection"); 
Trace.Write("Starting using Cast"); 
GridDataItem gridItem = e.Item as GridDataItem; 
if (gridItem !=null) 
{ 
    bool isWatch = Convert.ToBoolean(gridItem.OwnerTableView.DataKeyValues[e.Item.ItemIndex]["IsWatch"]); 
    if (isWatch) 
    { 
     gridItem.Style["Font-Weight"] = "bold"; 
    } 
    } 
    Trace.Write("Ending using Cast"); 

e questo è l'output di analisi ottengo

Starting using Reflection 0.79137944962406 0.576538 
Ending using Reflection 0.791600842105263 0.000221 
Starting using Cast 0.791623353383459 0.000023 
Ending using Cast  0.791649308270677 0.000026 
Starting using Reflection 0.876253801503759 0.084604 
Ending using Reflection 0.87631790075188 0.000064 
Starting using Cast 0.87633445112782 0.000017 
Ending using Cast  0.87634950075188 0.000015 

non è molto, ma se abbiamo dovuto fare questo molto nel corso del tempo si potrebbe aggiungere su.

+3

_ Tutto ciò che potrebbe aggiungere nel tempo. A meno che tu non abbia le prove che questo _actually è-aggiungendo nel tempo, non sottolineo. –

+0

Si tratta di best practice, se il casting è più veloce allora dovrei usare casting invece di reflection –

+0

Questa logica non segue affatto. Se il cast è CORRETTO, dovresti usare il cast invece del riflesso. La correttezza è più importante della velocità. –

risposta

15

Il riflesso è lento perché si stanno interrogando i metadati dell'assieme mentre il cast semplicemente modifica il tipo dell'oggetto a cui si fa riferimento.

I metadati dell'assieme rappresentano un utile archivio di informazioni, ma le informazioni vengono utilizzate al momento piuttosto che al momento dell'esecuzione. Questi metadati sono usati dal compilatore per il controllo del tipo statico (tra le altre cose). Stai usando gli stessi metadati per cercare informazioni sul tipo al momento dell'esecuzione (che va bene se non hai altra scelta) che è molto più lento del cast.

3

Reflection deve andare in runtime e determinare quali proprietà ecc. L'oggetto ha in fase di esecuzione. La trasmissione dice all'applicazione che dovrebbe aspettarsi che un oggetto abbia proprietà X e debba funzionare in un certo modo.

2

La trasmissione indica al runtime di "conoscere" il tipo di un oggetto particolare. Anche se è probabile che tu stia sbagliando, il runtime ti crede e non impiega il tempo extra necessario per controllare i metadati dell'assembly.

1

Perché non stai utilizzando lo is operator? Penso che sia più leggibile visto che non hai il cast esplicito, quindi controlla. Controlla semplicemente che la variabile sia del tipo corretto.

+0

" è "fa un cast sotto le coperte. –

+0

Il mio punto era che semplifica il codice (rendendolo più leggibile), non che faccia qualcosa di fondamentalmente diverso. Chiarirò – tvanfosson

+0

Questo è effettivamente più lento \t Avvio \t 1.5268064962406 \t 1,311905 \t Ending \t 1,52701457443609 \t 0,000208 \t partire \t 1,59114193383459 \t 0,064127 \t Ending \t 1,59120311278195 \t 0,000061 –

0

Bene, ho una risposta breve alla parte migliore pratica non sarebbe mai utilizzare la riflessione se è possibile ottenere lo stesso risultato con il codice normale.

Quando si ottimizza il codice, di solito è una buona idea stimare dove il tempo impiegato per l'ottimizzazione comporterà il massimo guadagno di prestazioni. reimplementare gli operatori in modo nativo nella lingua raramente sarà in cima a tale elenco

1

I cast possono essere eseguiti come confronti tra interi all'interno del runtime ma la riflessione implica chiamate di metodo complete.