c #: доступ к событиям родительского класса невозможен? - PullRequest
6 голосов
/ 20 января 2011

никогда не сталкивался с этим раньше. Вот образец:

using System;

namespace Testing
{
    public class Test
    {
        public event Action ActionRequired;
    }

    public class ChildTest : Test
    {
        public void DoSomething()
        {
            if (this.ActionRequired != null)
                this.ActionRequired();
        }
    }
}

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

Нетрудно плавать (добавить защищенный метод в базовый класс, который одновременно проверяет вызов события и вызывает этот метод из дочерних классов), но мне действительно интересно, в чем смысл этого ограничения?

Приветствия

Sebi

Ответы [ 3 ]

14 голосов
/ 20 января 2011

Вы не можете вызывать события извне класса, в котором они были определены.Тем не менее, вам не нужно;просто следуйте идиоматическому паттерну, который также объявляет защищенный метод для запуска указанного события.

class Whatever
{
    public event EventHandler Foo;

    protected virtual void OnFoo( EventArgs e )
    {
        EventHandler del = Foo;
        if( del != null )
        {
            del( this, e );
        }
    }
}

Теперь потомки класса «Все» могут вызвать событие, вызвав OnFoo () и передав соответствующий объект EventArgs.

РЕДАКТИРОВАТЬ: Относительно того, почему это поведение, Джон Скит объяснил это хорошо в другой теме (что также означает, что этот вопрос является дубликатом, поэтому голосование закрыть):

Когда вы объявляете событие, подобное общедоступному полю, компилятор создает общедоступное событие и личное поле.Внутри одного и того же класса (или вложенных классов) вы можете получить доступ к полю напрямую, например, чтобы вызвать все обработчики.Из других классов вы видите только событие, которое позволяет только подписку и отписку.

3 голосов
/ 20 января 2011

Синтаксис, который вы использовали для объявления события в вашем примере, на самом деле является синтаксическим сахаром для чего-то вроде этого:

private Action _actionRequired;
public event Action ActionRequired
{
    add { _actionRequired += value; }
    remove { _actionRequired -= value }
}

(фактический код, конечно, немного сложнее)

Важной частью здесь является то, что поле _actionRequired является приватным.Только само событие является публичным, но это всего лишь пара методов добавления / удаления (аналогично свойству).Таким образом, единственное, что вы можете сделать с событием, это подписаться на него или отказаться от него.Поле, содержащее фактический делегат, является закрытым, поэтому доступ к нему можно получить только из класса, который его объявляет.Когда вы используете ActionRequired в классе, который его объявляет, он ссылается либо на поле делегата, либо на само событие, в зависимости от контекста.

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

1 голос
/ 05 января 2017

Согласно предыдущему ответу, добавленному @ThomasLevesque https://stackoverflow.com/a/4742280/3926461

Вы можете объявить свое действие, не используя этот синтаксический сахар Как показано ниже:

 public class Test
 {
    protected Action _actionRequired;
    public event Action ActionRequired {
        add {
            _actionRequired += value;
        }
        remove {
            _actionRequired += value;
        }
    }
 }

public class ChildTest : Test
{
    public void DoSomething()
    {
        if (this._actionRequired != null)
            this._actionRequired();
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...