Casting e conversioni di tipi di dati in VB.NET

Il casting è il processo di conversione di un tipo di dati in un altro, ad esempio, da un tipo Integer a un tipo String. Alcune operazioni in VB.NET richiedono tipi di dati specifici per funzionare. Il casting crea il tipo di cui hai bisogno. Il primo articolo di questa serie in due parti, Casting e conversioni del tipo di dati in VB.NET, introduce il casting. Questo articolo descrive i tre operatori che puoi usare per eseguire il cast in VB.NET - DirectCast, CType e TryCast - e confronta le loro prestazioni.

Quando utilizzare diverse operazioni di casting

Le prestazioni sono una delle grandi differenze tra i tre operatori di casting secondo Microsoft e altri articoli. Ad esempio, Microsoft è solitamente attenta a segnalare che "DirectCast ... può fornire prestazioni leggermente migliori rispetto a CType durante la conversione da e verso il tipo di dati Object". (Enfasi aggiunta.)

Ho deciso di scrivere del codice da controllare.

Ma prima una parola di cautela. Dan Appleman, uno dei fondatori della casa editrice di libri tecnici Apress e un guru tecnico affidabile, una volta mi ha detto che il benchmarking delle prestazioni è molto più difficile da eseguire correttamente di quanto la maggior parte delle persone non creda. Ci sono fattori come le prestazioni della macchina, altri processi che potrebbero essere eseguiti in parallelo, ottimizzazione come la memorizzazione nella cache della memoria o l'ottimizzazione del compilatore ed errori nelle tue ipotesi su ciò che il codice sta effettivamente facendo. In questi benchmark, ho cercato di eliminare gli errori di confronto "mele e arance" e tutti i test sono stati eseguiti con la build di rilascio. Ma potrebbero esserci ancora errori in questi risultati. Se ne noti qualcuno, fammelo sapere.

I tre casting operator sono:

  • DirectCast
  • CType
  • TryCast

DirectCast

In pratica, di solito scoprirai che i requisiti della tua applicazione determineranno l'operatore che utilizzi. DirectCast e TryCast hanno requisiti molto ristretti. Quando si utilizza DirectCast, il tipo deve essere già noto. Sebbene il codice ...

theString = DirectCast (theObject, String)

... verrà compilato correttamente se l'oggetto non è già una stringa, quindi il codice genererà un'eccezione di runtime.

TryCast

TryCast è ancora più restrittivo perché non funzionerà affatto su tipi "valore" come Integer. (String è un tipo di riferimento. Per ulteriori informazioni sui tipi di valore e sui tipi di riferimento, vedere il primo articolo di questa serie.) Questo codice ...

theInteger = TryCast (theObject, Integer)

... non verrà nemmeno compilato.

TryCast è utile quando non sei sicuro del tipo di oggetto con cui stai lavorando. Invece di generare un errore come DirectCast, TryCast restituisce semplicemente Nothing. La pratica normale è eseguire il test per Nothing dopo aver eseguito TryCast.

CType

Solo CType (e gli altri operatori "Converti" come CInt e CBool) convertiranno i tipi che non hanno una relazione di ereditarietà come un numero intero in una stringa:

Dim theString As String = "1"
Dim theInteger As Integer
theInteger = CType (theString, Integer)

Questo funziona perché CType utilizza "funzioni di supporto" che non fanno parte di .NET CLR (Common Language Runtime) per eseguire queste conversioni.

Ma ricorda che CType genererà anche un'eccezione se la stringa non contiene qualcosa che può essere convertito in un numero intero. Se c'è la possibilità che la stringa non sia un numero intero come questo ...

Dim theString As String = "George"

... allora nessun operatore di casting funzionerà. Anche TryCast non funzionerà con Integer perché è un tipo di valore. In un caso come questo, dovresti usare il controllo di validità, come l'operatore TypeOf, per controllare i tuoi dati prima di provare a trasmetterli.

Test della prestazione

La documentazione di Microsoft per DirectCast menziona specificamente il casting con un tipo di oggetto, quindi è quello che ho usato nel mio primo test delle prestazioni. Il test inizia nella pagina successiva!

DirectCast userà solitamente un tipo di oggetto, quindi è quello che ho usato nel mio primo test delle prestazioni. Per includere TryCast nel test, ho incluso anche un blocco If poiché quasi tutti i programmi che utilizzano TryCast ne avranno uno. In questo caso, tuttavia, non verrà mai eseguito.

Ecco il codice che confronta tutti e tre durante il cast di un oggetto su una stringa:

Abbassa il tempo come nuovo cronometro ()
Dim theString As String
Dim theObject As Object = "An Object"
Dim theIterations As Integer =
CInt (Iterations.Text) * 1000000
'
'DirectCast Test
theTime.Start ()
Per i = 0 alle iterazioni
theString = DirectCast (theObject, String)
Prossimo
theTime.Stop ()
DirectCastTime.Text =
theTime.ElapsedMilliseconds.ToString
'
"CType Test
theTime.Restart ()
For i As Integer = 0 To theIterations
theString = CType (theObject, String)
Prossimo
theTime.Stop ()
CTypeTime.Text =
theTime.ElapsedMilliseconds.ToString
'
'TryCast Test
theTime.Restart ()
For i As Integer = 0 To theIterations
theString = TryCast (theObject, String)
Se la stringa non è nulla, allora
MsgBox ("Questo non dovrebbe mai essere visualizzato")
End If
Prossimo
theTime.Stop ()
TryCastTime.Text =
theTime.ElapsedMilliseconds.ToString

Questo test iniziale sembra dimostrare che Microsoft ha ragione. Ecco il risultato. (Esperimenti con un numero sempre maggiore di iterazioni e test ripetuti in condizioni diverse non hanno mostrato differenze significative da questo risultato.)

DirectCast e TryCast erano simili a 323 e 356 millisecondi, ma CType ha impiegato tre volte più tempo a 1018 millisecondi. Quando si lanciano tipi di riferimento come questo, si paga per la flessibilità di CType nelle prestazioni.

Ma funziona sempre in questo modo? L'esempio di Microsoft nella loro pagina per DirectCast è principalmente utile per dirti cosa non funzionerà usando DirectCast, non cosa lo farà. Ecco l'esempio di Microsoft:

Dim q As Object = 2.37
Dim i As Integer = CType (q, Integer)
'La seguente conversione non riesce in fase di esecuzione
Dim j As Integer = DirectCast (q, Integer)
Dim f As New System.Windows.Forms.Form
Dim c As System.Windows.Forms.Control
'La seguente conversione ha esito positivo.
c = DirectCast (f, System.Windows.Forms.Control)

In altre parole, non puoi usare DirectCast (o TryCast, anche se non lo menzionano qui) per eseguire il cast di un tipo Object a un tipo Integer, ma puoi usare DirectCast per eseguire il cast di un tipo Form in un tipo Control.

Controlliamo le prestazioni dell'esempio di Microsoft di ciò che funzionerà con DirectCast. Utilizzando lo stesso modello di codice mostrato sopra, sostituire ...

c = DirectCast (f, System.Windows.Forms.Control)

... nel codice insieme a sostituzioni simili per CType e TryCast. I risultati sono un po 'sorprendenti.

DirectCast era effettivamente la più lenta delle tre scelte a 145 millisecondi. CType è solo un po 'più veloce a 127 millisecondi ma TryCast, incluso un blocco If, è il più veloce a 77 millisecondi. Ho anche provato a scrivere i miei oggetti:

Classe ParentClass
...
Classe finale
Classe ChildClass
Eredita ParentClass
...
Classe finale

Ho ottenuto risultati simili. Sembra che se non stai trasmettendo un tipo di oggetto, è meglio non usare DirectCast.