Это правильный синтаксис для общих делегатов и событий? - PullRequest
3 голосов
/ 21 сентября 2010

Я читаю тему библиотеки msdn о genrics . Есть пример объявления события с общими делегатами, но правильно ли это?

// Code block 8. Generic event handling

public delegate void GenericEventHandler<S,A>(S sender,A args);
public class MyPublisher
{
   public event GenericEventHandler<MyPublisher,EventArgs> MyEvent;
   public void FireEvent()
   {
      MyEvent(this,EventArgs.Empty);
   }
}
public class MySubscriber<A> //Optional: can be a specific type
{
   public void SomeMethod(MyPublisher sender,A args)
   {...}
}
MyPublisher publisher = new MyPublisher();
MySubscriber<EventArgs> subscriber = new MySubscriber<EventArgs>();
publisher.MyEvent += subscriber.SomeMethod;  // is this line correct?

Можем ли мы напрямую применить метод к событию, не оборачивая его сначала нашим делегатом?

Ответы [ 3 ]

6 голосов
/ 21 сентября 2010

Да, это новый функционал в C # 2.0, и он создаст для вас делегата. Обратите внимание, что вы все еще создаете делегата, но создание невидимо.

1 голос
/ 22 сентября 2010
publisher.MyEvent += subscriber.SomeMethod; 

В приведенной выше строке правое выражение «subscriber.SomeMethod» имеет тип GenericEventHandler (S sender, A args).

Так же, как объекты являются экземплярами типов классов, методы являются экземплярами типов делегатов. Класс определяет шаблон для объекта ... делегат определяет сигнатуру для метода ...., который является параметром и возвращаемым типом. Переменная типа делегата - это просто ссылка на один из нескольких методов, сигнатура которых соответствует сигнатуре, указанной в объявлении делегата.

В старых версиях C # вам нужно написать что-то вроде следующего:

publisher.MyEvent +=    
  new GenericEventHandler<MyPublisher,EventArgs>(subscriber.SomeMethod);

В более новых версиях C # тип этого длинного уродливого выражения с правой стороны автоматически определяется, когда вы просто предоставляете subscriber.SomeMethod. И это определяется подписью SomeMethod, а также типом MyEvent ... который является делегатом, определяющим подпись.

Если код в SomeMethod действительно тривиален, и вы не будете вызывать его из какого-либо другого места в программе, вы можете полностью избежать написания его в именованном методе (например, SomeMethod) и вместо этого использовать синтаксис анонимного метода как следующий и написать тут же:

publisher.MyEvent += delegate(MyPublisher s, EventArgs a)
                             { 
                                 /* the SomeMethod Code */ 

                             };

Или, что еще лучше, используйте лямбда-выражения, подобные следующим:

 publisher.MyEvent += (s, a) => {/*the SomeMethod code*/};

В вышеприведенном лямбда-выражении типы параметров 's' и 'a' автоматически выводятся из типа MyEvent. ... который, конечно, делегат, указывающий подпись.

Теперь каждый раз, когда MyEvent запускает код в анонимном методе или лямбда-выражение будет выполняться.

0 голосов
/ 08 марта 2012

Я думаю, что это называется Делегатский вывод . Но как бы это ни называлось, его вполне законно использовать. Это синтаксически сахар , добавленный в c # 3.0

Возможно, вам следует использовать это, если вам нужно понять работу Универсальных делегатов и событий

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

namespace Generic_Delegates_and_Events
{
    public delegate void GenericEventHandler<S,A>(S sender,A args); //generic delegate

    public class MyPublisher
    {
        public event GenericEventHandler<MyPublisher,EventArgs> MyEvent;
        public void FireEvent()
        {
            MyEvent(this,EventArgs.Empty);
        }
    }

    public class MySubscriber<A> //Optional: can be a specific type
    {
        public void SomeMethod(MyPublisher sender,A args)
        {
            Console.WriteLine("MySubscriber::SomeMethod()");
        }
    }
    public class MySubscriber2<A> //Optional: can be a specific type
    {
        public void SomeMethod2(MyPublisher sender, A args)
        {
            Console.WriteLine("MySubscriber2::SomeMethod2()");
        }
    }
    class Program
    {
        static void Main(string[] args)
        {
            MyPublisher publisher = new MyPublisher();
            MySubscriber<EventArgs> subscriber = new MySubscriber<EventArgs>();
            publisher.MyEvent += subscriber.SomeMethod;
            MySubscriber2<EventArgs> subscriber2 = new MySubscriber2<EventArgs>();
            publisher.MyEvent += subscriber2.SomeMethod2;
            publisher.FireEvent();
        }
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...