Есть ли лучший способ написать этот повторяющийся код объявления события в C # при явной реализации интерфейса? - PullRequest
2 голосов
/ 06 мая 2010

У меня много кода, подобного следующему, где я явно реализую некоторые события, требуемые интерфейсом.

public class IMicrowaveNotifier {
  event EventHandler<EventArgs> DoorClosed;
  event EventHandler<EventArgs> LightbulbOn;
  // ...
}

public class Microwave : IMicrowaveNotifier {
  private EventHandler<EventArgs> _doorClosed;
  event EventHandler<EventArgs> IMicrowaveNotifier.DoorClosed {
    add { lock (this) _doorClosed += value; }
    remove { lock (this) _doorClosed -= value; }
  }

  private EventHandler<EventArgs> _lightbulbOn;
  event EventHandler<EventArgs> IMicrowaveNotifier.LightbulbOn {
    add { lock (this) _lightbulbOn += value; }
    remove { lock (this) _lightbulbOn -= value; }
  }

  // ...
}

Вы можете видеть, что многое из этого является шаблонным. В Ruby я мог бы сделать что-то вроде этого:

class Microwave
  has_events :door_closed, :lightbulb_on, ...
end

Есть ли аналогичный более короткий способ удаления этого шаблона в C #?

<Ч />

Обновление: Я исключил очень важную часть из моего примера: а именно, реализуемые события являются частью интерфейса, и я хочу реализовать это явно. Извините, что не упомянул об этом раньше!

Ответы [ 4 ]

10 голосов
/ 06 мая 2010

Попробуйте это:

public class Microwave {
    public event EventHandler<EventArgs> DoorClosed;
    public event EventHandler<EventArgs> LightbulbOn;
}

Этот код использует синтаксис C # полевого события :

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

В C # 1, 2 и 3 этот код будет компилироваться до того, что у вас есть выше. В C # 4 вы получите функционально эквивалентный код, который не использует явные блокировки . В любом случае вы можете использовать этот ярлык, не меняя потребителей этого типа.

Обновление: К сожалению, компилятор C # не позволяет вам использовать подобные событиям поля для явной реализации интерфейса. Если вы попытаетесь, вы получите эту ошибку компиляции:

Явная реализация интерфейса события должна использовать синтаксис метода доступа к событию

Обновление: Очень плохо, что для явной реализации интерфейса требуется использование синтаксиса метода доступа к событиям. Было бы круто, если бы в C # добавилась возможность создавать автоматически реализуемые события, подобные полям, например:

event EventHandler<EventArgs> IAppliance.DoorClosed { add; remove; }

Но этот синтаксис уже более устарел, чем существующий полевой синтаксис событий, и будет применим только в тех случаях, когда элемент интерфейса был явно реализован. Лучшее, что я думаю, было бы, если бы компилятор просто позволил нам сделать это:

event EventHandler<EventArgs> IAppliance.DoorClosed;
0 голосов
/ 06 мая 2010

Фрагменты кода, предложенные gbogumil, сэкономят некоторое время. С другой стороны, если есть определенный интерфейс, который вы регулярно реализуете, который требует этого, возможно ли вам создать абстрактный базовый класс?

0 голосов
/ 06 мая 2010

Напишите фрагмент кода для него и используйте ярлык. Точно так же, как при использовании if for foreach {tab} {tab}.

0 голосов
/ 06 мая 2010

Я не уверен, что Lock делает, так как я новичок, но вы можете подключить все элементы управления или все, что вызывает эти события, только к одному событию. В этом случае просто выполните оператор if, чтобы проверить, кто его отправляет.

Я бы подумал, что это выглядело бы намного аккуратнее, но все же потребовал бы некоторого количества работы, я думаю.

...