Referencje w C# – Jak obiekty „żyją” w pamięci

Co to jest referencja?

Referencja to jak „adres” obiektu w pamięci komputera. Gdy tworzymy obiekt, nie przechowujemy go bezpośrednio w zmiennej – przechowujemy tylko informację o tym, gdzie ten obiekt się znajduje.

Analogia z życia codziennego

Wyobraź sobie, że masz notes z adresami znajomych:

  • Dom przyjaciela = obiekt w pamięci
  • Adres w notesie = referencja
  • Notes = zmienna
// To jest jak zapisanie adresu w notesie
Osoba mojaOsoba = new Osoba();

Różnica między typami wartościowymi a referencyjnymi

Typy wartościowe (int, double, bool, char)

Typy wartościowe to typy danych, które przechowują swoją wartość bezpośrednio w zmiennej. Wyobraź sobie pudełko z napisem – w środku jest dokładnie to, co potrzebujesz.

int liczba1 = 10;
int liczba2 = liczba1;  // Kopiujemy wartość
liczba1 = 20;

Console.WriteLine(liczba1); // 20
Console.WriteLine(liczba2); // 10 - pozostało bez zmiany!

Typy referencyjne (klasy, string, tablice)

public class Osoba
{
    public string Imie;
    public int Wiek;
}

// Tworzymy obiekt
Osoba osoba1 = new Osoba();
osoba1.Imie = "Jan";
osoba1.Wiek = 18;

// "Kopiujemy" referencję (nie obiekt!)
Osoba osoba2 = osoba1;

// Zmieniamy przez osoba2
osoba2.Imie = "Anna";
osoba2.Wiek = 19;

// Co się stanie?
Console.WriteLine(osoba1.Imie); // Anna - zmienione!
Console.WriteLine(osoba1.Wiek); // 19 - zmienione!

Dlaczego tak się stało?

  • osoba1 i osoba2 wskazują na ten sam obiekt w pamięci
  • Zmiana przez jedną zmienną wpływa na drugą

Wizualizacja w pamięci

PAMIĘĆ:
┌─────────────────┐
│ Obiekt Osoba    │ ← Adres: 0x1A2B3C
│ Imie: "Anna"    │
│ Wiek: 19        │
└─────────────────┘
     ↑        ↑
   osoba1   osoba2
(0x1A2B3C) (0x1A2B3C)

Wartość null – „brak adresu”

Osoba osoba3 = null; // Nie wskazuje na żaden obiekt

// BŁĄD! - próba użycia nieistniejącego obiektu
// osoba3.Imie = "Piotr"; // NullReferenceException

Praktyczne przykłady

Przykład 1: Tablice

int[] tablica1 = {1, 2, 3};
int[] tablica2 = tablica1; // Ta sama referencja!

tablica2[0] = 999;

Console.WriteLine(tablica1[0]); // 999 - zmienione!

Przykład 2: Praca z obiektami

public class Samochod
{
    public string Marka;
    public string Model;
    public int Rocznik;
}

// Tworzymy dwa obiekty
Samochod auto1 = new Samochod();
auto1.Marka = "Toyota";

Samochod auto2 = new Samochod();
auto2.Marka = "BMW";

// auto1 i auto2 to różne obiekty!
Console.WriteLine(auto1.Marka); // Toyota
Console.WriteLine(auto2.Marka); // BMW

// Teraz kopiujemy referencję
Samochod auto3 = auto1; // auto3 wskazuje na ten sam obiekt co auto1
auto3.Marka = "Honda";

Console.WriteLine(auto1.Marka); // Honda - zmienione!

Najczęstsze błędy początkujących

Błąd 1: Myślenie, że kopiujemy obiekt

Osoba osoba1 = new Osoba();
osoba1.Imie = "Jan";

Osoba osoba2 = osoba1; // To NIE jest kopia obiektu!
// To jest kopia referencji (adresu)

Błąd 2: Nie sprawdzanie czy obiekt istnieje

Osoba osoba = null;
// osoba.Imie = "Test"; // BŁĄD! NullReferenceException

// Poprawnie:
if (osoba != null)
{
    osoba.Imie = "Test";
}

Sprawdzanie czy to ten sam obiekt

Osoba osoba1 = new Osoba();
Osoba osoba2 = new Osoba();
Osoba osoba3 = osoba1;

// Sprawdzanie referencji
Console.WriteLine(osoba1 == osoba2); // False - różne obiekty
Console.WriteLine(osoba1 == osoba3); // True - ten sam obiekt

// Sprawdzanie czy obiekt istnieje
Console.WriteLine(osoba1 != null); // True

Zadania do przećwiczenia

Zadanie 1: Przewiduj wynik

public class Ksiazka
{
    public string Tytul;
    public int Strony;
}

Ksiazka ksiazka1 = new Ksiazka();
ksiazka1.Tytul = "Hobbit";
ksiazka1.Strony = 300;

Ksiazka ksiazka2 = ksiazka1;
ksiazka2.Strony = 350;

Console.WriteLine(ksiazka1.Strony); // Co się wypisze?

Zadanie 2: Znajdź błąd

public class Student
{
    public string Imie;
    public double Ocena;
}

Student student = null;
student.Imie = "Kowalski"; // Gdzie jest błąd?