223 messaggi dal 08 gennaio 2011
Ciao, mi sembra un pò una contraddizione che si possa assegnare (in vb) il "valore" Nothing per esempio ad una variabile di tipo Integer ma che poi dopo questa assegnazione la lettura della variabile dia come risultato il valore 0.

Mi piacerebbe capire come mai non si è pensato di prevedere questa possibilità, cioè di consentire l'assegnazione di nessun valore ai tipi primitivi. Integer, Decimal, Single, Date, Boolean, ecc. ecc.

Capisco che per questi tipi è prevista una dichiarazione come Nullable, ma perchè questa separazione ? Cosa comporta dichiarare Nullable ad esempio un tipo Integer ?
11.862 messaggi dal 09 febbraio 2002
Contributi
Ciao Mario,


Ciao, mi sembra un pò una contraddizione che si possa assegnare (in vb) il "valore" Nothing per esempio ad una variabile di tipo Integer ma che poi dopo questa assegnazione la lettura della variabile dia come risultato il valore 0.


Forse il nome "Nothing" non è molto felice e lascia spazio a confusione. In realtà "Nothing" vuol dire "Il valore di default del tipo in questione", come chiarito dalla documentazione.
https://docs.microsoft.com/en-us/dotnet/visual-basic/reference/language-specification/lexical-grammar#nothing

Di conseguenza, quando assegni Nothing a una variabile Integer, gli stai di fatto assegnando il valore di default di Integer, che è 0.
Quando invece lo assegni a un reference type, come List(Of String), allora assumerà il suo valore di default che è "assenza di valore" o, per dirla in altri termini, "puntatore a null".


Mi piacerebbe capire come mai non si è pensato di prevedere questa possibilità, cioè di consentire l'assegnazione di nessun valore ai tipi primitivi. Integer, Decimal, Single, Date, Boolean, ecc. ecc.

Questo dipende da come fisicamente sono memorizzati quei valori in celle di memoria.
Un Integer è un tipo di valore memorizzato su 4 byte di memoria (cioè 32 bit). Tutte le possibili permutazioni di quei bit servono a rappresentare un numero Integer valido. Non c'è spazio per indicare l'"assenza di valore".
Microsoft avrebbe potuto predisporre un 33esimo bit allo scopo di indicare l'assenza di valore? Presumo che tecnicamente fosse fattibile ma credo che gli ingegneri che hanno progettato .NET siano stati contrari perché, improvvisamente, memorizzare un Integer ti costa almeno un byte in più (non puoi allocare singoli bit in memoria: devi "sprecare" almeno un intero byte, forse di più per questioni di performance di accesso al dato).
Quindi meglio lasciare che sia lo sviluppatore a decidere se vuole un Integer "normale" o un Integer che gli costa di più perché ammette anche l'assenza di valore.


Cosa comporta dichiarare Nullable ad esempio un tipo Integer ?

Che costa almeno un byte in più, come leggi qui.
https://stackoverflow.com/questions/294905/why-is-a-boolean-4-bytes-in-net

ciao,
Moreno
Modificato da BrightSoul il 29 settembre 2019 17:49 -

Enjoy learning and just keep making
223 messaggi dal 08 gennaio 2011
Grazie Moreno, della risposta.
Però, prendendo sempre come esempio l'intero, come si è fatto per la rappresentazione dei valori negativi che usano un bit dei 32 per indicare il segno, si sarebbe potuto ad esempio riservare il valore 11111....(32 bit settati ad 1) per rappresentare l'assenza di valore (Nullo) ; si sarebbe sacrificato un valore dell'intero range (2^32) ma si sarebbe ottenuta la rappresentazione del nullo senza aumentare la memoria occorrente.

Ho letto sulla documentazione ufficiale e mi è sembrato di capire che i tipi Nullable sono tipi riferimento, vengono allocati nell'heap, comportano conversioni Boxing quindi meno performanti.

Ma se devo in una classe prevedere l'uso di campi/proprietà di tipo valore che possono essere anche nulli, devo per forza ricorrere ai Nullable o c'è qualche via migliore ?

Ciao, grazie.
11.862 messaggi dal 09 febbraio 2002
Contributi

si sarebbe sacrificato un valore dell'intero range (2^32)

Questo è un problemone perché .NET non sarebbe stato interoperabile con altri sistemi.
Supponi che in Sql Server, in una colonna INT, tu abbia memorizzato il valore 2147483647 (valore massimo di un intero). Lo vai a leggere con ADO.NET e hai un'eccezione perché quel valore non è rappresentabile.

Idem quando realizzi videogiochi e hai bisogno di scambiare valori interi con la GPU.

Ma se devo in una classe prevedere l'uso di campi/proprietà di tipo valore che possono essere anche nulli, devo per forza ricorrere ai Nullable o c'è qualche via migliore ?

Sì, usa i Nullable.
Se gli interi si trovano in un oggetto complesso, allora vanno anche loro nell'heap.

https://dev.to/tyrrrz/interview-question-heap-vs-stack-c-5aae

If the value type was declared as a member of a class then it's stored on the heap, along with its parent.


ciao,
Moreno
Modificato da BrightSoul il 30 settembre 2019 23:35 -

Enjoy learning and just keep making
223 messaggi dal 08 gennaio 2011
Ciao Moreno, grazie ai tuoi consigli adesso ho le idee un pò più chiare e soprattutto sono tranquillizzato sull'uso dei Nullable che sono veramente comodi.

Tuttavia mi piacerebbe capire come mai storicamente, non solo in ambito .Net, per i tipi primitivi, non si è previsto di rappresentare il 'nessun valore'

Ciao, grazie.
Modificato da Mario Formosa il 01 ottobre 2019 08:19 -
11.862 messaggi dal 09 febbraio 2002
Contributi

Tuttavia mi piacerebbe capire come mai storicamente, non solo in ambito .Net, per i tipi primitivi, non si è previsto di rappresentare il 'nessun valore'

L'origine storica non la conosco. Presumo che sia così perché nessuno l'ha inventato. Probabilmente non si è sentita l'esigenza perché comunque puoi eleggere tu stesso dei valori "magici", per fare in modo che nella tua applicazione significhino "assenza di valore". Banalmente, anziché così:
int value = 5;
if (value == null)
{
   //Fai qualcosa
}
else
{
   //Fai qualcos'altro
}

Basterebbe fare così:
int value = 5;
if (value == NULL) //Qui NULL è il nome di una costante assegnata a int.MinValue
{
   //Fai qualcosa
}
else
{
   //Fai qualcos'altro
}


E chi ha inventato il null per i reference type (Tony Hoare) se ne è pentito perché un programma va in errore se provi a usare i membri di un oggetto se prima non hai controllato che non fosse null. E quello è un controllo che facilmente si dimentica di fare.
https://www.infoq.com/presentations/Null-References-The-Billion-Dollar-Mistake-Tony-Hoare/

In C# 8.0 sono stati introdotti i Nullable anche per i reference type: se lo desideri, tutti i tipi sono non-nullable per default e devi aggiungere tu il ? di fianco al tipo (es. string?) per indicare che possono anche ammettere valori null. In questo modo il programmatore può esprimere il suo intento in maniera più coerente, anziché subire le incosistenze del linguaggio che vuole che alcuni tipi siano nullable e altri no.
https://devblogs.microsoft.com/dotnet/nullable-reference-types-in-csharp/

In F# il valore null non viene in genere utilizzato.
https://docs.microsoft.com/it-it/dotnet/fsharp/language-reference/values/null-values

Martin Fowler, nel suo libro "Patterns of Enterprise Application Architecture" fornisce un'idea alternativa all'uso del null.
https://martinfowler.com/eaaCatalog/specialCase.html

ciao,
Moreno
Modificato da BrightSoul il 01 ottobre 2019 13:46 -

Enjoy learning and just keep making
223 messaggi dal 08 gennaio 2011
Grazie Moreno,
Molto interessante il tuo ultimo post.

Ciao.

Torna al forum | Feed RSS

ASPItalia.com non è responsabile per il contenuto dei messaggi presenti su questo servizio, non avendo nessun controllo sui messaggi postati nei propri forum, che rappresentano l'espressione del pensiero degli autori.