W języku C# klasy tworzy się podobnie jak w Javie, choć są elementy bardziej przypominające C++. Należy do nich pojęcie struktury.
Tak jak w C++ i Javie „normalne” klasy definiuje się używając słowa kluczowego class.
Można jednak użyć również słowa struct. W Javie jest to niedopuszczalne, w C++ w zasadzie równoważne użyciu class. W C# natomiast obiekty struktur i klas są zupełnie innego typu obiektami. Obiekty klas powstają na stercie (w pamięci wolnej), a deklarowana nazwa (poprzedzająca słowo kluczowe new) jest nazwą nie obiektu, ale odniesienia do obiektu (tak jak w Javie). Natomiast obiekty struktur tworzone są na stosie, tak jak zwykłe lokalne zmienne typów wbudowanych i tak jak w C++ obiekty klas i struktur które tworzymy na stosie (a nie na stercie za pomocą new). W C# nawet jeśli użyjemy new obiekt struktury (ale nie klasy) tworzony jest na stosie. Obowiązuje dla takich obiektów „semantyka wartości”, co w szczególności oznacza, że nazwa może być traktowana jako nazwa obiektu, a nie odnośnika.
Ma to daleko idące konsekwencje. Rozpatrzmy przykład:
1. using System;
2.
3. class OSOBA {
4. public string nazwisko;
5. public int wiek;
6. public OSOBA(string n, int w) {
7. nazwisko = n;
8. wiek = w;
9. }
10. }
11.
12. struct Osoba {
13. public string nazwisko;
14. public int wiek;
15. public Osoba(string n, int w) {
16. nazwisko = n;
17. wiek = w;
18. }
19. }
20.
21. class StruClass {
22. public static void Main() {
23. OSOBA kJanek = new OSOBA("Janek",18);
24. OSOBA kPiotr = new OSOBA("Piotr",19);
25.
26. Console.WriteLine("Po utworzeniu obiektow " +
27. "klasy:\n" +
28. "Janek: " + kJanek.nazwisko + " " +
29. kJanek.wiek + " : " + "Piotr: " +
30. kPiotr.nazwisko + " " + kPiotr.wiek);
31.
32. kJanek = kPiotr;
33. kPiotr.wiek = 29;
34.
35. Console.WriteLine("Po przypisaniu i zmianie " +
36. "wieku Piotra:\n" +
37. "Janek: " + kJanek.nazwisko + " " +
38. kJanek.wiek + " : " + "Piotr: " +
39. kPiotr.nazwisko + " " + kPiotr.wiek + "\n");
40.
41. Osoba sJanek = new Osoba("Janek",18);
42. Osoba sPiotr = new Osoba("Piotr",19);
43.
44. Console.WriteLine("Po utworzeniu obiektow " +
45. "struktury:\n" +
46. "Janek: " + sJanek.nazwisko + " " +
47. sJanek.wiek + " : " + "Piotr: " +
48. sPiotr.nazwisko + " " + sPiotr.wiek);
49.
50. sJanek = sPiotr;
51. sPiotr.wiek = 29;
52.
53. Console.WriteLine("Po przypisaniu i zmianie " +
54. "wieku Piotra:\n" +
55. "Janek: " + sJanek.nazwisko + " " +
56. sJanek.wiek + " : " + "Piotr: " +
57. sPiotr.nazwisko + " " + sPiotr.wiek + "\n");
58. }
59. }
Po utworzeniu obiektow klasy:
Janek: Janek 18 : Piotr: Piotr 19
Po przypisaniu i zmianie wieku Piotra:
Janek: Piotr 29 : Piotr: Piotr 29
Po utworzeniu obiektow struktury:
Janek: Janek 18 : Piotr: Piotr 19
Po przypisaniu i zmianie wieku Piotra:
Janek: Piotr 19 : Piotr: Piotr 29
W liniach 23-24 tworzymy dwa obiekty klasy: odnośniki do nich
nazywają się
kJanek
i
kPiotr. W linii 32
dokonujemy przypisania '
kJanek = kPiotr;' po czym zmieniamy
wiek Piotra (linia 33). W liniach 35-39 drukujemy informacje
o obu obiektach: widzimy, że są one identyczne. Zmieniliśmy wiek
Piotra, ale wiek Janka też się przy tym zmienił! Takie zachowanie
znamy z Javy.
Przyczyną tego jest to, że przypisanie
'
kJanek = kPiotr;' przepisało odniesienie do obiektu
opisującego Piotra do odnośnika
kJanek. Teraz wartością
obu odnośników,
kJanek
i
kPiotr, jest odniesienie
do tego samego obiektu. Obiekt pierwotnie wskazywany przez
odnośnik
kJanek
został „zgubiony” i może być usunięty
przez odśmiecacz.
Linie 41-57 są powtórzeniem linii 23-39 z tą różnicą, że teraz tworzymy nie obiekty klasy, ale obiekty struktury. Jak widzimy, przypisanie ' sJanek = sPiotr;' spowodowało przepisanie informacji zawartej w obiekcie sPiotr do obiektu sJanek, ale nie utożsamiło tych dwóch obiektów. Zmiana wieku Piotra w linii 51 zmodyfikowała tylko obiekt sPiotr, ale nie sJanek, co widzimy z wydruku: obiekt sJanek zawiera informacje takie jakie zostały tam wpisane za pomocą przypisania ' sJanek = sPiotr;'. Wiek Piotra został potem zmieniony, ale nie miało to już wpływu na wiek zapisany w obiekcie kJanek. Tak więc w tym przypadku mamy cały czas do czynienia z dwoma obiektami, a nazwy sPiotr i sJanek są nazwami tych obiektów, a nie odnośników do nich.
Podsumowując
Oczywiście klasy, struktury, konstruktory, tworzenie obiektów itd. to tematy bardzo obszerne i każdy język obiektowy ma mnóstwo specyficznych cech. Ponieważ naszym właściwym celem jest poznanie języka C++, więc nie będziemy tu szerzej omawiać szczegółowo różnic pomiędzy C# a Javą i C++, poprzestając na zasygnalizowaniu tylko niektórych z nich.
T.R. Werner, 21 lutego 2016; 20:17