🔥 Zapisy zamknięte, ale możesz pobrać Roadmapę .NET i dołączyć do listy oczekujących — Pobierz i dołącz do Listy VIP →

Paradygmaty w C# — proceduralny, OOP, funkcyjny

Paradygmaty programowania w C# — proceduralny, obiektowy, funkcjonalny, grafika

C# to jeden z niewielu języków, w którym możesz napisać ten sam program w trzech zupełnie różnych stylach — i wszystkie się skompilują. To nie historia z podręcznika — to praktyczny wybór, którego dokonujesz codziennie, często nieświadomie. Rozłóżmy jedno zadanie na trzy paradygmaty, żeby zobaczyć różnicę na własne oczy.

Zadanie: policz wartość koszyka z rabatem

Mamy listę produktów w koszyku. Klienci z statusem VIP dostają 10% rabatu na całość. Chcemy policzyć końcową kwotę do zapłaty.

Programowanie proceduralne

Kod to sekwencja kroków wykonywanych jeden po drugim, operujących na współdzielonych danych.

decimal ObliczKoszykProceduralnie(List<decimal> ceny, bool czyVip)
{
    decimal suma = 0;
    foreach (var cena in ceny)
    {
        suma += cena;
    }

    if (czyVip)
    {
        suma = suma * 0.9m;
    }

    return suma;
}

Prosto, czytelnie, działa. Problem pojawia się, gdy reguł rabatowych przybywa (rabat za ilość, kod promocyjny, rabat sezonowy) — funkcja rośnie, zbierając kolejne if-y, aż staje się trudna do ogarnięcia jednym spojrzeniem.

Programowanie obiektowe

Dane i zachowanie, które na nich operuje, żyją razem w jednym obiekcie.

public class Koszyk
{
    private readonly List<decimal> _ceny = new();
    public bool CzyVip { get; set; }

    public void Dodaj(decimal cena) => _ceny.Add(cena);

    public decimal ObliczSume()
    {
        decimal suma = _ceny.Sum();
        return CzyVip ? suma * 0.9m : suma;
    }
}

var koszyk = new Koszyk { CzyVip = true };
koszyk.Dodaj(100m);
koszyk.Dodaj(50m);
Console.WriteLine(koszyk.ObliczSume()); // 135

Teraz Koszyk hermetyzuje swój stan (_ceny) i logikę (ObliczSume) w jednym miejscu. Nowe reguły rabatowe mogą stać się osobnymi klasami implementującymi wspólny interfejs (dokładnie to pokazuje Strategy Pattern) — zamiast rosnącego if-a, masz zestaw małych, wymiennych klas.

Programowanie funkcjonalne

Dane się nie zmieniają (immutability), a rozwiązanie to złożenie czystych funkcji, które dla tych samych argumentów zawsze zwracają ten sam wynik.

decimal ObliczKoszykLinq(IEnumerable<decimal> ceny, bool czyVip)
{
    decimal suma = ceny.Sum();
    return czyVip ? suma * 0.9m : suma;
}

Żadnej zmiennej, która mutuje się krok po kroku (suma += cena zniknęło na rzecz ceny.Sum()) — dane przepływają przez funkcje, nie są modyfikowane w miejscu. To styl, w którym pisze się większość kodu LINQ — szerzej w LINQ w C#.

C# to język wieloparadygmatowy — i to jest jego siła

Powyższe trzy przykłady to nie trzy różne języki — to jeden i ten sam C#. W praktyce miksujesz style w obrębie tej samej klasy: obiektowa struktura (Koszyk jako klasa) z funkcyjną implementacją metody (_ceny.Sum() zamiast pętli), z proceduralnym fragmentem tam, gdzie kolejność kroków ma znaczenie (np. logowanie). Nie musisz wybierać jednego na całe życie projektu — wybierasz najlepsze narzędzie do konkretnego fragmentu kodu.

public class KoszykHybrydowy // obiektowa struktura
{
    private readonly List<decimal> _ceny = new();
    public bool CzyVip { get; set; }

    public void Dodaj(decimal cena) => _ceny.Add(cena); // proceduralna operacja — kolejność ma znaczenie

    public decimal ObliczSume() =>
        CzyVip ? _ceny.Sum() * 0.9m : _ceny.Sum(); // funkcyjna implementacja — LINQ, bez mutacji
}

Pułapka: dogmatyczne trzymanie się jednego paradygmatu

// ❌ "Wszystko musi być obiektowe" — klasa i interfejs dla trywialnego dodawania VAT
public interface IVatCalculator { decimal Calculate(decimal cena); }
public class VatCalculator : IVatCalculator
{
    public decimal Calculate(decimal cena) => cena * 1.23m;
}
var kalkulator = new VatCalculator();
var wynik = kalkulator.Calculate(100m);
// ✅ To wystarczy — nie każdy problem potrzebuje pełnej struktury obiektowej
decimal DodajVat(decimal cena) => cena * 1.23m;

To samo dotyczy przesady w drugą stronę — jeden długi łańcuch LINQ, który próbuje zrobić wszystko w jednej linijce, bywa trudniejszy do przeczytania niż prosta pętla foreach. Żaden paradygmat nie jest “lepszy” uniwersalnie — dogmatyczne trzymanie się jednego z nich, niezależnie od problemu, to dokładnie ta sama pułapka, przed którą ostrzega KISS: nie komplikuj kodu narzędziem, którego problem nie potrzebuje.

Kiedy który styl wybrać

  • Proceduralny — krótkie skrypty, sekwencje kroków, gdzie kolejność wykonania jest istotą problemu (np. konfiguracja aplikacji przy starcie).
  • Obiektowy — gdy modelujesz byty z tożsamością i stanem, które zmieniają się w czasie i mają jasno określone zachowanie (encje domenowe, serwisy).
  • Funkcjonalny — transformacje danych, przetwarzanie kolekcji, logika bez efektów ubocznych, którą łatwo testować w izolacji (dokładnie to, co LINQ robi najlepiej).

Nowoczesny C# (rekordy, pattern matching, LINQ, wyrażenia lambda) systematycznie dokłada narzędzia funkcyjne do języka, który zaczynał jako czysto obiektowy — nie dlatego, że jeden paradygmat “wygrał”, tylko dlatego, że różne problemy w tym samym systemie zasługują na różne narzędzia.

Podsumowanie

Paradygmat programowania to nie akademicka etykieta — to konkretny sposób organizacji kodu, który wybierasz świadomie, patrząc na naturę problemu. C# pozwala łączyć proceduralne, obiektowe i funkcyjne podejście w jednym pliku, jednej klasie, a nawet jednej metodzie — umiejętność rozpoznania, które podejście pasuje do którego fragmentu kodu, jest bardziej wartościowa niż deklaracja przynależności do jednego “obozu”.

👨‍💻
Mariusz Jurczenko
Senior .NET Developer · 10+ lat doświadczenia komercyjnego

Programista .NET z doświadczeniem komercyjnym w firmach takich jak NFZ, Kamsoft, Diagnostyka, Hermes Reply Polska czy Etisoft Smart Solutions. Twórca kursów, z których skorzystało już ponad 11 000 osób w Strefie Kursów i ponad 1 000 kursantów na dev-hobby.pl.

Specjalizacja: Clean Code, Clean Architecture i uczenie programowania tak, żeby dało się je naprawdę zrozumieć — nie wykuć.

🚀 Co dalej?

Zobacz to w praktyce na wideo i pobierz darmową roadmapę, żeby ułożyć naukę w spójną ścieżkę do pierwszej pracy.

Dodaj komentarz

czytanie to początek

Zamień wiedzę w umiejętności

Pobierz darmową Roadmapę .NET i ułóż takie tematy jak ten w spójną ścieżkę do pierwszej pracy.

Pobieram roadmapę →