0Pricing
C# Academy · Lekcja

Interfejsy generyczne

Uogólni Pan/Pani rozwiązania względem typów.

Interfejsy generyczne to bezpłatna lekcja C# Academy na CoddyKit. To lekcja 4 z 4. Możesz przeczytać całą lekcję poniżej za darmo — a potem ćwiczyć ją interaktywnie w przeglądarce z wbudowanym edytorem kodu i tutorem AI dostępnym 24/7. To część ścieżki edukacyjnej C# Academy, a Twój postęp synchronizuje się między webem a aplikacją CoddyKit. Kurs C# Academy zawiera 4 lekcji w sumie.

Czym jest interfejs generyczny?

Interfejs generyczny deklaruje parametry typu w nawiasach ostrych umieszczonych za nazwą. Klasy implementujące wybierają konkretne typy, a kontrakt interfejsu odpowiednio się dostosowuje.

Biblioteka .NET używa ich wszędzie, na przykład IEnumerable<T> i IComparable<T>.

interface IRepository<T>
{
    void Add(T item);
    T Get(int id);
}

Implementowanie interfejsu generycznego

Klasa może implementować interfejs generyczny, podając konkretny argument typu. Sygnatury metod używają wtedy rzeczywistego typu.

Powstaje w ten sposób bezpieczny typowo, wielokrotnego użytku kontrakt, który nie wymaga rzutowań.

using System.Collections.Generic;

class IntStore : IRepository<int>
{
    private readonly List<int> data = new();
    public void Add(int item) => data.Add(item);
    public int Get(int id) => data[id];
}

interface IRepository<T>
{
    void Add(T item);
    T Get(int id);
}

Zachowanie generyczności w klasie implementującej

Klasa może implementować interfejs generyczny, pozostając jednocześnie generyczna i przekazując własny parametr typu do interfejsu.

Dzięki temu implementacja pozostaje wielokrotnego użytku dla dowolnego typu elementu.

using System.Collections.Generic;

class Store<T> : IRepository<T>
{
    private readonly List<T> data = new();
    public void Add(T item) => data.Add(item);
    public T Get(int id) => data[id];
}

interface IRepository<T> { void Add(T item); T Get(int id); }

IComparable<T> w działaniu

IComparable<T> to wbudowany interfejs generyczny. Jego implementacja pozwala określić sposób porządkowania instancji danego typu, co umożliwia sortowanie.

Metoda CompareTo zwraca wartość ujemną, zero lub wartość dodatnią.

class Money : IComparable<Money>
{
    public int Cents;
    public int CompareTo(Money? other)
        => Cents.CompareTo(other?.Cents ?? 0);
}

Implementowanie IEnumerable<T>

IEnumerable<T> stanowi podstawę LINQ i instrukcji foreach. Typ, który go implementuje, można przeglądać za pomocą iteracji. Często deleguje się tę funkcję do iteratora wewnętrznej kolekcji.

Metody iteratorów z użyciem yield return ułatwiają to zadanie.

using System.Collections;
using System.Collections.Generic;

class Bag<T> : IEnumerable<T>
{
    private readonly List<T> items = new();
    public void Add(T x) => items.Add(x);
    public IEnumerator<T> GetEnumerator() => items.GetEnumerator();
    IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
}

Generyczny interfejs gotowy do uruchomienia

Ten kompletny program definiuje generyczny interfejs IPrinter<T>, implementuje go dla napisów, a następnie z niego korzysta.

Interfejs gwarantuje dostępność metody Print niezależnie od konkretnego typu.

using System;

interface IPrinter<T> { void Print(T value); }

class ConsolePrinter<T> : IPrinter<T>
{
    public void Print(T value) => Console.WriteLine(value);
}

class Program
{
    static void Main()
    {
        IPrinter<string> p = new ConsolePrinter<string>();
        p.Print("hello generics");
    }
}

Kowariancja z out

Parametr interfejsu generycznego oznaczony jako out jest kowariantny: występuje wyłącznie w pozycjach wyjściowych. Dzięki temu IEnumerable<Cat> można użyć tam, gdzie oczekiwane jest IEnumerable<Animal>.

Kowariancja zachowuje zgodność przypisań w łańcuchu dziedziczenia.

interface IProducer<out T>
{
    T Produce();
}

Kontrawariancja z in

Parametr oznaczony jako in jest kontrawariantny: występuje wyłącznie w pozycjach wejściowych. Dzięki temu IComparer<Animal> można użyć tam, gdzie potrzebny jest IComparer<Cat>.

Kontrawariancja odwraca kierunek przypisywania w przypadku odbiorców danych.

interface IConsumer<in T>
{
    void Consume(T item);
}

Wiele parametrów typów

Interfejsy generyczne mogą przyjmować więcej niż jeden parametr. IDictionary<TKey, TValue> to znany przykład z oddzielnymi typami klucza i wartości.

Każdy parametr może niezależnie być niezmienny, kowariantny lub kontrawariantny.

interface IMapper<TIn, TOut>
{
    TOut Map(TIn input);
}

Programowanie względem interfejsu

Korzystanie z generycznego interfejsu zamiast konkretnej klasy sprawia, że kod jest elastyczny. Można zamieniać implementacje bez zmieniania kodu wywołującego.

Parametry metod o typie IEnumerable<T> akceptują zarówno listy i tablice, jak i wyniki zapytań.

using System.Collections.Generic;
using System.Linq;

int Total(IEnumerable<int> values) => values.Sum();

Ograniczenia z użyciem interfejsów generycznych

Interfejsy generyczne często występują jako ograniczenia. where T : IComparable<T> pozwala metodzie sortować dane wejściowe lub je porównywać.

Łączy to dwie cechy generyków, umożliwiając tworzenie bezpiecznych i wielokrotnego użytku algorytmów.

T Min<T>(T a, T b) where T : IComparable<T>
    => a.CompareTo(b) <= 0 ? a : b;

Szybki test

Sprawdź swoją wiedzę na temat interfejsów generycznych.

Podsumowanie

Interfejsy generyczne deklarują parametry typów i pozwalają implementacjom je ustalać lub przekazywać dalej. Wbudowane przykłady obejmują IEnumerable<T>, IComparable<T> oraz IDictionary<TKey, TValue>.

Adnotacje wariancji out i in umożliwiają kowariancję i kontrawariancję, a interfejsy generyczne naturalnie współpracują z ograniczeniami where.

Często zadawane pytania

Czy lekcja „Interfejsy generyczne” jest bezpłatna?

Tak — pełny tekst „Interfejsy generyczne” jest dostępny za darmo tutaj w sieci. Aby ćwiczyć ją interaktywnie (wbudowany edytor kodu i tutor AI dostępny 24/7) i odblokować resztę kursu C# Academy, przejdź na CoddyKit PRO. Kurs C# Academy zawiera 4 lekcji w sumie.

Co nauczysz się w „Interfejsy generyczne”?

Uogólni Pan/Pani rozwiązania względem typów. Ćwiczysz C# Academy z praktycznym kodem, który uruchamiasz bezpośrednio w przeglądarce, a tutor AI dostępny 24/7 odpowiada na Twoje pytania podczas pracy nad lekcją.

Czy potrzebuję doświadczenia, aby zacząć C# Academy?

Nie wymagamy żadnego doświadczenia. C# Academy w CoddyKit jest strukturyzowany dla początkujących i zaawansowanych użytkowników, więc możesz zacząć tutaj lub od początku i uczyć się w swoim tempie. To lekcja 4 z 4.

Ile czasu zajmuje lekcja „Interfejsy generyczne”?

Większość lekcji CoddyKit trwa około 5–10 minut. Każda lekcja to mały, interaktywny krok, dzięki czemu robisz systematyczne postępy i zawsze wracasz dokładnie do tego samego miejsca — na webie i w aplikacji.

Czy mogę pisać i uruchamiać kod w tej lekcji C# Academy?

Tak. Każda lekcja C# Academy zawiera wbudowany edytor kodu, więc piszesz i uruchamiasz prawdziwy kod bezpośrednio w przeglądarce i od razu otrzymujesz sprzężenie zwrotne od AI — bez konfiguracji na komputerze.

Wszystkie lekcje w tym kursie

  1. Metody generyczne
  2. Klasy generyczne
  3. Ograniczenia where
  4. Interfejsy generyczne
← Powrót do C# Academy