Poniższy artykuł pochodzi z serii Przygotowań do egzaminu 70-536.
Lekcja 2 (Chapter 1) w Training Kit dotyczy typów referencyjnych (reference types) i wartościowych (value types). Tak naprawdę opisywanych jest tu kilka zagadnień. Pojawiają się tablice i operacje na nich, wyjątki, operacje na plikach oraz stringach. Wszystkie te zagadnienia są opisane dosyć pobieżnie i są to takie podstawy podstaw, więc doszedłem do wniosku że przedstawię tylko co ciekawsze zagadnienia.
O co więc chodzi z tymi typami referencyjnymi i wartościowymi? Do typów referencyjnych należą klasy, tablice, interfejsy, delegacje. Do typów wartościowych zaliczamy proste typy danych takie jak int, char czy byte. Typy różnią się od siebie przede wszystkim przydzielaniem pamięci oraz lokalizacją w hierarchii klas platformy .NET. Typy wartościowe mają przydzielaną pamięć na stosie.
W typach referencyjnych dane znajdują się na stercie, natomiast na stosie znajdują się referencje, czyli odwołanie do odpowiedniego miejsca na stercie. Troszkę to zagmatwane :) Pomiędzy opisywanymi typami zachodzi również różnica w momencie przypisywania wartości zmiennych. Kiedy przypisujemy zmiennej wartość typu referencyjnego, zmienna otrzymuje tylko referencję na oryginalny obiekt(a nie właściwą wartość tego obiektu). Dlatego poniższy kod powinien wyświetlić n1=3, n2=3.
Nasza klasa:
1: class Numbers
2: {
3: public int val;
4: public Numbers(int _val)
5: {
6: val = _val;
7: }
8: public override string ToString()
9: {
10: return val.ToString();
11: }
12: }
Oraz wywołanie:
1: Numbers n1 = new Numbers(0);
2: Numbers n2 = n1;
3: n1.val += 1;
4: n2.val += 2;
5: Console.WriteLine("n1={0}, n2={1}", n1,n2);
6: Console.ReadLine();
Jeżeli zamienimy klasę w strukturę (która jest typem wartościowym) otrzymamy wynik n1=1, n2=2. Dzieje się tak ponieważ przy typach wartościowych zachodzi przekopiowanie wartości, czyli zmiana jednej (wartości) nie powoduje zmiany drugiej.
W dalszej części lekcji mowa jest o najczęściej używanych wbudowanych typach referencyjnych.
Pierwszym z nich jest System.String oraz System.String.StringBuilder. Z tej części warto wiedzieć, że łańcuchy typu System.String są niezmienne. Oznacza to, że jakiekolwiek zmiany na łańcuchu powodują stworzenie nowego i porzucenie starego. Dlatego poniższy kod przydzieli w pamięci 3 nowe stringi:
1: string s;
2: s = "grupa";
3: s += ".NET";
4: s += "Eastgroup";
5: Console.WriteLine(s);
Po uruchomieniu powyższego kodu tylko ostatni string jest referencją. Dwa pozostałe są usuwane w procesie usuwania śmieci (garbage collection). Unikanie tego rodzaju tymczasowych łańcuchów pomaga uniknąć niepotrzebnego gromadzenia się śmieci, co poprawia wydajność. W poprawie wydajności ma nam pomóc klasa StringBuilder, która potrafi objąć wiele instrukcji. Jej domyślny konstruktor tworzy 16-bajtowy bufor, który rośnie w miarę potrzeb. Poniżej kod, który wykorzystuje StringBuilder’a do stworzenia napisu takiego jak poprzednio:
1: StringBuilder stringBuilder = new StringBuilder(30);
2: stringBuilder.Append("grupa");
3: stringBuilder.Append(".NET");
4: stringBuilder.Append("Eastgroup");
5: Console.WriteLine(stringBuilder.ToString());
W dalszej części lekcji pokazane zostały podstawy działania z wyjątkami, sortowanie tablicy oraz proste działanie na plikach (odczytywanie z pliku txt itp.) dlatego, tak jak pisałem na początku, nie będę omawiał tych zagadnień. Podejrzewam, że pojawią się one troszkę szerzej opisane w dalszej części książki.
Kolejny artykuł z serii to 70-536 Constructing Classes