Делегаты C#

Discussion in 'С/С++, C#, Rust, Swift, Go, Java, Perl, Ruby' started by shadowmaster, 2 Sep 2010.

  1. shadowmaster

    shadowmaster New Member

    Joined:
    16 Aug 2010
    Messages:
    17
    Likes Received:
    0
    Reputations:
    0
    Собственно где более менее понятно написано про оные ?
    Для уровня выше среднего.
    Прочитал msdn разобрал примеры, но так не пойму их практического применения.
     
  2. .ATK

    .ATK Active Member

    Joined:
    20 Feb 2009
    Messages:
    143
    Likes Received:
    111
    Reputations:
    9
  3. Bers

    Bers Member

    Joined:
    17 May 2010
    Messages:
    78
    Likes Received:
    30
    Reputations:
    26
    Вот это самому прочесть никак? Хорошо, я прочту вслух: делегат - это суть указатель на функцию. Зачем нужен указатель на функцию? Чтобы дать возможность одной функции вызывать другую, неизвестную заранее (например, делегат на эту вызываемую функцию передается в вызывающую функцию как параметр). Теперь то же самое, но на примерах.

    Пример номер раз. События.
    События в .NET реализованы по сути как мультикаст делегат. Такой делегат ссылается не на одну функцию, а на список онных. Если у тебя есть такое событие:
    PHP:
    public class Foo
    {
      public 
    event EventHandler Bar;
    }
    То для того, чтобы подписаться на него, нужно передать в событие экземпляр делегата на функцию-обработчик:
    PHP:
    private void Foo_OnBar(object sender, EventArgs e)
    {
      
    System.Console.WriteLine("Foo.Bar triggered");
    }

    .....


    var 
    foo = new Foo();
    foo.Bar += new EventHandler(Foo_OnBar);
    // еще можно написать так:
    foo.Bar += Foo_OnBar;
    // в этом случае компилятор сам добавит создание экземпляра делегата.
    Пример номер два. LINQ и ему подобные вещи.
    Взглянем на такой LINQ-запрос:
    PHP:
    var input = new [] { 1, 2, 3, 4, 5, 6, 7 };
    var 
    result = input.Where(x => x > 0);
    А теперь взлянем на сигнатуру метода System.Linq.Enumerable.Where():
    PHP:
    public static IEnumerable<TSource> Where<TSource>(this IEnumerable<TSource> source, Func<TSource, bool> predicate);
    Вспомним, что Func<TX, TY> есть делегат такого вида:
    PHP:
    public delegate TY Func<TX, TY>(TX x);
    Т.е. предикат, передающийся в метод Where, - это тоже делегат. В данном случае это делегат на анонимный метод, к тому же его тип был выведен компилятором.
    Если переписать этот LINQ-запрос, используя синтаксис query comprehension, то делегаты станут еще более неявными :)
    PHP:
    var result = from x in input
                  where x 
    > 0
                  select x
    ;
    Однако это тот же самый запрос, и внутри него те же самые делегаты.

    Пример номер три. Простое делегирование :)

    Приведу еще пример простого делегирования, например, пусть это будет выполнение кода в потоке из пула потоков.

    PHP:

    System
    .Threading.ThreadPool.QueueUserWorkItem( _ =>
    {
      
    // do something
      
    System.Console.WriteLine("Job is done");
    });
    Ну, тут тоже хорошо видно, что сигнатура у метода QueueUserWorkItem примерно такая:
    PHP:
    public static void QueueUserWorkItem(WaitCallback callback);
    Где
    PHP:
    public delegate void QueueUserWorkItem(object state);
    Т.е., грубо говоря, делегаты используются почти везде. Сложно прочесть про них на MSDN и не понять, где же они вообще используются :)
     
    1 person likes this.