2009-05-14 9 views
8

provare il seguente codiceImpossibile (o abilitato) alla lista <int>. Più veloce <Enum>()?

public enum Color 
{ 
    Blue=1, 
    Red=2, 
    Green=3 
} 

public List<Color> ConvertColorEnum() 
{ 
    var intColor = new List<int>(){1,2,3}; 
    return intColor.Cast<Color>().ToList(); 
} 

Pensi che il ConvertColorEnum() restituirà un elenco di colore, vale a dire, List<Color>(){Color.Blue, Color.Red, Color.Green}?

L'ho provato su 2 macchine, una con .net 3.5 (versione mscorlib 2.0.50727.1433), un'altra con .net 3.5 SP1 (versione mscorlib 2.0.50727.3082). I risultati sono stati diversi: il .net 3.5 ha gettato un InvalidCastException perché non è possibile convertire il numero intero in enum, mentre .net 3.5 SP1 potrebbe essere eseguito correttamente, con risultati corretti restituiti.

Chiunque vorrebbe provare questo sulla sua macchina e segnalare il risultato o spiegare perché è così?

risposta

4

È possibile leggere la differenza tra SP1 e la versione originale del .net 3.5 framework in the release notes.

Qui è quello che dice per questo particolare problema:

in LINQ espressioni di query oltre collezioni non generici come System.Collections.ArrayList, il da clausola della query viene riscritto da la compilatore per includere una chiamata all'operatore di cast . Cast converte tutti i tipi di elemento nel tipo specificato nella clausola from nella query . Inoltre, nella versione originale di Visual C# 2008, l'operatore di cast esegue anche alcune conversioni di tipo valore e conversioni definite dall'utente . Tuttavia, queste conversioni vengono eseguite da utilizzando la classe System.Convert invece della semantica C# standard. Queste conversioni causano anche significativi problemi di prestazioni in determinati scenari .In Visual C# 2008 SP1, l'operatore Cast viene modificato per generare un InvalidCastException per il tipo di valore numerico e le conversioni definite dall'utente . Questa modifica elimina sia la semantica non standard del cast di C# sia il problema di prestazioni. Questa modifica è illustrata nell'esempio seguente .

È inoltre possibile ottenere ulteriori dettagli in this blog post.

17

Se si desidera che funzioni in entrambi i modi, utilizzare invece Select.

return intColor.Select(i=>(Color)i).ToList(); 

Per quanto riguarda il perché ...? metodo di estensione

+0

@marc, sto per dire grats sul 50K ma il tuo dolorosamente vicino a 49.999;) –

+0

Vexing, non è vero? –

+0

Buona idea, ma non pensi che intColor.Cast () sia più sintetico e leggibile? – Graviton

4

L'Cast fa uso di un iteratore che, sulla prossima mossa, memorizza l'uscita del enumeratore originale in una variabile oggetto (così boxe come necessario) quindi tenta di gettare che al tipo di risultato.

I tipi di valore in forma di box non rispondono all'operazione di cast nello stesso modo in cui lo farebbero se fossero unbox (dove sono possibili diverse conversioni automatiche), invece consentono solo il casting alla loro forma originale non condivisa.

Immagino che la precedente attuazione dell'estensione cast era o facendo in modo completamente diverso o aveva qualche involucro speciale per tipi enum da convertire in forma integrale (questo è difficile in quanto si deve trattare con tutte le forme possibili)

La risposta di Marc alla soluzione corretta è completamente corretta ed è in realtà più efficiente del cast in ogni caso per i motivi di boxe sopra menzionati.

+0

Ah sì, 5__ab - Non ho notato quello ;-p –

+0

facile da perdere - devo amare i nomi sintetizzati del compilatore, Spero che MS abbia reso più semplice caricare l'intera sorgente - Forse dovrei scrivere un plugin per riflettore soemtime per prenderlo dal server dei simboli ... – ShuggyCoUk

Problemi correlati