Co powiesz na poniższy kod? Co się stanie?
1: static void Main(string[] args)
2: {
3: StringBuilder sb = new StringBuilder();
4: Method(sb);
5: Console.WriteLine(sb.ToString());
6: }
7:
8: static void Method(StringBuilder fooSB)
9: {
10: fooSB.Append("test");
11: fooSB = null;
12: }
Muszę Ci powiedzieć, że źle zgadałem co się stanie. Pierwszą moją myślą, było, że podczas wykonania się programu w linijce 5 zostanie wyrzucony wyjątek NullReferenceException. A co się okazało po uruchomieniu programu w Visual Studio? Wyświetlił się napis “test”. Co jak już napisałem z początku mnie zaskoczyło.
No ale w czym tkwi szczegół. Przecież obiekty do metod są przekazywane przez referencje i w tym przypadku tak powinno się wykonać. Nawet dowodzi to, że do StringBuildera został dodany napis “test”. Szczegół w tym, że sama referencja jest przekazywana przez wartość. Co oznacza, że do metody jest kopiowany adres, pod którym znajduje się StringBuilder i wszystkie operacje na nim są ok.
Natomiast jeśli zmienimy samą referencje – przypiszemy jej wartość null, to zmienia się wartość kopi oryginalnej referencji, a nie oryginalna referencja i dlatego nie nastąpi wyrzucenie wyjątku w powyższym kodzie.
Natomiast w kodzie poniżej (do sygnatury metody zostało dodane słowo kluczowe ref):
1: static void Main(string[] args)
2: {
3: StringBuilder sb = new StringBuilder();
4: Method(ref sb);
5: Console.WriteLine(sb.ToString());
6: }
7:
8: static void Method(ref StringBuilder fooSB)
9: {
10: fooSB.Append("test");
11: fooSB = null;
12: }
Nastąpi już wyrzucenie wyjątku NullReferenceException, dlatego, że referencja do obiektu jest przekazywana przez referencje, a nie wartość i zmiana referencji w ciele metody, spowoduje zmianę oryginalnej referencji z metody Main.
A Ty wiedziałeś co się stanie?
Tags: csharp,
ref
Categories: Techniczne
92389248-e281-4e91-aeef-116e8328d4e2|3|2.3