Press "Enter" to skip to content

3 Absolute Beginners – Keywords Identificatori e variabili

Livello: principianti

Prerequisiti: aver completato le lezioni precedenti

Il Vocabolario

La prima cosa che uno deve iniziare ad imparare quando studia una nuova lingua è il suo vocabolario. Anche i linguaggi di programmazione non differiscono da questo.  Se non per una cosa fondamentale, il loro vocabolario è sempre molto compatto. Ma come per tutti i linguaggi, in realtà non ne userete quasi mai tutte le parole ma ne userete alcune più di altre. Per un linguaggio di programmazione, il vocabolario è formato da quelle che si chiamano Keywords, ovvero parole chiave. Se ne volete una definizione completa, la trovate qui: C#Keywords Definition on MSDN ma ne vediamo alcune per gruppi fra quelle che utilizzeremo più spesso.

Modificatori di scopo e comportamento

abstract, private, public, internal, protected, override, new, static

Queste parole, saranno solitamente poste come “prefisso” alle dichiarazioni di oggetti ed elementi che compongono gli oggetti, i modificatori di scopo identificano quali sono i limiti entro cui un elemento o un oggetto è visibile all’interno di un programma,  i modificatori di comportamento permettono di dare una serie di direttive al compilatore e a chi utilizzerà poi gli oggetti in cui sono definiti riguardo il modo in cui tali oggetti saranno utilizzati. Vedremo più in avanti l’uso di tutti questi, i principali con cui lavoreremo per sviluppare applicazioni sono comunque 3 solitamente e sono:

public, private, static.

Dichiarazioni di oggetti

class, interface, struct, enum

Questi sono i quattro  tipi di oggetti che andremo ad utilizzare per fare qualsiasi cosa in C#, in realtà potremmo anche utilizzare il solo class, ma gli altri tre possono tornare utili in molti ambiti. Ricordate la parola interface, che è collegata al Polimorfismo che se pure ha un nome che sembra quello di una malattia contagiosa, o di un animale dotato di molte teste e molte zampe, in realtà e uno degli strumenti più potenti a disposizione dei programmatori.

Istanziare un oggetto

new

Probabilmente la keyword più importante di C#, perché permette di istanziare una classe, ovvero, dal progetto, costruire la casa. La parola new ed il suo uso sono indispensabili per fare qualsiasi cosa, salvo Hello World, e anche in Hello World, c’è qualcuno che lo fa per noi dietro le quinte.

Tipi di dati fondamentali

bool, char,byte, short, int, long, float, double, decimal, string, void

Ciascuna di queste keyword è l’ alias di una classe del .Net Framework che mappa questo tipo di dati anzi, salvo string, che è un oggetto un po’ speciale, in realtà sono tutti degli struct, e quindi dei Value Types (ne parleremo più avanti in questo articolo). Vediamo la lista di quello che mappano a nostro uso e consumo:

  • bool=booleano, può assumere solo 2 valori, true o false (che sono anche essi keyword) la classe del framework mappata su di esso è System.Boolean.
  • char=carattere, contiene un carattere in formato Unicode (Tutte le stringhe usate in memoria da .Net sono in Unicode, anche se possono essere salvate e recuperate in ogni tipo di codifica grazie all’ Encoding, è mappato dalla classe System.Char. E contiene un numero a 2 byte rappresentante detto carattere. Questo può farci capire come una stringa .net, occupa 2 byte per ogni carattere che la forma (e anche se non ho mai guardato da vicino, scommetto che ha un byte = 0 come terminatore).
  • byte=intero a 8 bit, contiene un numero intero senza segno che va da 0 a 255. E’ l’unità logica standard di memorizzazione sui computer attuali e qualsiasi file su disco è riconducibile ad un array di byte, la classe del framework mappata su di esso è System.Byte.
  • short=intero a 16 bit, contiene un numero intero con il segno che va da -32.768 a +32767 ed è mappato da System.Int16 se volete la versione senza segno, è ushort che va da 0 a 65535 ed è mappata da System.Int16
  • int=intero a 32 bit, contiene un numero intero che va da  -2147483648 fino a 2147483647 (2 elevato alla -31 fino a 2 elevato alla 31) mappato dalla classe System.Int32, la versione senza segno è uint ed è mappata da System.UInt32.
  • long = intero a 64 bit, contiene un numero che va da -2E+63 a +2E+63  (ovvero due alla 63esima…) è mappato dalla classe System.Int64. la versione senza segno è ulong ed è mappata da System.Int64.
  • float= rappresenta un numero a virgola mobile a 32 bit, ed è mappato da System.Single, ha una precisione massima di 7 cifre
  • double=rappresenta un numero a virgola mobile a 64 bit ed è mappato da  System.Double ha una precisione fino a 15 o 16 cifre.
  • decimal=rappresenta un numero a virgola mobile a 128 bit ed è mappato da System.Decimal ha una precisione fino a 29 cifre.
  • string= rappresenta una stringa alfanumerica unicode, è mappato da System.String ed ha la peculiarità di essere Immutabile ed essere gestito dal framework .Net in modo tale che se la stessa stringa è ripetuta più volte nel codice, viene comunque creata una sola volta e tutti i punti ove viene usata puntano allo stesso oggetto. Quando parleremo di Stringhe ne tratteremo estesamente, sappiate che la string è uno dei tipi più usati in ogni programma ed è una di quelle più importanti da capire e imparare a usare.
  • void= è un tipo di dato particolare perché dichiara semplicemente che non c’è un dato, è un codice convenzionale che serve a dichiarare i metodi che non hanno alcun tipo di dato di ritorno.

Un secondo, Sabrina, perché tutte le classi del framework non seguono la nomenclatura che hai indicato ed hanno un punto nel nome?
Lo spiego più sotto, quando parliamo della nomenclatura delle variabili e dei Namespace.

Costrutti di controllo e ciclo

if, else, else if, switch, default, break, for, foreach, while, do while, continue

Le parole chiave qui sopra sono fra le più usate ed importanti, permettono di implementare le strutture di controllo del codice, che sono quelle che valutano un determinato accadimento (un tasto premuto, un azione dell’utente, un click o un tap, o dei dati ricevuti via internet) e prendono delle decisioni in base al risultato della valutazione. I cicli non hanno tutti lo stesso funzionamento, ma possono ripetere più volte la valutazione di dati ed elaborare quindi delle serie di informazioni invece che informazioni singole. Avremo almeno una lezione specifica per imparare ad usarli.

Costrutti di controllo delle eccezioni

try, catch, finally, throw

Queste keyword permettono di controllare il verificarsi di errori e intercettarli, verificarli e trattarli quando possibile in modo da poter creare interfacce in grado correggere errori noti, oppure di informare gli utenti di eventuali errori e indicare come ovviare o come provare di nuovo dopo aver corretto qualcosa.

Dichiarazione e costruzione degli eventi

event, delegate

Anche se gli eventi non sono parte di questa prima serie di lezioni, è indispensabile sapere che esistono visto che tutti gli attuali sistemi operativi con interfaccia grafica lavorano per eventi, gli eventi possono essere scatenati dall’hardware (il click del mouse, o il tap su un touch screen piuttosto che il cambio di posizione del sensore dell’accelerometro o quello del GPS, ma possono anche essere scatenati dalle classi di una applicazione per informare di qualcosa che si è verificato o deve essere notificato ad altre classi dell’applicazione. Sono il modo che hanno le applicazioni di conversare con il mondo utilizzando l’hardware.

Ci fermiamo qui, ci saranno altre keyword che useremo ma per ora, leggere a cosa servono e sapere che esistono almeno queste è importante.

What’s Your name?

La prima lezione di inglese a scuola iniziava più o meno così, e considerato che C# è una lingua, la prima vera lezione di C# dopo aver imparato qualche nozione sull’ambiente di lavoro nelle prime due lezioni, e aver imparato un po’ di vocabolario nel paragrafo precedente, riguarda il modo in cui diamo i nomi alle cose all’interno di C#.

In un linguaggio di programmazione, soprattutto uno come C# che utilizza gli oggetti, dovremo dare nome a decine, se non centinaia o migliaia di cose mentre scriviamo il codice, inoltre dovremo usare altrettante cose che sono state create a nostro uso e consumo da parte dei programmatori di Microsoft quindi dovremo Imparare decine, o centinaia di Nomi di oggetti che fanno parte delle librerie del .Net Framework ed altri scritti da programmatori che hanno creato componenti e librerie (open source o commerciali) che ci servirà utilizzare per raggiungere i nostri scopi e creare l’Applicazione perfetta per risolvere i nostri problemi o quelli dei nostri Utenti.

Quindi, la prima cosa da imparare è come sono fatti i nomi di oggetti e cose in C# e quali sono le convenzioni standard indicate dalle linee guida chiamate: Buonsenso e soprattutto: cerca di fare le cose come fa tutto il resto del mondo ed evita di inventare l’acqua calda.

Cos’è un identificatore?

Un identificatore è un nome, o per andare proprio a livello basico una parola, che identifica in modo univoco un elemento all’interno del codice C# che compone un applicazione. Ho usato la parola elemento e non oggetto perché l’ oggetto in C# è una cosa precisa, in un programma identificheremo molti tipi di cose. Le principali, per darvi alcune idee sono:

  • Namespaces
  • Classi
  • Oggetti
  • Variabili
  • Property
  • Metodi
  • Strutture
  • Enumerazioni

Qual’è il formato che deve avere un identificatore in C#

Lo abbiamo già detto ma ripetiamo volentieri: un identificatore deve essere composto da 1 o più caratteri, il primo carattere deve essere una lettera oppure un underscore (_), possono contenere lettere, numeri, underscore, non possono contenere spazi o caratteri di spaziatura ne alcun altro tipo di punteggiatura. Non possono essere uguali ad una qualsiasi keyword del linguaggio C#. Gli identificatori ammettono qualsiasi lettera, anche quelle accentate, ma da dinosauro della programmazione vi consiglio vivissimamente di evitare di usare lettere accentate per dare nomi ad oggetti.

x, fileName, _data, Size, MainWindow, hotelRooms, item2

sono tutti leciti

2x, file name, -data, size.x, Main:Window, hotel/rooms, 2_item, do, switch

sono tutti sbagliati e non possono essere usati.

Vi consiglio di provare a creare un progetto e all’interno di una classe, provare a definire delle variabili con i nomi qui sopra per verificare gli errori che riceverete.

Quali sono le regole per la nomenclatura in C#

La sola regola obbligatoria è quella sopra scritta, ma ovviamente vi sono una serie di convenzioni che sono utilizzate a livello globale che ritengo opportuno citare, anche se poi ciascuno è libero di usare la nomenclatura che preferisce.

  • Tutti gli identificatori dovrebbero essere Auto Esplicativi, ovvero, leggendone il nome si dovrebbe avere un idea abbastanza precisa di cosa si tratta, pertanto, è estremamente becero da parte di chi scrive il codice scrivere gli identificatori in modo criptico, o usare una lingua non neutra, anche se ovviamente, nei vostri programmi che non dovrete mai far vedere a un programmatore straniero siete liberi di usare l’italiano. Per quanto mi riguarda ho preso l’abitudine di usare l’inglese, sia per gli identificatori che per i commenti. Per quanto non sia facile. Sono considerati orribili sia gli identificatori con una singola lettera (a meno che non si tratti dei contatori dei cicli for, o di una variabile con uno scopo locale e minuscolo per cui non ha bisogno di spiegazione) che gli identificatori  formati da abbreviazioni eccessive o da parole non collegate al loro uso. Ma ovviamente considerato che, Knowledge is Power come diceva Francesco Bacone, se volete potete usare gli identificatori più incomprensibili che volete. Salvo che poi, quando riprenderete in mano un progetto ad anni di distanza, sarete voi stessi a mandarvi delle maledizioni perché per capire quello che avevate fatto ci metterete una vita. La regola base è quindi, se non c’è un motivo specifico, usiamo nomi a noi chiari.
  • Gli identificatori pubblici sono sempre espressi in PascalCase. Cosa intendiamo con identificatori pubblici, ad esempio i nomi delle classi dei nostri programmi, i nomi dei metodi pubblici o internal che sono utilizzati dall’esterno delle classi, i nomi dei namespace, i nomi delle property pubbliche e degli eventi. Cosa intendiamo con PascalCase? come la parola PascalCase mostra, ogni identificatore pubblico inizia con una lettera maiuscola, e se formato da più parole, ciascuna parola inizia con una maiuscola. Questo permette di dare all’identificatore una maggiore leggibilità. Vedrete come le classi del .Net Framework obbediscano tutte alla regola. Perché PascalCase e non GalileoCase o NewtonCase? il termine deriva dal linguaggio Pascal, uno dei primi linguaggi strutturati progettato per  insegnare a programmare correttamente agli studenti universitari. Per saperne di più Pascal programming language.
    • Console, System, FileName, DirectoryName, GetFileName, ReadAllBytes sono esempi di variabili PascalCase.
  • Gli identificatori locali, le variabili di classe, i parametri dei metodi sono sempre espressi in camelCase. Cosa vuol dire camelCase, da come ho scritto la parola si dovrebbe intuire, così come dal modo in cui è fatto un Cammello -^^ che inizia piatto e poi ha le gobbe. Quindi camelCase significa che l’identificatore inizia con una lettera minuscola e se composto da più parole, le parole successive alla prima iniziano con una lettera maiuscola.
    • addendo, fileName, initialLoan, animalSpecie sono esempi di variabili camelCase.
  • Gli identificatori pubblici non iniziano mai con  underscore (_) mentre se vi piace, potete usarlo per le variabili private delle classi o per i metodi privati delle classi, io sinceramente non amo molto il carattere se non per le costanti e per i nomi di file. non lo uso praticamente mai nelle mie classi, dove come prefisso per riconoscere le variabili private  uso la lettera m (emme minuscolo perché sono delle variabili member). In passato usavo la p (pi minuscolo) come prefisso per i parametri, ma dopo discussione estesa sui pro ed i contro con i colleghi, ho deciso di soprassedere e quindi da un anno a questa parte non la uso più. Il motivo per usarla era uno solo, sapere all’interno del codice di un metodo quali variabili fossero parametri rispetto alle variabili locali. L’intellisense e soprattutto la buona pratica di creare metodi brevi, rendono questa convenzione non necessaria.
  • Le costanti, dovrebbero essere scritte con lettere maiuscole e underscore o per lo meno iniziare con un prefisso maiuscolo in modo da essere identificabili subito come tali.
    Ad esempio SQL_SelectContacts o SQL_SELECT_CONTACTS sono un buon modo per capire che stiamo guardando delle costanti.

Direi che le cose principali sono queste, seguire o meno le regole è vostra libera scelta quindi potete fare quello che preferite.

Un momento, ma nella lezione di Hello World abbiamo scritto dei nomi con i punti!!!

System.Console.WriteLine("hello, world!");
System.Console.ReadLine();

Corretto abbiamo scritto dei nomi con i punti, ma in realtà, System, Console e WriteLine sono 3 diversi identificatori, ed abbiamo utilizzato l’ operatore punto (.) o dot in inglese che è uno dei fondamenti della sintassi di C#  (e di tutti i linguaggi ad oggetti C like) l’operatore punto è definito come Member Access Operator, ovvero operatore di accesso ai membri, membri di cosa chiederete voi: membri dei Namespace, membri delle classi e così via.

System.Console.WriteLine

Vuol dire al compilatore: Esegui il metodo WriteLine, della classe Console, contenuta nel namespace System.

System.IO.File.ReadAllText

Vuol dire al compilatore: Esegui il metodo ReadAllText della classe File, contenuta nel namespace IO, contenuto nel namespace System.

Il namespace è un eccezione?

Si e No, infatti quando creiamo una classe con un namespace “indentato” se così vogliamo dire, la sua dichiarazione sarà:

namespace Dnw.HelloWorld.Entity

Quindi sembra che abbiamo dichiarato un identificatore con il nome separato da punti, in realtà non è così, perché il compilatore costruisce una classe che si trova dentro al namespace Entity, però è informato del fatto che il namespace Entity è contenuto nel Namespace HelloWorld, che è contenuto nel namespace Dnw. Considerate i namespaces come le scatole cinesi, oppure le matrioske. o semplicemente immaginate che Dnw sia una stanza, HelloWorld sia un Armadio nella stanza e Entity sia un cassetto nell’armadio in cui ad esempio ho inserito una classe che si chiama Fazzoletto.

Vi ho confuso a sufficienza? Ottimo, allora proseguiamo e parliamo di Variabili.

Cos’è una variabile?

Per iniziare a parlare di variabili e provare a creare degli identificatori e verificare quello che vi ho spiegato in merito, creiamo un progetto WPF praticamente identico all’ HelloWorld della precedente lezione:

In Visual Studio, selezioniamo New Project (Nuovo Progetto) ed apparirà la finestra qui sotto.

identifiersvariables_project_01[4]

Selezioniamo C# e Applicazione WPF, poi cambiamo il nome del progetto (la soluzione cambierà da sola) in IdentifiersVariables.

Andiamo per prima cosa a modificare MainWindow.xaml

        Title="Identifiers and Variables" Height="350" Width="525" Loaded="Window_Loaded">     <Grid>         <TextBox Name="TxtContent"/>     </Grid>
  • Modifichiamo Title in “Identifiers and Variables” al posto di MainWindow
  • Aggiungiamo l’attributo Loaded=”Windows_Loaded” per poter scrivere del codice eseguito quando la finestra viene caricata.
  • Nel tag Grid aggiungiamo il tag TextBox con l’ attributo Name = “TxtContent”

A questo punto, per andare a scrivere del codice e testare come si scrivono gli identificatori, per poi definire cosa sono le variabili, posizioniamoci su Window_Loaded e facciamo tasto destro Go To Definition.

private void Window_Loaded(object sender, RoutedEventArgs e)
{
	int x = 10;
	int y = 4;
	int z = x * y;
	int sumTotal = x + y + z;
	TxtContent.Text = "x+y+z=sumTotal " + x.ToString() + "+" + y.ToString() + "+" + z.ToString() + " = " + sumTotal.ToString();
	TxtContent.HorizontalAlignment = HorizontalAlignment.Center;
	TxtContent.VerticalAlignment = VerticalAlignment.Center;
	TxtContent.FontSize = 16;
	TxtContent.Foreground = Brushes.Red;
}

Nel Metodo Window_Loaded che ci viene creato inseriamo il codice qui sopra.  Tanto per vedere come scrivere degli identificatori incomprensibili. In questo caso x, y, z sono comprensibili perché il metodo fa solo delle operazioni di assegnazione, moltiplicazione e somma, ma se invece i valori ci arrivassero da qualche altro oggetto rientrando nel programma fra qualche anno, come faremmo a ricordarci cosa sono i valori di x, y, z? Ecco perché variabili come sumTotal sono un po’ più utili per il vostro lavoro.

identifiersvariables_output[4]

Se notate le assegnazioni che ho fatto alla TextBox che ho chiamato TxtContent, per formattare il suo aspetto e visualizzare il risultato della mia operazione, vi rendete conto che anche senza commentare il codice, i nomi significativi che sono stati dati alle Property della classe TextBox di cui TxtContent è un istanza, mi permettono di capire che in questo metodo sto assegnando all’oggetto un testo da visualizzare, e sto allineando il testo contenuto al centro in orizzontale e verticale, inoltre sto assegnando la dimensione alla font e sto decidendo che il suo colore sarà Rosso.

Tc.Tx = "x+y+z=sumTotal" + x.ToString() + "+" + y.ToString() + "+" + z.ToString() + " = " + sumTotal.ToString();
Tc.HA = HA.Center;
Tc.VA = VA.Center;
Tc.Fs = 16;
Tc.FC = Br.Red;

Se chi ha scritto le librerie WPF fosse stato criptico chiamando le property della TextBox le enumerazioni e la collezione dei Brushes (pennelli con i colori base web) con nomi altrettanto criptici, certamente capire che cosa succede in queste istruzioni non sarebbe così semplice, pertanto ricordatevi che se ci sono delle regole di nomenclatura seguite in tutto il mondo, un motivo valido c’è.

Cos’è una Variabile?

int x = 10;

Una variabile, in C# è la dichiarazione dell’istanza di un oggetto o di un riferimento ad una istanza di un oggetto. In parole semplici, una variabile è un nome che permette ad un programma di accedere ad un area della memoria della device su cui il programma sta funzionando per leggere o scrivere dei dati.

Nella riga di esempio qui sopra, abbiamo dichiarato una variabile di tipo int (intero a 32 bit) che farà si che il sistema riservi 4 byte di memoria con questo nome. Fatto questo, abbiamo assegnato a quest’area di memoria il numero 10, (in memoria sarà rappresentato con 00 00 00 0A in 4 byte in esadecimale). (se vi chiedete che cosa vuol dire: Esadecimale su Wikipedia.

In un programma C# dichiareremo moltissime variabili che potranno essere locali (definite in una porzione di codice come nell’esempio relativo agli identificatori), variabili di classe, definite all’interno di una classe e quindi accessibili a tutto quello che si trova nella classe, variabili pubbliche (altamente sconsigliato usarle ma ci sono) definite all’interno di una classe ma modificabili all’esterno.

Variabili di tipo Value e variabili di tipo Reference

Ci sono 2 tipi di variabili che possono essere usate in C#, le variabili di tipo Value che sono tutte “struct” – strutture – o tipi dati di base, quali int, short, double, byte, char eccetera. oppure Variabili di tipo Reference, che sono tutte variabili di tipo “class” – classi – e sono la maggior parte di tutti gli oggetti del framework e buona parte di quelli che definiremo noi stessi.

Qual’è la differenza?

Una variabile di tipo Value, accede direttamente all’oggetto che rappresenta (nel caso dell’ int, x rappresenta il valore dei 4 byte che rappresentano l’intero) pertanto, quando viene modificata, il suo valore viene modificato in modo diretto, quando viene copiata, il suo valore viene duplicato in modo diretto.

Una variabile di tipo Reference, semplicemente è un puntatore ad un oggetto, ovvero contiene al suo interno un indirizzo di memoria che è il punto in cui la struttura dati dell’oggetto che rappresenta è memorizzato. Pertanto se viene modificata, l’oggetto a cui puntava cambia, rimane “appeso” in memoria fino a che il sistema di Garbage Collector non lo butta via riciclando la memoria. Quando viene copiata, questo tipo di variabile non crea una copia dell’oggetto ma semplicemente un altro puntatore all’indirizzo dello stesso oggetto. Infatti, se un valore viene modificato nella prima variabile, la modifica si riflette anche nella seconda (al contrario di quanto accade per le variabili di tipo Value dove invece la copia non cambia).

Si tratta di concetti fondamentali, che devono essere compresi altrimenti potremmo trovarci dei comportamenti anomali nel nostro software e non sapere il motivo.

Per fare un esempio, creiamo una classe, veramente semplice che contiene al suo interno solo una variabile intera:

namespace IdentifiersVariables
{
 
	public class Totalizer                <<<<<<----- la nostra minuscola classe con 1 totalizzatore di tipo int
	{
		public int TotalValue;
 
		public override string ToString()
		{
			return TotalValue.ToString();
		}
	}
	
	/// <summary>
	/// Interaction logic for MainWindow.xaml
	/// </summary>
	public partial class MainWindow : Window
	{

Definiamo la nostra classe all’interno di MainWindow.xaml.cs all’esterno della definizione della classe MainWindow stessa.

Prima dimostrazione, variabili di tipo Value, tutti i tipi di dati numerici di base, assieme a DateTime sono dei dati di tipo Value.

TxtContent.Text = string.Empty;
 
//Monday
int subTotalCash = 5000;
int progressive = subTotalCash;
TxtContent.Text = "Monday: " + subTotalCash.ToString();
TxtContent.Text = TxtContent.Text + "\r\nProgressive: " + progressive.ToString();

Creiamo una variabile intera (subTotalCash) gli assegnamo un valore, poi creiamo una seconda variabile (progressive) e gli assegnamo il valore di subTotalCash visualizzandole otterremo che i due valori sono identici.

Monday: 5000 
Progressive: 5000
//Tuesday
subTotalCash = subTotalCash + 3000;
progressive = subTotalCash;
TxtContent.Text = TxtContent.Text +"\r\nTuesday: " + subTotalCash.ToString() + "Sub total";
TxtContent.Text = TxtContent.Text + "\r\nProgressive: " + progressive.ToString();

Se modifichiamo il valore di subTotalCash sommandogli un nuovo valore e  torniamo ad assegnarlo a progressive, vedremo che ancora una volta il valori sono uguali.

Tuesday: 8000Sub total
Progressive: 8000
//Wednesday
subTotalCash = subTotalCash + 4000;
TxtContent.Text = TxtContent.Text + "\r\nWednesday: " + subTotalCash.ToString() + "Sub Total";
TxtContent.Text = TxtContent.Text + "\r\nProgressive before sum: ";
TxtContent.Text = TxtContent.Text + "\r\nProgressive: " + progressive.ToString();
progressive = subTotalCash;
TxtContent.Text = TxtContent.Text + "\r\nProgressive after sum: ";
TxtContent.Text = TxtContent.Text + "\r\nProgressive: " + progressive.ToString();

Se ora modifichiamo il valore di subTotalCash di nuovo e poi stampiamo di nuovo le 2 variabili, possiamo notare che progressive ha il valore vecchio, e viene modificata solo dopo che gli abbiamo nuovamente assegnato il valore di subTotalCash.

Wednesday: 12000Sub Total
Progressive before sum: 
Progressive: 8000
Progressive after sum: 
Progressive: 12000

Possiamo affermare che subTotalCash e progressive sono 2 oggetti indipendenti, progressive  assume un valore che è una copia di quello che gli è stato assegnato.

TxtContent.Text = TxtContent.Text + "\r\n--------------: " ;
progressive = progressive + 123;
TxtContent.Text = TxtContent.Text + "\r\nReverse Proof we modified progressive: ";
TxtContent.Text = TxtContent.Text + "\r\nProgressive: " + progressive.ToString();
TxtContent.Text = TxtContent.Text + "\r\nAfter Progressive change: " + subTotalCash.ToString() + "unmodified";

Come prova al contrario, modifichiamo progressive e lasciamo subTotalCash invariato, vediamo che progressive cambia e subTotalCash non viene modificato.

--------------: 
Reverse Proof we modified progressive: 
Progressive: 12123
After Progressive change: 12000 Sub total unmodified

Adesso facciamo la prova con la Reference Value, quindi invece che due numeri interi, utilizziamo 2 classi di tipo Totalizer:

TxtContent.Text = TxtContent.Text + "\r\n---------------: ";
TxtContent.Text = TxtContent.Text + "\r\nReference test: ";
//Monday reference
Totalizer subTotal = new Totalizer();
subTotal.TotalValue = 5000;
TxtContent.Text = TxtContent.Text + "\r\nMonday: " + subTotal.ToString() + "Sub total";
Totalizer progressTotal = subTotal;
 
TxtContent.Text = TxtContent.Text + "\r\nProgressive: " + progressTotal.ToString();

Creiamo un Totalizer che chiamiamo subTotal  in cui creiamo un istanza della classe vuota. Gli assegnamo un valore, poi assegnamo subTotal ad una nuova variabile progressTotal sempre di tipo Totalizer:

---------------: 
Reference test: 
Monday: 5000 Sub total
Progressive: 5000
//Tuesday reference
subTotal.TotalValue = subTotal.TotalValue + 3000;
TxtContent.Text = TxtContent.Text + "\r\nTuesday: " + subTotal.ToString() + "Sub total";
TxtContent.Text = TxtContent.Text + "\r\nProgressive: " + progressTotal.ToString() ;

Stavolta modifichiamo solo il contenuto di subTotal ma stampiamo entrambi e vediamo cosa accade

Tuesday: 8000 Sub total
Progressive: 8000

Possiamo notare che sia SubTotal che ProgressiveTotal sono stati cambiati.

//Wednesday reference
subTotal.TotalValue = subTotal.TotalValue + 4000;
TxtContent.Text = TxtContent.Text + "\r\nWednesday: " + subTotal.ToString() + "Sub total";
TxtContent.Text = TxtContent.Text + "\r\nProgressive: " + progressTotal.ToString();
 
TxtContent.Text = TxtContent.Text + "\r\nReverse Proof we modify progressive: ";
progressTotal.TotalValue = progressTotal.TotalValue + 123;
TxtContent.Text = TxtContent.Text + "\r\nProgressive: " + progressTotal.ToString();
TxtContent.Text = TxtContent.Text + "\r\nThe subtotal: " + subTotal.ToString() + "Changed";

Ora facciamo la riprova, modifichiamo di nuovo subTotal e vediamo cosa accade e per fare la prova inversa, modifichiamo progressTotal e vediamo cosa accade.

Wednesday: 12000 Sub total
Progressive: 12000
Reverse Proof we modify progressive: 
Progressive: 12123
The subtotal: 12123 Changed

Anche in questo caso, se modifichiamo SubTotal cambia anche progressTotal e viceversa, pertanto in questo caso, le 2 variabili sono un riferimento (reference) allo stesso oggetto, per questo motivo, modificando una modifichiamo anche la seconda.

Essendo una lezione Informale, ci fermiamo qui, ma torneremo a parlare della definizione e all’uso di variabili, considerato che è molto importante in qualsiasi applicazione, rivedete e cercate di comprendere bene la differenza fra variabili Value e Reference, vi apre un mondo intero all’interno della programmazione.

 

Il codice esempio collegato a questa lezione può essere scaricato al link seguente:

Domande, approfondimenti, correzioni e qualsiasi altro contatto potete effettuarli con il link in cima alla pagina.