Ref i OutCzęść NR.5Zastanawiałeś się nad tym co się dzieje ze zmiennymi, gdy wysyłasz je jako parametr do metody. Otóż parametry otrzymywane przez metody są kopiami. Czyli działanie metody nie wpłynie na wysłaną zmienną, ponieważ metoda operuje na kopii.
Nie ma znaczenia czy parametr jest typu int, float, string czy referencją on się nie zmieni. Oto przykład:
Cuboid cuboid = new Cuboid(1, 2, 3);
string napis = "Ala ma kota";
int liczba = 121;
NieZmienie(cuboid,liczba,napis);
Console.ReadLine();
static void NieZmienie(Cuboid cuboid,int liczba,string napis)
{
cuboid = new Cuboid(44, 555, 666);
liczba--;
napis = "1234567890qwertyuiopasdfghj";
}
Rezultat działającego kodu po skończonej metodzie.
Jak widać jest tak, jak mówię.
W trakcie wykonywania metody wydaje się ,że zmienne rzeczywiście ulegają zmianie ,ale tak nie jest. W czasie debugowania kodu zmienne o tej samej nazwie są przedstawiane zależnie od kontekstu wykonywania.
Metoda może zmienić argument obiekt, do którego się metoda referuje ,ale metoda nie może zmienić referencji do obiektu. Co to dokładnie znaczy? Znaczy to ,że mogę zmienić zawartość pól klasy Cuboid. Aby udowodnić to tymczasowo zmieniłem modyfikator dostępu pól klasy Cuboid z prywatnych na publiczne co jest złą praktyką.
public static void ZmienieZawartośćObiektu(Cuboid cu)
{
cu.a = 12;
cu.b = 21;
cu.h = 33;
}
Cuboid cu = new Cuboid(1,1,1);
ZmienieZawartośćObiektu(cu);
W większości wypadków to zachowanie jest całkowicie prawidłowe. Jednak czasami chcemy napisać metodę, która rzeczywiście zmieni nasze podane argumenty. W C# mamy do dyspozycji słowa kluczowe ref i out do tego celu.
Ref
Jeśli dopiszesz do parametru słowo kluczowe ref ,parametr stają się rzeczywiście tylko aliasem do metody. Czyli jakakolwiek jego zmiana w metodzie zostanie zachowana na zawsze. Dzieje się tak, ponieważ parametr w metodzie jest referencją do tego samego obiektu ,a nie kopii. Oto przykład tej samej metody “NieZmienie” tylko tym razem ona zmieni wartości na stałe. Może więc lepiej nazwać ją “Zmienie”.
static void Zmienie(ref Cuboid cuboid, ref int liczba,
ref string napis)
{
cuboid = new Cuboid(44, 555, 666);
liczba--;
napis = "1234567890qwertyuiopasdfghj";
}<
Słowo kluczowe ref też musi wystąpić przy wysłaniu parametrów do metody. Dobrze wiedzieć jak dana metoda zadziała i co robi z parametrami ,skoro nie mam wyboru i muszę użyć słowa kluczowego ref.
Cuboid argcuboid = new Cuboid(1, 2, 3);
string argnapis = "Ala ma kota";
int argliczba = 121;
Zmienie(ref argcuboid, ref argliczba, ref argnapis);
Zmieniłem nazwy zmiennych aby uświadomić, że w tym przypadku zmienna “argliczba” i parametr" “liczba” w metodzie referują się do tego samego obiektu.
Pamiętaj, że zmienne, zanim wyślesz je do metody muszą mieć przypisane wartości.
Słowo kluczowe out
W metodzie z parametrem ref, parametr musi mieć przypisaną wartość, zanim zostanie wywołana metoda. Może jednak chciałbyś, by metoda operowana na niezainicjowanej zmiennej i ją zmieniła. Właśnie do tego celu służy słowo kluczowe “out”.
Słowo kluczowe out w działaniu jest zbliżone do ref. Argument jest aliasem dla parametru metody.
Kiedy tworzysz metodę z parametrem out. Pamiętaj aby w trakcie działania metoda przypisała parametrowi out jakąś domyślną wartość w jakimkolwiek ciągu operacji wewnątrz metody. Jednym słowem parametr zawsze musi wrócić z przypisaną wartością.
Zawsze.
static void Zmienie2(out int liczba)
{
liczba = 121;
}
int f;
Zmienie2(out f);
Przykładem metody, gdzie wstępują parametry out jest np. metoda int.TryParse().Znasz metodę Parse(), która zmienia łańcuch znaków na liczbę. Metoda ta najpierw sprawdza, czy dany łańcuch może być zmieniony na liczbę , a potem przypisuje do niej wartość.
int eee;
string li = Console.ReadLine();
int.TryParse(li,out eee);
Console.WriteLine(eee);
Powyższy kod sprawdza działanie tej metody w praktyce i jej działanie na pewno nie wyrzuci żadnego wyjątku, w przeciwieństwie do int.Parse().
Sprawdziłem tę metodę. Jeśli string jest liczbą, to zmienna ma przypisaną wartość z łańcucha znaków. Jeśli metoda nie była w stanie zmienić napisu na cyfrę zmienna równa się zero.