CodeGym /Kursy /C# SELF /Konstruktory i inicjalizacja obiektu

Konstruktory i inicjalizacja obiektu

C# SELF
Poziom 16 , Lekcja 3
Dostępny

1. Proste konstruktory

Konstruktor — to specjalna metoda klasy, która wywołuje się automatycznie przy tworzeniu obiektu. Inicjalizuje (ustawia) obiekt: nadaje wartości początkowe, robi walidacje, może nawet poprawić ci humor, jeśli napiszesz w nim żart.

Konstruktor pozwala ci od razu stworzyć obiekt w określonym stanie, zamiast ustawiać wszystkie jego dane pojedynczo przez pola i właściwości ręcznie. To wygodne i bezpieczne, bo od razu podajesz wszystkie ważne parametry — i nie zapomnisz o czymś krytycznym.

Bez konstruktora kod może wyglądać topornie i być podatny na błędy:

Person p = new Person();
p.Name = "Julia";
p.Age = 25; // A co jeśli zapomnimy podać wiek?

Z konstruktorem:


Person p = new Person("Julia", 25); // Wszystko przekazane od razu i obiekt gotowy do życia!

Składnia konstruktora

Konstruktor — to specjalna "metoda", której nazwa dokładnie pokrywa się z nazwą klasy i która nie ma wartości zwracanej (nawet void). Tak wygląda konstruktor domyślny:


public class Person
{
    // Konstruktor domyślny (bez parametrów)
    public Person()
    {
        // Tu możesz napisać kod inicjalizacji
    }
}
Konstruktor domyślny

Konstruktor domyślny — to taki niewidzialny "pomocnik", który nie przyjmuje żadnych parametrów i po prostu ustawia wszystkie pola i właściwości twojej klasy na ich wartości domyślne:

  • Dla typów liczbowych (int, double, float itd.) to będzie 0.
  • Dla typu logicznego (bool) to false.
  • Dla typów referencyjnych (string, inne klasy) to null (czyli "nic", "brak referencji do obiektu").
  • Dla DateTime to będzie 01.01.0001 00:00:00.

Jak wywołać konstruktor?

Właściwie, kiedy piszesz operator new przy tworzeniu obiektu, wywołujesz konstruktor!

Person p = new Person();

Jeśli nie zdefiniujesz jawnie żadnego konstruktora, kompilator C# stworzy dla ciebie konstruktor domyślny (bez parametrów). Ale jeśli zadeklarujesz choć jeden własny — konstruktor domyślny znika i kompilator poprosi cię, żebyś dodał go ręcznie, jeśli go potrzebujesz.

Przykład

Dodajmy konstruktor do klasy naszej aplikacji. Oto prosta wersja klasy studenta:


public class Student
{
    public string Name;
    public int Age;

    // Konstruktor z dwoma parametrami (imię i wiek)
    public Student(string name, int age)
    {
        Name = name; // Przypisujemy wartość do pola
        Age = age;
    }
}

Teraz możesz stworzyć studenta tak:

Student s = new Student("Jan", 21);
Console.WriteLine($"{s.Name}: {s.Age} lat"); // Jan: 21 lat
  • Zadeklarowaliśmy konstruktor o tej samej widoczności (public), co sama klasa.
  • W konstruktorze przypisujemy wartości polom, używając przekazanych parametrów.
  • Taki sposób chroni przed zapominalstwem: kompilator wymusi podanie imienia i wieku przy tworzeniu obiektu.

2. Parametry konstruktora

W C# możesz zadeklarować kilka konstruktorów z różnymi zestawami parametrów. To się nazywa przeciążenie konstruktora (o przeciążaniu metod jeszcze pogadamy później).

Na przykład, dodajmy konstruktor bez parametrów:

public class Student
{
    public string Name;
    public int Age;

    // Konstruktor domyślny
    public Student()
    {
        Name = "Bez imienia";
        Age = 0;
    }

    // Konstruktor z parametrami
    public Student(string name, int age)
    {
        Name = name;
        Age = age;
    }
}

Teraz oba warianty są możliwe:


Student s1 = new Student();          // Imię: Bez imienia, wiek: 0
Student s2 = new Student("Ola", 22); // Imię: Ola, wiek: 22

Użycie konstruktora do walidacji

Konstruktor — świetne miejsce, żeby sprawdzać "jakość" przekazywanych danych. Na przykład, student nie może mieć ujemnego wieku!


public Student(string name, int age)
{
    if (age < 0)
        throw new ArgumentException("Wiek nie może być ujemny!");
    Name = name;
    Age = age;
}

Teraz jeśli ktoś spróbuje stworzyć studenta Student("Maluch", -2), aplikacja rzuci wyjątek (ArgumentException). Takie podejście często się stosuje dla "żelaznej" niezawodności danych.

3. Inicjalizacja złożonych obiektów

Często w prawdziwych aplikacjach jeden obiekt może "składać się" nie tylko z prymitywów, ale też zawierać inne obiekty:

public class Group
{
    public string GroupName;
    public Student[] Students;

    public Group(string groupName, Student[] students)
    {
        GroupName = groupName;
        Students = students;
    }
}

Teraz łatwo stworzyć grupę z zestawem studentów:

var students = new Student[]
{
    new Student("Jan", 20),
    new Student("Maria", 19)
};
Group g = new Group("Grupa-101", students);

Inicjalizacja pól domyślnych

Czasem chcesz ustawić wartości domyślne dla niektórych pól, jeśli nie wszystkie parametry trafiają do konstruktora. Na przykład, jeśli e-mail nie jest obowiązkowy:

public Student(string name, int age)
{
    Name = name;
    Age = age;
    Email = "unknown@noemail.com"; // Wartość domyślna
}

4. Inicjalizacja przez Object Initializer

Konstruktory możesz łączyć z inną wygodną składnią — inicjalizatorami obiektów. Możesz wywołać konstruktor, a potem w klamrach podać wartości właściwości nowego obiektu:


public class Student
{
    public string Name { get; set; }
    public int Age { get; set; }
    public string Email { get; set; }

    // Konstruktor i tak jest zalecany
    public Student(string name, int age)
    {
        Name = name;
        Age = age;
        Email = "";
    }
}

Student s = new Student("Antoni", 18) { Email = "antoni@domain.com" }; // konstruktor + właściwości

Ta składnia świetnie się sprawdza, gdy część parametrów ma wartości domyślne albo nie zawsze są znane przy tworzeniu.

5. Typowe błędy i niuanse

Pracując z konstruktorami, początkujący często trafiają na kilka popularnych błędów. Ogarniemy je na luzie:

Błąd nr 1: Niezgodność nazw
Czasem mylą się nazwy parametrów i pól, zwłaszcza jeśli różnią się tylko wielkością liter.


public Student(string Name, int Age) // Z wielkiej litery!
{
    Name = Name; // Ups! Oba Name odnoszą się do parametru. Pole zostanie nieustawione.
}

Jak poprawnie: Użyj this żeby odwołać się do pola obiektu:

public Student(string name, int age)
{
    this.Name = name;
    this.Age = age;
}

Albo po prostu wybieraj różne nazwy (np. nameParam, ageParam), ale praktyka z this. jest uznawana za dobry styl, szczególnie w większych projektach.

Błąd nr 2: Brak konstruktora domyślnego

Jeśli zadeklarowałeś choć jeden konstruktor, a potem próbujesz stworzyć obiekt bez parametrów — dostaniesz błąd kompilacji:

public class Student
{
    public Student(string name) { /*...*/ }
}

// gdzieś w kodzie
Student s = new Student(); // Błąd! Brak konstruktora bez parametrów.

Rozwiązanie: Jawnie dodaj konstruktor bez parametrów:

public Student() { /*...*/ }

Błąd nr 3: Nieskończona rekursja — jeśli konstruktor wywołuje sam siebie


public Student()
{
    // Błąd! Wywołuje sam siebie — nieskończona rekursja.
    new Student();
}
Komentarze
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION