PARAMETRI DI METODO IN C SHARP, IL PASSAGGIO DEI PARAMETRI NEI VALUE TYPES
using System; namespace Modificatori_Ref_Out_In { class Program { static void Main(string[] args) { int x = 10; Console.WriteLine(x);//x=10 MyMethod(x); Console.WriteLine(x);//x=10 } static void MyMethod(int y) { y=20; } } }
Prima di affrontare l’argomento i “Parametri di metodo in c sharp” analizziamo il comportamento di default dei value type e dei reference type quando vengono passati come parametri ad un metodo. Come vedi quando si passa un value type, come lo è un int, ad un metodo sai già che il passaggio avviene per valore, cioè una copia del valore di x viene passato ad y. Modificando y all’interno del metodo statico di fatto stiamo modificando la copia di x che al ritorno dal metodo ritrova il suo valore inalterato. Questo è il comportamento standard dei value type. Vediamo come si comporta un reference type quando lo passiamo il suo reference ad un metodo.
PARAMETRI DI METODO IN C SHARP IL PASSAGGIO DEI PARAMETRI NEI REFERENCE TYPES
using System; namespace Modificatori_Ref_Out_In { public class MyClass { public int x = 10; } class Program { static void Main(string[] args) { MyClass mc = new MyClass(); Console.WriteLine(mc.x);//x=10 MyMethod(mc); Console.WriteLine(mc.x);//x=20 } static void MyMethod(MyClass y) { y.x=20; } } }
Nel passaggio dei tipi reference anche qui avviene una copia per valore, ma avviene una copia dei reference, il reference di mc viene passatao ad y. Entrambi i reference puntano lo stesso oggetto quindi se modifichiamo la variabile x dentro MyMethod di fatto andiamo a modificare lo stato dell’oggetto puntato dai due reference mc e y. Se facciamo puntare y ad una nuova istanza di MyClass allora il reference mc non verrebbe intaccato e il valore della variabile x rimane inalterato.
using System; namespace Modificatori_Ref_Out_In { public class MyClass { public int x = 10; } class Program { static void Main(string[] args) { MyClass mc = new MyClass(); Console.WriteLine(mc.x);//x=10 MyMethod(mc); Console.WriteLine(mc.x);//x=10 } static void MyMethod(MyClass y) { y= new MyClass(); y.x=20; } } }
y ora punta ad un nuovo reference indipendente da mc, per questo motivo il valore di x rimane invariato.
MODIFICATORE REF
using System; namespace Modificatori_Ref_Out_In { public class MyClass { public int x = 10; } class Program { static void Main(string[] args) { int z = 10; MyClass mc = new MyClass(); Console.WriteLine($"{"x= "+mc.x + " " +" z= "+z}");//z=10,x=10 MyMethod(ref mc, ref z); Console.WriteLine($"{"x= "+mc.x + " " +" z= "+z}");//z=20,x=20 } static void MyMethod(ref MyClass y, ref int k) { y.x=20; k=20; } } }
Per passare un reference parameter ad un metodo occorre specificare la keyword ref sia all’interno del metodo che all’atto dell’invocazione. Come vedi dal codice per quanto riguarda i reference type il comportamento non cambia, passando invece un value type questa volta il valore di z è cambiato. La variabile z e questo è molto importante deve avere un valore già assegnato, mentre per le variabili reference si può passare anche null. Per capire meglio quello che è successo dobbiamo considerare che:
- Quando passiamo i parametri by value viene, allocata memoria nello stack per i parametri di un metodo e questa memoria è separata rispetto al valore iniziale degli argomenti passati.
- Quando facciamo il passaggio by ref ulteriore memoria non viene allocata nello stack i parametri diventano loro stessi degli alias per i valori originari degli argomenti, cioè condividono la stessa memoria degli argomenti ed è per questo motivo che una modifica dei parametri all’interno del metodo provoca una modifica degli argomenti originari.
using System; namespace Modificatori_Ref_Out_In { public class MyClass { public int x = 10; } class Program { static void Main(string[] args) { MyClass mc = new MyClass(); Console.WriteLine($"{mc.x}");//x=10 MyMethod(ref mc); Console.WriteLine($"{mc.x}");//x=20 } static void MyMethod(ref MyClass y) { y= new MyClass(); y.x=20; } } }
Questa volta il comportamento è diverso da quanto visto prima, il nuovo oggetto viene creato all’interno di MyMethod, la variabile di istanza originaria mc viene sovrascritta con il nuovo valore puntato da y, entrambe mc e y puntano al nuovo oggetto creato nel metodo.
IL MODIFICATORE OUT
Questo tipo di modificatore fornisce in output da un metodo dei valori, in aggiunta all’istruzione return che può tornare solo un valore. Vediamo un esempio:
using System; namespace Modificatori_Ref_Out_In { public class MyClass { public int x = 10; } class Program { static void Main(string[] args) { MyClass mc; int k; MyMethod(out mc,out k); Console.WriteLine($"{mc.x} {k}");//x=20, k=20 } static void MyMethod(out MyClass y, out int k) { y= new MyClass(); y.x=20; k=20; } } }
Molto spesso gli argomenti dei metodi che restituiscono valori in output non sono assegnati, è obbligatorio inizializzarli nel metodo se non si vuol ricevere un errore dal compilatore.
MODIFICATORE IN
Tale modificatore serve a rendere i parametri passati in sola lettura, read-only, cioè all’interno del metodo non verranno modificati. L’unica cosa che è permesso di modificare sono gli attributi della classe MyClass ma non il riferimento all’oggetto.
using System; namespace Modificatori_Ref_Out_In { public class MyClass { public int x = 10; } class Program { static void Main(string[] args) { MyClass mc = new MyClass(); int k = 10; MyMethod(mc,k); Console.WriteLine($"{mc.x} {k}");//x=20, k=10 } static void MyMethod(in MyClass y, in int k) { //y= new MyClass();ERRORE DEL COMPILATORE //k=20;ERRORE DEL COMPILATORE y.x=20; } } }
Lascia un commento