Дизайн Языка C#: явная интерфейсная реализация события

Небольшой вопрос о дизайне языка 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

Я думаю, что подобные полю события являются некоторой двойственностью для автореализованных свойств.

Таким образом, мой вопрос: какова причина дизайна такого сделанного ограничения?

32
задан Stephen Kennedy 11 November 2018 в 12:45
поделиться

3 ответа

Интересный вопрос. Я немного порылся в архиве языковых заметок и обнаружил, что это решение было принято 13 октября 1999 года, но в заметках нет обоснования этого решения.

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

30
ответ дан 27 November 2019 в 20:13
поделиться

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

Например, это вызовет ошибку 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() { }
}

см. Ошибка компилятора CS0071

21
ответ дан 27 November 2019 в 20:13
поделиться

На самом деле это не было бы оригинальной мыслью с моей стороны.

Однако, я подумал, что мог бы ответить на это:

"Навскидку я не вижу никакой теоретической или практической причины, почему мы не могли бы иметь полеподобные явно реализованные события. Я также не вижу причин, по которым нам это особенно необходимо. Возможно, это останется одной из загадок непознанного." -Эрик Липперт


В главе 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 информацию о логике обработчиков событий при создании пользовательских коллекций из пользовательских объектов) - я упоминаю об этом только потому, что не претендую на авторитет в этом конкретном вопросе. Я просто студент, ищущий "просветления" :-)

.
1
ответ дан 27 November 2019 в 20:13
поделиться
Другие вопросы по тегам:

Похожие вопросы: