Alkampfer's Place

Il blog di Gian Maria Ricci
posts - 659, comments - 871, trackbacks - 80

My Links

News

Gian Maria Ricci Mvp Logo CCSVI in Multiple Sclerosis

English Blog

Tag Cloud

Article Categories

Archives

Post Categories

Image Galleries

I miei siti

Siti utili

VB e C# cugini ma non fratelli :D

Il VB ed il C# sono linguaggi simili, ma hanno le loro sottili differenze, vediamo ad esempio i due snippet sottostanti.

Prima di tutto si noti come il Vb non richiede nessun cast per convertire il valore della variabile O di tipo object in un Double, mentre il C# richiede un cast.

Se li si esegue lo snippet VB viene visualizzato "D2 = 34", mentre lo snippet C# genera InvalidCastException. Se qualcuno rimanesse stupito di questo comportamento si consideri che quando A viene messo in O1 c'è un operazione di boxing e quindi L'istruzione (Double) 01 è una operazione di unboxing che chiaramente fallisce dato che tenta di unboxare un Int32 come Double. Se non siete convinti ecco cosa trovate disassemblando l'eseguibile: L_000f: unbox.any float64 se consultate la documentazione della unbox.any vedrete che se il tipo di dato boxato non corrisponde si genera errore. Questo si traduce nella regola d'oro: durante una operazione di unboxing in C# le conversioni implicite non funzionano. L'istruzione corretta è

In questo caso correttamente indichiamo al compilatore di effettuare una operazione di unbox di un Int32, una volta effettuata il compilatore effettua il cast implicito a double, il codice IL ora è il seguente

L_000f: unbox.any int32
L_0014: conv.r8

Come potete vedere la unbox è ora corretta, a seguire ha una conversione a Double. Per finire il discorso qualcuno si potrà chiedere perché in VB funziona tutto senza cast; ecco l'IL generato: L_000f: call float64 [Microsoft.VisualBasic] Microsoft.VisualBasic.CompilerServices.Conversions::ToDouble(object), come potete vedere il vb passa per una funzione particolare che effettua la conversione a double e quindi tratta il valore O come object, naturalmente le performance in questo caso non sono proprio ottimali. Per avere in VB lo stesso comportamento del C# dobbiamo utilizzare un DirectCast a integer, in questo caso anche nell'IL generato da vb troviamo l'opcode unbox.

Spero di non avervi tediato :D

Alk.

Print | posted on sabato 22 settembre 2007 12:12 | Filed Under [ .NET ]

Feedback

Gravatar

# Re: VB e C# cugini ma non fratelli :D

non capisco perchè non metti questi post direttamente sul Muro, ma bisogna cliccarci sopra.
22/09/2007 12:47 | Igor Damiani
Gravatar

# re: VB e C# cugini ma non fratelli :D

Perchè nel caso di post un po lunghetti, con immagini dentro, preferisco mettere solo la descrizione breve :D, in questo modo il muro risulta più snello. Magari chi ha monitor non proprio enormi riesce a vedere tutto il contenuto del muro in meno schermate :P...poi magari mi sbaglio e mi faccio troppi problemi :D

Alk.
22/09/2007 12:57 | Gian Maria
Gravatar

# re: VB e C# cugini ma non fratelli :D

Non vorrei essermi perso qualcosa, ma credo che la sola differenza sia che di default VB continua a mantenere Option Strict Off e quindi effettua la conversione implicitamente.

Impostando Option Strict On infatti, anche VB non effettua più la conversione implicita e sarebbe necessario scrivere il seguente codice:

Dim a As Int32 = 34
Dim o As Object = a
Dim d As Double = DirectCast(o, Double)

che porta allo stesso comportamento di C#.

Ciao!
23/09/2007 14:51 | Mario Duzioni
Gravatar

# re: VB e C# cugini ma non fratelli :D

Si si, è proprio questo il problema. il VB di default ha l'option strict off è per questo che esegue, purtroppo, le conversioni in modo implicito anche quando servirebbe invece un cast. Sinceramente avrei preferito che il default fosse "option strict On" anzi, avrei preferito che non ci fosse proprio la possibilità di avere un option strict off :D

Alk.
23/09/2007 23:33 | Gian Maria
Gravatar

# re: VB e C# cugini ma non fratelli :D

Option Strict Off é "IL MALE". Penso che venga mantenuto solo per continuare a sfamare i programmatori VB6 che non vogliono adattarsi a .NET... Non puoi fare un paragone tra VB con option strict off e C#! :-(
Se tu avessi impostato option strict On avresti lo stesso comportamento in VB (InvalidCastException) se usassi l'equivalente Directcast (che si limita a fare un cast di interfacce e non una conversione):
Dim D2 As Double = DirectCast(O, Double)
Tutto filerebbe liscio usando il più flessibile CType in VB (che però é da paragonare ad un Convert.To in C#).
Il motivo per cui il codice C# si blocca (Idem il VB corretto) é che cerchi di fare l'unboxing di un tipo int verso un tipo double: la forma corretta sarebbe stata l'unboxing nel tipo corretto e lasciare poi che la conversione automatica avesse il suo effetti:
Double D2 = (Int32) O1;
equivalente VB:
Dim D2 As Double = DirectCast(O, Int32)
24/09/2007 14:10 | Michele Bernardi
Gravatar

# re: VB e C# cugini ma non fratelli :D

Sisi, proprio come ho detto "durante una operazione di unboxing in C# le conversioni implicite non funzionano" questa è una cosa che però per i meno esperti talvolta genera perplessità :D. PEr quanto riguarda option strict OFF = "Il male" sono prettamente daccordo, però purtroppo quello è il default, per cui VB.NET di default è un linguaggio con option strict = off, per cui quando faccio confronti solitamente confronto i linguaggi con le impostazioni di default :D. Personalmente non ho nemmeno un progetto in cui tengo option strict = OFF.

Alk.
25/09/2007 10:31 | Gian Maria
Gravatar

# re: VB e C# cugini ma non fratelli :D

Beh, per essere pignolo non si tratta di un'operazione di unboxing, ma di cast esplicito, ed equivale in VB.NET a un Directcast.
26/09/2007 02:29 | Michele Bernardi
Gravatar

# re: VB e C# cugini ma non fratelli :D

Il problema è proprio invece l'unboxing, dato che Il valore originario (un Int32 e quindi un value type) viene messo in una variabile Object (quindi viene boxato), non posso fare poi un cast in c# (o un directCast in Vb) ad un Double, perchè durante gli unboxing le operazioni di conversione non vengono effettuate. Dall'IL generato l'istruzione unbox.any float64 è inequivocabile, ma comunque ogni qualvolta faccio un cast da un object ad un value type sto facendo un'operazione di unboxing e non un semplice cast. :P

Alk.
26/09/2007 10:40 | Gian Maria
Comments have been closed on this topic.

Powered by:
Powered By Subtext Powered By ASP.NET