C # знает два термина, delegate
и event
. Давайте начнем с первого.
делегат
A delegate
является ссылкой на метод. Также как вы можете создать ссылку на экземпляр:
MyClass instance = myFactory.GetInstance();
Вы можете использовать делегата для создания ссылки на метод:
Action myMethod = myFactory.GetInstance;
Теперь, когда у вас есть эта ссылка на метод, вы можете вызвать метод через ссылку:
MyClass instance = myMethod();
Но почему ты? Вы также можете просто позвонить myFactory.GetInstance()
напрямую. В этом случае вы можете. Однако, есть много случаев, чтобы подумать о том, где вы не хотите, чтобы остальная часть приложения знала myFactory
или вызывала myFactory.GetInstance()
напрямую.
Очевидным является, если вы хотите иметь возможность заменить myFactory.GetInstance()
в myOfflineFakeFactory.GetInstance()
одном центральном месте (он же шаблон фабричного метода ).
Шаблон фабричного метода
Итак, если у вас есть TheOtherClass
класс, и он должен использовать myFactory.GetInstance()
, вот как будет выглядеть код без делегатов (вам нужно сообщить TheOtherClass
о типе вашего myFactory
):
TheOtherClass toc;
//...
toc.SetFactory(myFactory);
class TheOtherClass
{
public void SetFactory(MyFactory factory)
{
// set here
}
}
Если вы используете делегатов, вам не нужно указывать тип моей фабрики:
TheOtherClass toc;
//...
Action factoryMethod = myFactory.GetInstance;
toc.SetFactoryMethod(factoryMethod);
class TheOtherClass
{
public void SetFactoryMethod(Action factoryMethod)
{
// set here
}
}
Таким образом, вы можете передать делегат другому классу для использования, не раскрывая им ваш тип. Единственное, что вы выставляете - это подпись вашего метода (сколько у вас параметров и тому подобное).
«Подпись моего метода», где я слышал это раньше? О да, интерфейсы !!! интерфейсы описывают сигнатуру целого класса. Представьте, что делегаты описывают сигнатуру только одного метода!
Еще одно большое различие между интерфейсом и делегатом заключается в том, что при написании класса вам не нужно говорить на C # «этот метод реализует этот тип делегата». Что касается интерфейсов, вам нужно сказать «этот класс реализует этот тип интерфейса».
Кроме того, ссылка на делегат может (с некоторыми ограничениями, см. Ниже) ссылаться на несколько методов (вызванных MulticastDelegate
). Это означает, что при вызове делегата будет выполнено несколько явно присоединенных методов. Ссылка на объект всегда может ссылаться только на один объект.
Ограничения для a MulticastDelegate
заключаются в том, что подпись (метод / делегат) не должна иметь никакого возвращаемого значения ( void
) и ключевых слов out
и ref
не используется в подписи. Очевидно, что вы не можете вызвать два метода, которые возвращают число и ожидают, что они вернут один и тот же номер. Как только подпись соответствует, делегат автоматически становится MulticastDelegate
.
Мероприятие
События - это просто свойства (например, get; set; свойства для полей экземпляра), которые предоставляют подписку делегату от других объектов. Эти свойства, однако, не поддерживают get; set ;. Вместо этого они поддерживают add; удалять;
Таким образом, вы можете иметь:
Action myField;
public event Action MyProperty
{
add { myField += value; }
remove { myField -= value; }
}
Использование в пользовательском интерфейсе (WinForms, WPF, UWP и т. Д.)
Итак, теперь мы знаем, что делегат является ссылкой на метод и что у нас может быть событие, которое позволит миру узнать, что они могут дать нам свои методы, на которые будут ссылаться наши делегаты, и мы являемся кнопкой UI, тогда: мы может попросить любого, кто интересуется, нажали ли на меня, зарегистрировать свой метод у нас (через событие, которое мы выставили). Мы можем использовать все те методы, которые были нам даны, и ссылаться на них нашим делегатом. А потом мы будем ждать и ждать .... пока пользователь не придет и не нажмет на эту кнопку, у нас будет достаточно причин для вызова делегата. И поскольку делегат ссылается на все эти методы, данные нам, все эти методы будут вызваны. Мы не знаем, что делают эти методы, и мы не знаем, какой класс реализует эти методы. Все, что нас волнует, это то, что кто-то был заинтересован в том, чтобы нас нажимали,
Ява
Такие языки, как Java, не имеют делегатов. Вместо этого они используют интерфейсы. Они делают так, чтобы попросить любого, кто заинтересован в том, чтобы «нас нажимали», реализовать определенный интерфейс (с помощью определенного метода, который мы можем вызвать), а затем предоставить нам весь экземпляр, который реализует интерфейс. Мы храним список всех объектов, реализующих этот интерфейс, и можем вызывать их «определенный метод, который мы можем вызвать» всякий раз, когда нас нажимают.