Небольшой вопрос о дизайне языка C# :))
Если у меня был интерфейс как это:
interface IFoo {
int Value { get; set; }
}
Возможно явно реализовать такой интерфейс с помощью автореализованных свойств C# 3.0:
sealed class Foo : IFoo {
int IFoo.Value { get; set; }
}
Но если у меня было событие в интерфейсе:
interface IFoo {
event EventHandler Event;
}
И попытка явно реализовать его с помощью подобного полю события:
sealed class Foo : IFoo {
event EventHandler IFoo.Event;
}
Я получу следующую ошибку компилятора:
error CS0071: An explicit interface implementation of an event must use event accessor syntax
Я думаю, что подобные полю события являются некоторой двойственностью для автореализованных свойств.
Таким образом, мой вопрос: какова причина дизайна такого сделанного ограничения?
Интересный вопрос. Я немного порылся в архиве языковых заметок и обнаружил, что это решение было принято 13 октября 1999 года, но в заметках нет обоснования этого решения.
Навскидку, я не вижу никаких теоретических или практических причин, почему мы не можем иметь полеподобные явно реализованные события. Я также не вижу причин, по которым нам это особенно необходимо. Возможно, это останется одной из загадок непознанного.
При явной реализации события, которое было объявлено в интерфейсе, вы должны вручную предоставить средства доступа добавления и удаления событий, которые обычно предоставляются компилятором. Код доступа может связать событие интерфейса с другим событием в вашем классе или с собственным типом делегата.
Например, это вызовет ошибку CS0071:
public delegate void MyEvent(object sender);
interface ITest
{
event MyEvent Clicked;
}
class Test : Itest
{
event MyEvent ITest.Clicked; // CS0071
public static void Main() { }
}
Правильный способ:
public delegate void MyEvent(object sender);
interface ITest
{
event MyEvent Clicked;
}
class Test : Itest
{
private MyEvent clicked;
event MyEvent Itest.Clicked
{
add
{
clicked += value;
}
remove
{
clicked -= value;
}
}
public static void Main() { }
}
На самом деле это не было бы оригинальной мыслью с моей стороны.
Однако, я подумал, что мог бы ответить на это:
"Навскидку я не вижу никакой теоретической или практической причины, почему мы не могли бы иметь полеподобные явно реализованные события. Я также не вижу причин, по которым нам это особенно необходимо. Возможно, это останется одной из загадок непознанного." -Эрик Липперт
В главе 23 книги A Programmer's Introduction to C#, Second Edition, Эрик Ганнерсон пишет:
"[I]если при нажатии на кнопку нужно вызвать другой класс, можно использовать оператор +=, например, так:
button.Click += new Button. ClickHandler(OtherMethodToCall);
К сожалению, если другой класс не был осторожен, он может сделать следующее:
button.Click = new Button.ClickHandler(OtherMethodToCall);
Это было бы плохо, поскольку это означало бы, что наш ButtonHandler будет отцеплен и будет вызван только новый метод."
...
"Необходим какой-то способ защиты поля делегата, чтобы доступ к нему осуществлялся только с помощью += и -=."
Далее на следующих нескольких страницах он комментирует включение методов add() и remove() для реализации такого поведения; возможность прямой записи в эти методы и последствия выделения памяти для ненужных ссылок на делегат.
Я бы добавил больше, но я слишком уважаю автора, чтобы делать это без его разрешения. Я рекомендую найти копию этой книги и вообще рекомендую все, что написано Эриком Ганнерсоном (блог и т.д...)
В любом случае, я надеюсь, что это имеет отношение к теме, и если да, то надеюсь, что это прольет свет на эту "тайну неизвестного"? (Я читал именно эту главу и искал на Stack Overflow информацию о логике обработчиков событий при создании пользовательских коллекций из пользовательских объектов) - я упоминаю об этом только потому, что не претендую на авторитет в этом конкретном вопросе. Я просто студент, ищущий "просветления" :-)
.