Ответ 1
Эквивалентная конструкция в D состоит в использовании Сигналов и слотов. Это другое средство реализации Наблюдательного паттерна, что фактически означает событие С#.
Недавно я закончил шестимесячную стажировку в компании, которая использует С# для большей части своего программирования. За это время я впервые использовал и привык к С#, чтобы делать события. Как показано ниже:
acc.AccountBalanceLow += new AccountBalanceDelegate(atm.AccountToLow);
acc.AccountBalanceLow +=new AccountBalanceDelegate(atm.AccountToLowAgain);
Поддерживает ли D такие конструкции? Я бы предположил, что пользователь может быть создан пользователем, используя перегрузку оператора, но я не совсем уверен. Если не возможно, что тогда было бы распространенным способом исключения?
Эквивалентная конструкция в D состоит в использовании Сигналов и слотов. Это другое средство реализации Наблюдательного паттерна, что фактически означает событие С#.
D (и С++) используют аналогичный шаблон сигналы и слоты.
Если вы чувствуете необходимость использовать стили-события С# вместо сигналов и слотов, их очень просто реализовать:
module fluidity.core.event;
class Event {
alias void delegate(EventArgs) handler_t;
handler_t[] handlers;
Object owner;
this() {}
this(Object o) { owner = o; }
void attach(handler_t handler) {
if (handler)
handlers ~= handler;
}
void detach(handler_t handler) {
int i = -1;
foreach (j, h; handlers)
{
if (h is handler)
{
i = j;
break;
}
}
if (i > -1)
handlers = handlers[0..i] ~ handlers[i+1..$];
}
void raise() { raise(new EventArgs(owner)); }
void raise(EventArgs e) {
// call all handlers
foreach (handler; handlers)
{
if (handler)
handler(e);
}
}
void opAddAssign(handler_t handler) {
attach(handler);
}
void opSubAssign(handler_t handler) {
detach(handler);
}
}
class EventArgs {
Object source;
bool handled;
void handle() { handled = true; }
this() {}
this(Object s) {
source = s;
}
}
Вот пример событий стиля С# с использованием сигналов, слотов и шаблонов:
events.d:
import std.signals;
class Event(T...){
mixin Signal!(T);
void broadcast(T args){
emit(args);
}
void opAddAssign(slot_t slot){
connect(slot);
}
void opSubAssign(slot_t slot) {
disconnect(slot);
}
}
декларация:
public Event!(int) onSomeEventOfInt;
public Event!(string, int) onSomeEventOfStringAndInt;
конкретизации:
this.onSomeEventOfInt = new Event!(int)();
this.onSomeEventOfStringAndInt = new Event!(string, int)();
событие пожара:
int i = 4;
string str = "hello";
this.onSomeEventOfInt.broadcast(i);
this.onSomeEventOfStringAndInt.broadcast(str, 4);
регистрация наблюдателя:
obj1.onSomeEventOfInt += &handleEventOfInt
obj1.onSomeEventOfStringAndInt += &handleEventOfStringAndInt
void handleEventOfInt(int g)
{ /*do something */ }
void handleEventOfStringAndInt(string str, int g)
{ /*do something */ }
Проверьте систему событий DFL. Он работает ТОЧНО так же, как С#.NET.
Загрузите DFL, возьмите модуль событий и используйте его так, как вам нравится. Я изменил его, чтобы использовать вариационные аргументы шаблона. Это дает максимальную гибкость.