Nuta
Dostęp do tej strony wymaga autoryzacji. Możesz spróbować zalogować się lub zmienić katalogi.
Dostęp do tej strony wymaga autoryzacji. Możesz spróbować zmienić katalogi.
Delegat to typ, który bezpiecznie hermetyzuje metodę, podobnie jak wskaźnik funkcji w języku C i C++. W przeciwieństwie do wskaźników funkcji języka C, delegaty są obiektami zorientowanymi, bezpiecznymi i bezpiecznymi typami. W poniższym przykładzie zadeklarowano delegata o nazwie Callback, który może obudowywać metodę, która przyjmuje string jako argument i zwraca void.
public delegate void Callback(string message);
Obiekt delegata jest zwykle konstruowany przez podanie nazwy metody, którą opakowuje delegat, lub za pomocą wyrażenia lambda. W ten sposób można wywołać delegata. Wywołanie delegata powoduje uruchomienie metody przypisanej do instancji delegata. Parametry przekazywane do delegata przez obiekt wywołujący są przekazywane do metody. Delegat zwraca, jeśli istnieje, wartość zwracaną z metody. Przykład:
// Create a method for a delegate.
public static void DelegateMethod(string message)
{
Console.WriteLine(message);
}
// Instantiate the delegate.
Callback handler = DelegateMethod;
// Call the delegate.
handler("Hello World");
Typy delegatów pochodzą z Delegate klasy na platformie .NET. Typy delegatów są zapieczętowane, nie można ich rozszerzać i nie można utworzyć klas niestandardowych z Delegate. Ponieważ zainicjowany delegat jest obiektem, można go przekazać jako argument lub przypisać do właściwości. Metoda może przyjąć delegata jako parametr i wywołać delegata w późniejszym czasie. Jest to nazywane wywołaniem zwrotnym asynchronicznym i jest to typowa metoda powiadamiania obiektu wywołującego po zakończeniu długiego procesu. Gdy delegat jest używany w ten sposób, kod używający delegata nie potrzebuje żadnej wiedzy na temat implementacji używanej metody. Funkcjonalność jest podobna do hermetyzacji, którą zapewniają interfejsy.
Innym typowym zastosowaniem wywołań zwrotnych jest zdefiniowanie niestandardowej metody porównania i przekazanie tego delegata do metody sortowania. Dzięki niemu kod obiektu wywołującego staje się częścią algorytmu sortowania. Poniższa przykładowa metoda używa typu Callback jako parametru.
public static void MethodWithCallback(int param1, int param2, Callback callback)
{
callback("The number is: " + (param1 + param2).ToString());
}
Następnie możesz przekazać delegata utworzonego w poprzednim przykładzie do tej metody:
MethodWithCallback(1, 2, handler);
Na konsoli zostanie wyświetlony następujący wynik:
The number is: 3
MethodWithCallback nie musi bezpośrednio wywoływać konsoli — nie trzeba jej projektować z myślą o konsoli. To, co robi MethodWithCallback, to przygotowanie ciągu i przekazanie go do innej metody. Metoda delegowana może używać dowolnej liczby parametrów.
Gdy delegat jest tworzony, aby opakować metodę instancji, odnosi się zarówno do tej instancji, jak i do metody. Delegat nie ma wiedzy o typie instancji, poza metodą, którą opakowuje. Delegat może odwoływać się do dowolnego typu obiektu, o ile istnieje metoda dla tego obiektu zgodna z podpisem delegata. Gdy delegat jest skonstruowany w celu opakowania metody statycznej, odwołuje się tylko do metody . Rozważ następujące deklaracje:
public class MethodClass
{
public void Method1(string message) { }
public void Method2(string message) { }
}
Oprócz pokazanych wcześniej statycznych metod DelegateMethod mamy teraz trzy metody, które można opakowować w wystąpieniu Callback .
Delegat może wywołać więcej niż jedną metodę, co nazywa się multicastem. Aby dodać dodatkową metodę do listy metod delegata — listy wywołań — wystarczy dodać delegata, używając operatorów dodawania lub przypisania dodawania ('+' lub '+='). Przykład:
var obj = new MethodClass();
Callback d1 = obj.Method1;
Callback d2 = obj.Method2;
Callback d3 = DelegateMethod;
//Both types of assignment are valid.
Callback allMethodsDelegate = d1 + d2;
allMethodsDelegate += d3;
Obiekt allMethodsDelegate zawiera trzy metody na liście wywołań —Method1 , Method2i DelegateMethod. Oryginalne trzy delegaty, d1, d2i d3, pozostają niezmienione. Po wywołaniu allMethodsDelegate wszystkie trzy metody są wywoływane w ustalonej kolejności. Jeśli delegat używa parametrów odwołania, odwołanie jest przekazywane sekwencyjnie do każdej z trzech metod z kolei, a wszelkie zmiany według jednej metody są widoczne dla następnej metody. Jeśli którakolwiek z metod zgłasza wyjątek, który nie jest przechwycony w metodzie, wyjątek ten jest przekazywany do wywołującego delegata. Nie są wywoływane żadne kolejne metody na liście wywołań. Jeśli delegat ma wartość zwracaną i/lub wychodzące parametry, zwraca wartość zwracaną i parametry ostatniej wywoływanej metody. Aby usunąć metodę z listy wywołań, użyj operatorów odejmowania lub przypisania odejmowania (- lub -=). Przykład:
//remove Method1
allMethodsDelegate -= d1;
// copy AllMethodsDelegate while removing d2
Callback oneMethodDelegate = (allMethodsDelegate - d2)!;
Ponieważ typy delegatów pochodzą z System.Delegate klasy, metody i właściwości zdefiniowane przez tę klasę mogą być wywoływane na delegacie. Aby na przykład znaleźć liczbę metod na liście wywołań delegata, możesz napisać:
int invocationCount = d1.GetInvocationList().GetLength(0);
Delegaty posiadający więcej niż jedną metodę na liście wywołań pochodzą z MulticastDelegate, która jest podklasą System.Delegate. Powyższy kod działa w obu przypadkach, ponieważ obie klasy obsługują element GetInvocationList.
Delegaty multiemisji są szeroko używane w obsłudze zdarzeń. Obiekty źródła zdarzeń wysyłają powiadomienia o zdarzeniach do obiektów adresatów zarejestrowanych w celu odbierania tego zdarzenia. Aby zarejestrować się na wydarzenie, adresat tworzy metodę zaprojektowaną do obsługi zdarzenia, a następnie tworzy delegata dla tej metody i przekazuje delegata do źródła zdarzenia. Delegat jest wywoływany przez źródło, gdy zdarzenie ma miejsce. Delegat wywołuje następnie metodę obsługi zdarzeń na odbiorcy, dostarczając dane zdarzenia. Źródło zdarzeń definiuje typ delegata dla danego zdarzenia. Aby uzyskać więcej informacji, zobacz Zdarzenia.
Porównanie delegatów dwóch różnych typów przypisanych w czasie kompilacji powoduje błąd kompilacji. Jeśli instancje delegatów są statycznie typu System.Delegate, porównanie jest dozwolone, ale w czasie wykonywania zwraca wartość false. Przykład:
delegate void Callback1();
delegate void Callback2();
static void method(Callback1 d, Callback2 e, System.Delegate f)
{
// Compile-time error.
Console.WriteLine(d == e);
// OK at compile-time. False if the run-time type of f
// is not the same as that of d.
Console.WriteLine(d == f);
}