c # Использование ссылки на участника события - PullRequest
2 голосов
/ 13 января 2012

Кто-нибудь знает, почему это невозможно?Если событие является просто экземпляром MulticastDelegate, вы должны иметь возможность ссылаться на него в коде.компилятор говорит, что EventA может находиться только слева от - = или + =.

public delegate void MyDelegate();
public event MyDelegate EventA;

public void addHandlerToEvent(MulticastDelegate md,Delegate d){
 md+=d;

}

///
addHandlerToEvent(EventA,new MyDelegate(delegate(){}));

Ответы [ 3 ]

1 голос
/ 13 января 2012

Событие не является многоадресным делегатом, точно так же, как свойство не является полем.

Синтаксис C # event оборачивает многоадресные делегаты для упрощения жизни, предоставляя синтаксический сахар для добавления и удаления делегатов обработчиков.Ваше определение события будет скомпилировано в следующее:

private MyDelegate _EventA;

public event MyDelegate EventA
{
    [MethodImpl(MethodImplOptions.Synchronized)]
    add 
    { 
        _EventA = (MyDelegate)Delegate.Combine(_EventA, value);
    }

    [MethodImpl(MethodImplOptions.Synchronized)]
    remove 
    { 
        _EventA = (MyDelegate)Delegate.Remove(_EventA, value);
    }
}

Методы add и remove в расширенном определении события затем вызываются, когда вы используете operator += и operator -= для события.

Это сделано для того, чтобы скрыть внутренние элементы делегата многоадресной рассылки, но предоставляет простой способ реализации публикации / подписки на события.Возможность получить базовый делегат (вне класса, в котором он определен) нарушит эту намеренную инкапсуляцию.

1 голос
/ 13 января 2012

Событие - это член, который связывает пару методов добавления / удаления (*), каждый из которых принимает делегата, соответствующего сигнатуре события. По умолчанию компилятор C # будет автоматически определять поле делегата MultiCast для каждого события, а также добавлять и удалять члены, которые будут принимать переданный делегат и добавлять или удалять их в / из этого поля MulticastDelegate. Оператор myEvent += someMethod;, когда он выполняется вне класса, определяющего событие, является обязательным синтаксическим сокращением, по существу, myEvent.AddHandler(someMethod) и myEvent -= someMethod; для myEvent.RemoveHandler(someMethod), за исключением того, что в C # нет способа вызвать add / remove методы, за исключением использования обозначений += и -=.

При использовании нотации += и -= в классе, который определяет событие, все немного сложнее, поскольку поле, определенное автоматически сгенерированным кодом события, имеет то же имя, что и событие, и поведение myEvent += someMethod; зависит от версии C #.

(*) Технически трио, поскольку событие также включает в себя метод «повышения», но на практике этот метод практически никогда не используется.

1 голос
/ 13 января 2012

События поддерживаются многоадресными делегатами, да, но их цель состоит в том, чтобы обеспечить реализацию схемы наблюдателей , где наблюдатели (в данном случае делегаты) могут быть только зарегистрированы (+=) или незарегистрированы.(-=).Если бы нормальный доступ к поддерживающему делегату был возможен вне самого класса, тогда клиентский код мог бы вмешиваться в несвязанный делегат, который был зарегистрирован в другом месте, что могло бы испортить ситуацию.Кроме того, в некоторой степени за пределами паттерна наблюдателя стоит посмотреть, какие другие вещи наблюдают за рассматриваемым событием.

Если вам необходимо выполнить подобные манипуляции с делегатом поддержки,должно быть сделано внутри класса (где он обрабатывается как обычный делегат, а не событие).

Вы также можете явно реализовать вспомогательный делегат и предоставить средство доступа для регистрации / отмены регистрации с ним:

private EventHandler SomeEvent;

public event EventHandler
{
    add
    {
        SomeEvent += value;
    }
    remove
    {
        SomeEvent -= value;
    }
}

Таким образом, вы можете предоставить прямой доступ к делегату, если вам нужно.Тем не менее, по-прежнему лучше предоставлять публичный доступ к нему для целей подписки / отписки как события (а не необработанного делегата), в противном случае вы можете столкнуться с проблемами безопасности потоков с гонками данных на делегатах.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...