1. Wprowadzenie do C#
  2. Szybki start
  3. Pierwszy program
  4. Komentarze
  5. Typy danych
  6. Zmienne
  7. Pola
  8. Właściwości
  9. Stałe
  10. Metody
  11. Instrukcje warunkowe
  12. Pętle
  13. Tablice
  14. Kolekcje
  15. Klasy
  16. Dziedziczenie
  17. Polimorfizm
  18. Konwersja typów
  19. Właściwości klasy String
  20. Typy wyliczeniowe
  21. Interfejsy
  22. Klasy statyczne
  23. Klasy Abstrakcyjne
  24. Przestrzenie nazw
  25. Wyjątki
  26. Typy generyczne
  27. JSON
  28. XML
  29. Podsumowanie

Delegaty generyczne

Delegaty generyczne to specjalny rodzaj delegatów, które pozwalają na przechowywanie referencji do metod generycznych. Delegat generyczny jest określony przez typ generyczny i ma takie same ograniczenia na typach generycznych jak metoda, do której jest przypisany.

Aby utworzyć delegata generycznego, należy zdefiniować nowy typ delegata za pomocą słowa kluczowego delegate , a następnie określić typ generyczny po nazwie delegata, używając znaku <>.

								
delegate T MojDelegat<T>(T arg);
								
						
Wyjaśnienie

W powyższym przykładzie MyDelegate jest delegatem generycznym, który przyjmuje jeden argument typu T i zwraca typ T.

Delegaty generyczne mogą być używane do przechowywania referencji do metod generycznych, a następnie wywoływania ich przez delegata.

								
using System;

class MojaKlasa
{
    public static T ZrobCos<T>(T arg)
    {
        // ...
        return arg;
    }
}

delegate T MojDelagat<T>(T arg);

class Program
{
    static void Main()
    {
        MojDelagat<int> del = MojaKlasa.ZrobCos;

        int wynik = del(5);

        Console.WriteLine(wynik); // wyświetla 5
    }
}
								
						

przykład, w którym używamy delegatów generycznych do implementacji systemu porównywania elementów w kolekcji:

								
using System;

class Kolekcja<T>
{
    private T[] elementy;

    public Kolekcja(T[] elementy)
    {
        this.elementy = elementy;
    }

    public void Sortuj(PorownajDelegat<T> porownaj)
    {
        Array.Sort(elementy, (x, y) => porownaj(x, y));
    }
}

delegate int PorownajDelegat<T>(T x, T y);

class Program
{
    static void Main()
    {
        int[] liczby = { 3, 7, 4, 2, 8, 6 };

        var kolekcja = new Kolekcja<int>(liczby);

        kolekcja.Sortuj(PorownajLiczby);

        foreach (int liczba in liczby)
        {
            Console.Write(liczba + " ");
        }
        // wyświetla: 2 3 4 6 7 8

        string[] slowa = { "abc", "def", "ghi", "jkl" };

        var kolekcja2 = new Kolekcja<string>(slowa);

        kolekcja2.Sortuj(PorownajSlowa);

        foreach (string slowo in slowa)
        {
            Console.Write(slowo + " ");
        }
        // wyświetla: abc def ghi jkl
    }

    static int PorownajLiczby(int x, int y)
    {
        return x - y;
    }

    static int PorownajSlowa(string x, string y)
    {
        return string.Compare(x, y);
    }
}
								
						

W tym przykładzie, delegaty PorownajLiczby i PorownajSlowa zwracają wartość int, która jest używana przez metodę Array.Sort do określenia kolejności elementów w tablicy.

Notatka

Dzięki temu, że klasa Kolekcja posiada metodę Sortuj z delegatem generycznym, możemy łatwo posortować różne kolekcje różnych typów danych za pomocą różnych kryteriów porównywania, bez konieczności tworzenia nowych metod sortujących dla każdego z nich.