Nothing non è uguale a nullecco svelato il mistero
![]()
Nothing non è uguale a nullecco svelato il mistero
![]()
Pietro
Infatti ... mai detto che sono le stesse cose ...
Anzi, ho spostato il discorso sul null proprio perche' mi sembrava che ci fosse stato (come c'era) l'equivoco tra il nothing e il null ...![]()
Ma daiOriginariamente inviato da oregon
Infatti ... mai detto che sono le stesse cose ...
Anzi, ho spostato il discorso sul null proprio perche' mi sembrava che ci fosse stato (come c'era) l'equivoco tra il nothing e il null ...![]()
, sono io che ho bisogno di capire :master: Ma allora, mi dite che non esiste in basic l'analogo del c#, null
![]()
Pietro
Diciamo che Nothing se usato con i reference types è come null, se è usato con i value types no.
Amaro C++, il gusto pieno dell'undefined behavior.
Perfetto, ho capito il concetto.Originariamente inviato da MItaly
Diciamo che Nothing se usato con i reference types è come null, se è usato con i value types no.![]()
Pietro
I soliti casi particolari a-la-Microsoft, tanto per confondere un pochino le acque.Originariamente inviato da MItaly
Diciamo che Nothing se usato con i reference types è come null, se è usato con i value types no.
Scherzi a parte, mi piacerebbe conoscere il motivo di questa scelta con cui si attribuisce un comportamento apparentemente differente a Nothing (valore predefinito) in VB.NET, rispetto a C#. Immagino che un motivo ci sia (la prima frase era solo per ridere), e se qualcuno ha qualche riferimento o supposizione in proposito, la posti pure.
Programmo molto poco in VB.NET, più in C#, e questa cosa non la sapevo proprio, per quanto difficilmente mi sarebbe mai capitato di sperimentarla considerando il mio modus operandi di stendere il codice, in generale. Curioso, comunque.
Ciao!![]()
MARCO BREVEGLIERI
Software and Web Developer, Teacher and Consultant
Home | Blog | Delphi Podcast | Twitch | Altro...
Per quanto mi riguarda, questo è contemporaneamente un vero errore e orrore, detto da uno che usa ancora il basic. Il comportamento è del tutto innaturale, inutile e sopratutto dannoso, dato che può indurre a scrivere codice sbagliato.Originariamente inviato da alka
I soliti casi particolari a-la-Microsoft, tanto per confondere un pochino le acque.
Scherzi a parte, mi piacerebbe conoscere il motivo di questa scelta con cui si attribuisce un comportamento apparentemente differente a Nothing (valore predefinito) in VB.NET, rispetto a C#. Immagino che un motivo ci sia (la prima frase era solo per ridere), e se qualcuno ha qualche riferimento o supposizione in proposito, la posti pure.
Programmo molto poco in VB.NET, più in C#, e questa cosa non la sapevo proprio, per quanto difficilmente mi sarebbe mai capitato di sperimentarla considerando il mio modus operandi di stendere il codice, in generale. Curioso, comunque.
Ciao!![]()
![]()
Pietro
insomma, anche uno che usa il basic sa che...
Nothing ha senso solo come valore per variabili di tipi reference: i tipi reference infatti sono puntatori a istanze di classi situate nell'heap, e Nothing rappresenta un puntatore nullo (che non punta a nulla). Non ha senso invece assegnare Nothing ad una variabile di un tipo value, visto che questi tipi non sono puntatori.
Pietro
Una supposizione può essere che assegnare Nothing ad una variabile in VB.NET sia come azzerarla completamente; in C l'equivalente sarebbe
per cui un puntatore diventa un puntatore nullo, un intero viene impostato a 0, i membri di una struttura vengono azzerati (o "nullati", a seconda del loro tipo).codice:memset(&variabile, 0, sizeof(variabile);
D'altra parte il codice MSIL generato per il Main di questo programma
(che altro non è che una versione leggermente modificata del codice di esempio già citato) è il seguente:codice:Imports System Namespace Namespace1 Public Module Module1 Public Structure MyStruct Public Name As String Public Number As Short End Structure Public Class MyCl Public Name As String Public Number As Short End Class Public Function Main(ByVal arguments() As String) As Integer Dim S As MyStruct, I As Integer, B As Boolean, O As MyCl = New MyCl S = Nothing ' Sets S.Name to Nothing, S.Number to 0. I = Nothing ' Sets I to 0. B = Nothing ' Sets B to False. O = Nothing 'Sets O to null Return 0 End Function End Module End Namespace
.codice:.method public static int32 Main(string[] arguments) cil managed { .entrypoint .custom instance void [mscorlib]System.STAThreadAttribute::.ctor() = ( 01 00 00 00 ) // Code size 26 (0x1a) .maxstack 1 //dichiarazione variabili locali .locals init (bool V_0, //B As Boolean int32 V_1, //I As Integer int32 V_2, //(valore restituito) As Integer class Namespace1.Module1/MyCl V_3, //O As MyCl valuetype Namespace1.Module1/MyStruct V_4) //S As MyStruct IL_0000: newobj instance void Namespace1.Module1/MyCl::.ctor() //crea una nuova istanza della classe e mette un puntatore ad essa sullo stack IL_0005: stloc.3 //pesca dallo stack il puntatore e lo memorizza in MyCl IL_0006: ldloca.s V_4 //mette sullo stack un puntatore a MyStruct IL_0008: initobj Namespace1.Module1/MyStruct //inizializza i membri della struttura puntata dal puntatore che si trova sullo stack a 0/Nothing => è l'esatto equivalente di MyStruct = Nothing IL_000e: ldc.i4.0 //mette 4 byte di 0 sullo stack IL_000f: stloc.1 //mette nella variabile locale 1 (I) il valore appena messo sullo stack IL_0010: ldc.i4.0 //idem IL_0011: stloc.0 //idem (nella variabile locale 0, ossia B) IL_0012: ldnull //mette un null sullo stack IL_0013: stloc.3 //mette in O il valore appena messo sullo stack IL_0014: ldc.i4.0 //vedi sopra IL_0015: stloc.2 //vedi sopra (imposta il valore restituito a 0) IL_0016: br.s IL_0018 //salta a IL_0018 IL_0018: ldloc.2 //mette sullo stack il valore restituito IL_0019: ret //ritorna } // end of method Module1::Main
Questo ci dimostra che la mia supposizione è errata, visto che anche a livello di MSIL si distinguono tutti i vari casi.
In sostanza con tutto questo sappiamo che impostare una variabile a Nothing equivale a:
- azzerarla (ldc.{i|r}{4|8}.0 - stloc.<var>) se si tratta di un value type "primitivo";
- azzerarne i membri (ldloca.s <var> - initobj) se si tratta di un value type "composto";
- impostarla a puntatore non valido (ldnull - stloc.<var>) se si tratta di un reference type;
ossia non ne sappiamo nulla più di prima.
L'unica altra possibilità che mi viene in mente è che a livello concettuale, magari prima ancora della definizione di MSIL, Nothing sia stato pensato come ho detto sopra, ma che a livello pratico, dopo la definizione completa di MSIL, è stato implementato in questa maniera, visto che MSIL distingue i vari casi.
Amaro C++, il gusto pieno dell'undefined behavior.
Più che a livello di MSIL, cioè relativo alla dinamica con cui il valore Nothing viene trattato, ero curioso di sapere le motivazioni per cui in VB.NET è stato scelto di seguire questa convenzione diversa rispetto a quella adottata in C#.![]()
MARCO BREVEGLIERI
Software and Web Developer, Teacher and Consultant
Home | Blog | Delphi Podcast | Twitch | Altro...