Static w C# – współdzielone zasoby klasy

Poznasz słowo kluczowe static – pola i metody należące do klasy, nie do obiektów. Nauczysz się tworzyć liczniki instancji, klasy pomocnicze i zrozumiesz działanie Math, Console czy File!

static pole statyczne metoda statyczna klasa statyczna Math
01

Problem – dane wspólne dla wszystkich obiektów

Czasami potrzebujesz danych lub funkcji wspólnych dla wszystkich obiektów danej klasy. Jak to zrobić?

cs/Problem.cs C#
// 😰 PROBLEM: Chcemy zliczać ile obiektów utworzono

public class Uzytkownik
{
    public string Nazwa;
    public int Licznik;  // Każdy obiekt ma SWÓJ licznik!
    
    public Uzytkownik(string nazwa)
    {
        Nazwa = nazwa;
        Licznik++;  // Zwiększa tylko SWÓJ licznik
    }
}

Uzytkownik u1 = new Uzytkownik("Jan");
Uzytkownik u2 = new Uzytkownik("Anna");
Uzytkownik u3 = new Uzytkownik("Piotr");

Console.WriteLine(u1.Licznik);  // 1 – każdy ma swój!
Console.WriteLine(u2.Licznik);  // 1
Console.WriteLine(u3.Licznik);  // 1

// Chcieliśmy: 3 (łączna liczba użytkowników)
Problem

Zwykłe pola należą do każdego obiektu osobno. Potrzebujemy czegoś, co należy do klasy, nie do obiektów!

02

Czym jest static?

Słowo kluczowe static oznacza, że element należy do klasy, nie do obiektów. Istnieje jedna kopia dla całej klasy.

Analogia: Tablica ogłoszeń 📋

Wyobraź sobie klasę szkolną:

  • Pola instancyjne = zeszyt każdego ucznia (każdy ma swój)
  • Pola statyczne = tablica ogłoszeń (jedna dla wszystkich)

Gdy nauczyciel napisze ogłoszenie, wszyscy je widzą!

Analogia: Kalkulator na biurku 🧮
  • Metoda instancyjna = pisanie w swoim zeszycie (potrzebujesz SWOJEGO zeszytu)
  • Metoda statyczna = kalkulator na biurku nauczyciela (jeden dla wszystkich)
Klasa Uzytkownik
static LiczbaUzytkownikow = 3
↓ współdzielone ↓
u1
Nazwa: „Jan”
u2
Nazwa: „Anna”
u3
Nazwa: „Piotr”
03

Pola statyczne

Pole statyczne to zmienna należąca do klasy. Istnieje tylko jedna kopia.

cs/PoleStatyczne.cs C#
public class Uzytkownik
{
    // Pole STATYCZNE – jedno dla całej klasy
    public static int LiczbaUzytkownikow = 0;
    
    // Pole INSTANCYJNE – osobne dla każdego obiektu
    public string Nazwa;
    
    public Uzytkownik(string nazwa)
    {
        Nazwa = nazwa;
        Uzytkownik.LiczbaUzytkownikow++;  // Wspólny licznik
    }
}

// Przed utworzeniem
Console.WriteLine(Uzytkownik.LiczbaUzytkownikow);  // 0

Uzytkownik u1 = new Uzytkownik("Jan");
Uzytkownik u2 = new Uzytkownik("Anna");
Uzytkownik u3 = new Uzytkownik("Piotr");

Console.WriteLine(Uzytkownik.LiczbaUzytkownikow);  // 3 ✅
Dostęp przez nazwę klasy!

Do pól statycznych odwołujesz się przez nazwę klasy:

Uzytkownik.LiczbaUzytkownikow  // ✅ Przez klasę
u1.LiczbaUzytkownikow          // ⚠️ Działa, ale ZŁA PRAKTYKA

Stałe statyczne

cs/Stale.cs C#
public class Konfiguracja
{
    public const double PI = 3.14159265359;
    public static readonly string Wersja = "1.0.0";
}

// Użycie – bez new!
Console.WriteLine(Konfiguracja.PI);      // 3.14159...
Console.WriteLine(Konfiguracja.Wersja);  // 1.0.0
04

Pola statyczne vs instancyjne

Pole instancyjne

  • Należy do: obiektu
  • Kopie: każdy obiekt ma swoją
  • Dostęp: obiekt.Pole
  • Przykład: Imię użytkownika

Pole statyczne

  • Należy do: klasy
  • Kopie: jedna dla klasy
  • Dostęp: Klasa.Pole
  • Przykład: Liczba użytkowników
AspektInstancyjneStatyczne
Słowo kluczowebrakstatic
Liczba kopiiN (ile obiektów)1
Wymaga obiektu?TakNie
ŻyjeZ obiektemCały program
05

Metody statyczne

Metoda statyczna należy do klasy. Możesz ją wywołać bez tworzenia obiektu.

cs/MetodaStatyczna.cs C#
public class Kalkulator
{
    public static int Dodaj(int a, int b)
    {
        return a + b;
    }
    
    public static double Pierwiastek(double x)
    {
        return Math.Sqrt(x);
    }
}

// Użycie – BEZ tworzenia obiektu!
int suma = Kalkulator.Dodaj(5, 3);        // 8
double wynik = Kalkulator.Pierwiastek(16);  // 4.0

// NIE musisz robić:
// Kalkulator k = new Kalkulator();
// k.Dodaj(5, 3);
Ograniczenie!

Metoda statyczna nie ma dostępu do pól i metod instancyjnych!

cs/Ograniczenie.cs C#
public class Osoba
{
    public string Imie;                   // Instancyjne
    public static int LiczbaOsob = 0;    // Statyczne
    
    public static void WyswietlLiczbe()
    {
        Console.WriteLine(Osoba.LiczbaOsob);  // ✅ OK
        // Console.WriteLine(Imie);  // ❌ BŁĄD!
    }
}
Może używać?Metoda instancyjnaMetoda statyczna
Pola instancyjne✅ Tak❌ Nie
Pola statyczne✅ Tak✅ Tak
Metody instancyjne✅ Tak❌ Nie
Metody statyczne✅ Tak✅ Tak
06

Kiedy używać static?

✅ Użyj static gdy…Przykład
Nie potrzebujesz danych obiektuMath.Sqrt()
To funkcja pomocnicza (utility)StringHelper.Trim()
Metoda fabrykującaDateTime.Parse()
Operacje na danych wspólnychLicznik, konfiguracja
Punkt wejścia programuMain()
❌ NIE używaj static gdy…Dlaczego?
Metoda operuje na danych obiektuPotrzebujesz this
Zachowanie zależy od stanuKażdy obiekt może działać inaczej
Metoda może być nadpisanaStatic nie wspiera polimorfizmu
07

Klasy statyczne

Klasa statyczna zawiera tylko elementy statyczne. Nie można tworzyć jej instancji.

cs/KlasaStatyczna.cs C#
public static class Walidator
{
    public static bool CzyEmail(string tekst)
    {
        return tekst.Contains("@") && tekst.Contains(".");
    }
    
    public static bool CzyNumerTelefonu(string tekst)
    {
        return tekst.Length == 9 && tekst.All(char.IsDigit);
    }
}

// Użycie – bez new!
bool ok = Walidator.CzyEmail("jan@example.com");  // true

// ❌ NIE MOŻNA utworzyć instancji!
// Walidator w = new Walidator();  // BŁĄD!
Cechy klasy statycznej
  • static przed class
  • Wszystkie składowe MUSZĄ być statyczne
  • Nie można utworzyć obiektu
  • Nie może dziedziczyć
  • Idealna na funkcje pomocnicze
08

Konstruktor statyczny

Konstruktor statyczny jest wywoływany automatycznie, jeden raz, przy pierwszym użyciu klasy.

cs/KonstruktorStatyczny.cs C#
public class Baza
{
    public static string ConnectionString;
    public static DateTime DataUruchomienia;
    
    // Bez public! Bez parametrów!
    static Baza()
    {
        Console.WriteLine("Inicjalizacja...");
        ConnectionString = "Server=localhost";
        DataUruchomienia = DateTime.Now;
    }
}

Console.WriteLine("Start");
Console.WriteLine(Baza.ConnectionString);  // Tu się odpala!
Console.WriteLine(Baza.ConnectionString);  // Już nie

// Wynik:
// Start
// Inicjalizacja...
// Server=localhost
// Server=localhost
Cechy konstruktora statycznego
  • Brak modyfikatora dostępu
  • Brak parametrów
  • Wywoływany automatycznie
  • Tylko raz
09

Właściwości statyczne

cs/WlasciwosciStatyczne.cs C#
public class Aplikacja
{
    private static int _licznik = 0;
    
    public static int Licznik
    {
        get { return _licznik; }
        private set { _licznik = value; }
    }
    
    public static string Nazwa { get; set; } = "MojaApka";
    
    public static DateTime Start { get; } = DateTime.Now;
}

Console.WriteLine(Aplikacja.Nazwa);   // MojaApka
Console.WriteLine(Aplikacja.Start);   // 2024-01-15...

Przykład: DateTime.Now

cs/DateTimeNow.cs C#
// DateTime.Now to właściwość statyczna!
DateTime teraz = DateTime.Now;
DateTime dzisiaj = DateTime.Today;

// Nie tworzysz obiektu – to moc static!
10

Static w .NET

KlasaTypPrzykłady
MathKlasa statycznaMath.Sqrt(), Math.PI
ConsoleKlasa statycznaConsole.WriteLine()
FileKlasa statycznaFile.ReadAllText()
EnvironmentKlasa statycznaEnvironment.UserName
DateTimeStruct z staticDateTime.Now, DateTime.Parse()
intStruct z staticint.Parse(), int.MaxValue
stringKlasa z staticstring.IsNullOrEmpty()
cs/StaticNET.cs C#
// Math
double x = Math.Sqrt(25);       // 5
double y = Math.Pow(2, 10);     // 1024
int z = Math.Max(5, 10);         // 10

// int
int n = int.Parse("42");        // 42
int max = int.MaxValue;         // 2147483647

// string
bool ok = string.IsNullOrEmpty("");  // true
string s = string.Join(", ", new[] {"a", "b"});  // "a, b"

// File
bool istnieje = File.Exists("plik.txt");
string tekst = File.ReadAllText("dane.txt");
11

Wzorzec: Licznik instancji

cs/LicznikInstancji.cs C#
public class Produkt
{
    private static int _licznik = 0;
    public static int LiczbaProduktow => _licznik;
    
    public int Id { get; }
    public string Nazwa { get; set; }
    public decimal Cena { get; set; }
    
    public Produkt(string nazwa, decimal cena)
    {
        _licznik++;
        Id = _licznik;  // Unikalne ID
        Nazwa = nazwa;
        Cena = cena;
    }
}

Produkt p1 = new Produkt("Laptop", 2500);
Produkt p2 = new Produkt("Myszka", 50);

Console.WriteLine(p1.Id);  // 1
Console.WriteLine(p2.Id);  // 2
Console.WriteLine(Produkt.LiczbaProduktow);  // 2
12

Wzorzec: Klasa pomocnicza (utility)

cs/StringHelper.cs C#
public static class StringHelper
{
    public static string Capitalize(string s)
    {
        if (string.IsNullOrEmpty(s)) return s;
        return char.ToUpper(s[0]) + s.Substring(1).ToLower();
    }
    
    public static string Reverse(string s)
    {
        char[] arr = s.ToCharArray();
        Array.Reverse(arr);
        return new string(arr);
    }
    
    public static bool IsPalindrome(string s)
    {
        string clean = s.ToLower().Replace(" ", "");
        return clean == Reverse(clean);
    }
    
    public static int CountWords(string s)
    {
        if (string.IsNullOrWhiteSpace(s)) return 0;
        return s.Split(' ', StringSplitOptions.RemoveEmptyEntries).Length;
    }
}

// Użycie
string x = StringHelper.Capitalize("hELLO");    // "Hello"
string y = StringHelper.Reverse("ABC");        // "CBA"
bool p = StringHelper.IsPalindrome("kajak");  // true
int w = StringHelper.CountWords("To jest");   // 2
13

Częste błędy

❌ Błąd 1: Dostęp do instancyjnego z static

❌ Źle

public class Osoba
{
    public string Imie;
    
    public static void Wyswietl()
    {
        Console.WriteLine(Imie);
        // BŁĄD! Static nie zna Imie
    }
}

✅ Dobrze

public class Osoba
{
    public string Imie;
    
    public void Wyswietl()  // Bez static!
    {
        Console.WriteLine(Imie);
    }
}

❌ Błąd 2: Dostęp przez obiekt zamiast klasę

⚠️ Działa, ale ZŁE

Osoba o = new Osoba();
Console.WriteLine(o.LiczbaOsob);
// Działa, ale myląca składnia

✅ Dobrze

Console.WriteLine(Osoba.LiczbaOsob);
// Jasno widać że to static!

❌ Błąd 3: Tworzenie instancji klasy statycznej

❌ Źle

public static class Helper { }

Helper h = new Helper();
// BŁĄD KOMPILACJI!

✅ Dobrze

public static class Helper
{
    public static void Metoda() { }
}

Helper.Metoda();  // Bez new!

❌ Błąd 4: public w konstruktorze statycznym

❌ Źle

public class X
{
    public static X()  // BŁĄD!
    {
    }
}

✅ Dobrze

public class X
{
    static X()  // Bez modyfikatora!
    {
    }
}
14

Podsumowanie

Kluczowe pojęcia
  • static – element należy do klasy, nie do obiektów
  • Pole statyczne – jedna kopia dla całej klasy
  • Metoda statyczna – wywoływana bez obiektu
  • Klasa statyczna – tylko elementy static, bez new
  • Konstruktor statyczny – raz, automatycznie
ElementSkładniaDostęp
Pole statycznepublic static int X;Klasa.X
Metoda statycznapublic static void F()Klasa.F()
Klasa statycznapublic static class KK.Metoda()
Konstruktor stat.static Klasa()automatycznie

Schemat składni

cs/Schemat.cs C#
// Klasa z elementami static i instancyjnymi
public class Przyklad
{
    public static int Licznik;       // Statyczne
    public string Nazwa;              // Instancyjne
    
    static Przyklad() { }             // Konstr. statyczny
    public Przyklad() { }             // Konstr. instancyjny
    
    public static void MetodaStat() { }  // Statyczna
    public void MetodaInst() { }         // Instancyjna
}

// Klasa w pełni statyczna
public static class Helper
{
    public static void Metoda() { }
}
Zadania

Zadania praktyczne

📝 Zadanie 1: Licznik Studentów

Utwórz klasę Student z:

  • Polami: Imie, NumerIndeksu
  • Polem statycznym LiczbaStudentow
  • Konstruktorem zwiększającym licznik

Utwórz 5 studentów i wyświetl ich liczbę.

📝 Zadanie 2: Generator ID

Utwórz klasę Zamowienie gdzie każde zamówienie ma unikalne ID generowane automatycznie (1, 2, 3…).

💡 Podpowiedź: Użyj statycznego licznika w konstruktorze

📝 Zadanie 3: Klasa MathHelper

Utwórz statyczną klasę MathHelper z metodami:

  • IsEven(int n) – czy parzysta
  • IsPrime(int n) – czy pierwsza
  • Factorial(int n) – silnia

⭐ Zadanie 4: Konfiguracja aplikacji

Utwórz klasę AppConfig z:

  • Statycznymi właściwościami: AppName, Version, MaxUsers
  • Statycznym konstruktorem wczytującym wartości
  • Metodą DisplayConfig()

⭐⭐ Zadanie 5: Logger

Utwórz statyczną klasę Logger do logowania:

  • Log(string message) – wyświetla z datą
  • LogError(string message) – z „ERROR:”
  • LogWarning(string message) – z „WARNING:”
  • Statyczny licznik LogCount

💡 Użyj DateTime.Now do formatowania