Используйте событие и делегат в подклассе - PullRequest
5 голосов
/ 17 июня 2010

Почему я не могу использовать событие, объявленное в Base из Sub?

class Program
{
    static void Main(string[] args)
    {
        Sub sub = new Sub();
        sub.log += new Base.logEvent(sub_log);
        sub.go();
    }

    static void sub_log(string message, int level)
    {
        Console.Out.WriteLine(message + " " + level);
    }
}

public abstract class Base
{
    public delegate void logEvent(String message, int level);

    public event logEvent log;
}

public class Sub : Base
{

    public void go()
    {
        log("Test", 1); // <-- this wont compile
    }
}

Ответы [ 3 ]

6 голосов
/ 17 июня 2010

События могут быть вызваны только из класса, который их объявляет.

За пределами определения класса (даже в производном классе) вы можете регистрироваться и отменять регистрацию только из event. Внутри класса компилятор позволяет только вызвать событие. Это нестандартное поведение C # (которое на самом деле немного меняется в C # 4 - Крис Барроуз описывает изменения в своем блоге ).

То, что вы хотите здесь сделать, это предоставить метод RaiseLogEvent() в базовом классе, который позволил бы производному классу вызывать это событие.

public abstract class Base
{ 
  public delegate void logEvent(String message, int level); 

  public event logEvent log; 

  protected void RaiseLogEvent( string msg, int level )
  {
      // note the idomatic use of the copy/test/invoke pattern...
      logEvent evt = log;
      if( evt != null )
      {
          evt( msg, level );
      }
  }
} 

Кроме того, вам следует рассмотреть возможность использования типа делегата EventHandler<> вместо создания собственных типов событий, когда это возможно.

2 голосов
/ 17 июня 2010

Потому что события могут вызываться только из декларирующего класса. Просто создайте метод в базовом классе, чтобы вызвать его:

protected virtual RaiseLogEvent(string s, int i)
{
  log(s, i);
}

Так что вы можете использовать его при создании классов и даже переопределить его.

С другой стороны, я настоятельно рекомендую вам следовать рекомендациям по проектированию событий, создать собственный класс EventArgs и использовать делегат EventHandler<T>.

0 голосов
/ 06 августа 2015

Да, вы можете объявлять события в базовом классе, чтобы их также можно было вызывать из производных классов.

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

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

Повышение событий базового класса в производных классах

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