2009-01-29 9 views
8

Myślę, że rozumiem pojęcie delegata w języku C# jako wskaźnik do metody, ale nie mogę znaleźć żadnych dobrych przykładów, gdzie byłoby to dobry pomysł, aby z nich korzystać. Jakie są przykłady, które są znacznie bardziej eleganckie/lepsze w przypadku delegatów lub nie można ich rozwiązać za pomocą innych metod?C# - Czy ktoś może mi powiedzieć, dlaczego i gdzie powinienem korzystać z delegatów?

+0

O Boże, zadałem to pytanie prawie rok temu, a teraz trudno wyobrazić sobie życie przed wyrażeniami delegatów/lambda! Muszę powiedzieć, że odpowiedzi tutaj nadal są jednymi z najlepszych przykładów w sieci. Taka jest moc SO. – Alex

Odpowiedz

6

Co dokładnie masz na myśli przez delegatów? Oto dwa sposoby, w których mogą być stosowane:

void Foo(Func<int, string> f) { 
//do stuff 
string s = f(42); 
// do more stuff 
} 

i

void Bar() { 
Func<int, string> f = delegate(i) { return i.ToString(); } 
//do stuff 
string s = f(42); 
// do more stuff 
} 

Chodzi w drugim jest to, że można zadeklarować nowych funkcji w locie, jak delegatów. Można to w dużej mierze zastąpić wyrażeniami lambda i jest przydatna za każdym razem, gdy masz małą logikę, którą chcesz 1) przekazać do innej funkcji, lub 2) po prostu wykonać wielokrotnie. LINQ jest dobrym przykładem. Każda funkcja LINQ przyjmuje jako argument wyrażenie lambda, określające zachowanie. Na przykład, jeśli masz List<int> l, wtedy l.Select(x=>(x.ToString()) wywoła ToString() na każdym elemencie na liście. A wyrażenie lambda, które napisałem, zostało zaimplementowane jako delegat.

Pierwszy przypadek pokazuje, jak można zastosować Select. Bierzesz delegata jako argument, a następnie wywołujesz go, gdy jest to potrzebne. Pozwala to wywołującemu dostosować sposób działania funkcji. Ponownie wybierając Select(), sama funkcja gwarantuje, że delegat, któremu zostaniesz przekazany, zostanie wywołany dla każdego elementu na liście, a wynik każdego z nich zostanie zwrócony. To, co delegatowi faktycznie jest , to należy do Ciebie. To sprawia, że ​​jest to niezwykle elastyczna i ogólna funkcja.

Oczywiście są również wykorzystywane do subskrybowania wydarzeń. W skrócie, delegaci umożliwiają ci odwoływanie się do funkcji, używanie ich jako argumentów w wywołaniach funkcji, przypisywanie ich do zmiennych i cokolwiek innego chcesz robić.

6

Używam głównie do łatwego programowania asynch. Wyrzucenie metody za pomocą metody Begin ... delegatów jest naprawdę łatwe, jeśli chcesz strzelać i zapomnieć.

Delegata można również używać jako interfejsu , np., gdy interfejsy nie są dostępne. Na przykład. metody wywoływania z klas COM, zewnętrzne klasy .Net itp.

0

tak naprawdę nie ma niczego, co rozwiąże rozwj, którego nie można rozwiązać innymi metodami, ale zapewniają one bardziej eleganckie rozwiązanie.

Z delegatami można korzystać z dowolnej funkcji, o ile ma wymagane parametry.

Alternatywą jest często używać rodzaju niestandardowe budowy systemu konferencyjnego w programie, tworząc dodatkową pracę i więcej obszarów do błędów do pełzania w

11

.NET 1.0 delegatów:

this.myButton.Click += new EventHandler(this.MyMethod); 

Użytkownicy .NET 2.0:

this.myOtherButton.Click += delegate { 
    var res = PerformSomeAction(); 
    if(res > 5) 
     PerformSomeOtherAction(); 
}; 

Wydają się bardzo przydatne. Co powiesz na:

new Thread(new ThreadStart(delegate { 
    // do some worker-thread processing 
})).Start(); 
+0

To jest po prostu niesamowite! Zrozumiany – SMUsamaShah

4

Wydarzenia są najbardziej oczywistym przykładem. Porównaj sposób implementacji wzorca obserwatora w Javie (interfejsy) i C# (delegaci).

Ponadto, wiele nowych funkcji C# 3 (na przykład wyrażeń lambda) opiera się na delegatach i jeszcze bardziej upraszcza ich użycie.

3

Na przykład w aplikacjach wielowątkowych. Jeśli chcesz, aby kilka wątków używało pewnej kontroli, będziesz używał delegatów. Przepraszamy, kod znajduje się w VisualBasic.

Najpierw zadeklarować delegata

Private Delegate Sub ButtonInvoke(ByVal enabled As Boolean) 

Napisz funkcję, aby włączyć przycisk/wyłączyć z kilku wątków

Private Sub enable_button(ByVal enabled As Boolean) 
    If Me.ButtonConnect.InvokeRequired Then 

     Dim del As New ButtonInvoke(AddressOf enable_button) 
     Me.ButtonConnect.Invoke(del, New Object() {enabled}) 
    Else 
     ButtonConnect.Enabled = enabled 
    End If 

End Sub 
2

nich korzystać przez cały czas z LINQ, zwłaszcza z wyrażeń lambda, aby zapewnić funkcja do oceny warunku lub zwrotu selekcji. Używaj ich również do zapewnienia funkcji, która porówna dwa przedmioty do sortowania. To ostatnie jest ważne w przypadku ogólnych kolekcji, w których domyślne sortowanie może być lub może nie być właściwe.

var query = collection.Where(c => c.Kind == ChosenKind) 
         .Select(c => new { Name = c.Name, Value = c.Value }) 
         .OrderBy((a,b) => a.Name.CompareTo(b.Name)); 
2

Jedną z zalet Delegatów jest wykonywanie asynchroniczne.

podczas asynchronicznego wywoływania metody nie wiadomo, kiedy zakończy wykonywanie, więc należy przekazać delegatowi do tej metody, która wskazuje inną metodę, która zostanie wywołana po zakończeniu pierwszej metody wykonania. W drugiej metodzie możesz napisać kod informujący, że wykonanie zostało zakończone.

1

Niektóre inne komentarze dotknął na świecie async ... ale i tak będę komentować, ponieważ mój ulubiony „smak” robi takie zostały wymienione:

ThreadPool.QueueUserWorkItem(delegate 
{ 
    // This code will run on it's own thread! 
}); 

Również ogromna powodem jest dla delegatów "CallBacks". Powiedzmy, że zrobię trochę funkcjonalności (asynchronicznie), a ty chcesz, żebym zadzwonił jakiś sposób (powiedzmy „AlertWhenDone”) ... można przejść w „delegata” na swój sposób, co następuje:

TimmysSpecialClass.DoSomethingCool(this.AlertWhenDone); 
1

Poza swoją rolą w wydarzeniach, które prawdopodobnie znasz, jeśli używałeś WinForm lub asp.net, uczestnicy są przydatni, aby uczynić zajęcia bardziej elastycznymi (np. Sposób, w jaki są używane w LINQ).

Elastyczność w przypadku "znajdowania" rzeczy jest dość powszechna. Masz kolekcję rzeczy i chcesz zapewnić sposób na znalezienie rzeczy. Zamiast zgadywać w dowolny sposób, że ktoś może chcieć znaleźć rzeczy, możesz teraz zezwolić rozmówcy na dostarczenie algorytmu, aby mógł przeszukiwać Twoją kolekcję, ale uznają to za stosowne.

Oto przykładowy kod trywialny:

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

namespace Delegates 
{ 
    class Program 
    { 
     static void Main(string[] args) 
     { 
      Collection coll = new Collection(5); 
      coll[0] = "This"; 
      coll[1] = "is"; 
      coll[2] = "a"; 
      coll[3] = "test"; 

      var result = coll.Find(x => x == "is"); 

      Console.WriteLine(result); 

      result = coll.Find(x => x.StartsWith("te")); 

      Console.WriteLine(result); 

    } 

} 

public class Collection 
{ 
    string[] _Items; 

    public delegate bool FindDelegate(string FindParam); 

    public Collection(int Size) 
    { 
     _Items = new string[Size]; 

    } 

    public string this[int i] 
    { 
     get { return _Items[i]; } 
     set { _Items[i] = value; } 
    } 

    public string Find(FindDelegate findDelegate) 
    { 
     foreach (string s in _Items) 
     { 
      if (findDelegate(s)) 
       return s; 
     } 
     return null; 
    } 

} 
} 

Wyjście

jest

Test

2

Technicznie delegat jest typem odniesienia używany do hermetyzacji metodę z konkretnego podpisu i Typ zwrotu

0

tam jest zaletą korzystania delegata gdy ma do czynienia z połączeń zewnętrznych do bazy danych?

Na przykład można kodować A:

static void Main(string[] args) { 

      DatabaseCode("test"); 

} 

public void DatabaseCode(string arg) { 

      .... code here ... 

} 

poprawić w kodzie B:

static void Main(string[] args) { 

      DatabaseCodeDelegate slave = DatabaseCode; 
      slave ("test"); 

} 

public void DatabaseCode(string arg) { 

      .... code here ... 

} 
public delegate void DatabaseCodeDelegate(string arg); 

Wydaje się, że to jest subiektywne, ale to obszar, gdzie występują silne sprzeczne punkty widzenia?