Почему события не могут использоваться таким же образом в производных классах как в базовом классе в C#?

В Java все находится в форме класса.

Если вы хотите использовать любой объект, тогда у вас есть две фазы:

  1. Объявить
  2. Инициализация

Пример:

  • Объявление: Object a;
  • Инициализация: a=new Object();

То же самое для концепции массива

  • Объявление: Item i[]=new Item[5];
  • Инициализация: i[0]=new Item();

Если вы не дают секцию инициализации, тогда возникает NullpointerException.

31
задан skaffman 11 December 2010 в 21:24
поделиться

6 ответов

Общепринятая практика здесь должна иметь защищенный виртуальный метод OnSomeEvent на Вашем базовом классе, затем назвать тот метод в производных классах. Кроме того, для поточной обработки причин Вы захотите сохранить ссылку на обработчик прежде, чем проверить пустой указатель и назвать его.

Для объяснения, почему считанный Jon Skeet ответ или спецификация C#, которая описывает, как компилятор автоматически создает частное поле.

Вот одна возможная работа вокруг.

public class A
{
    public event EventHandler SomeEvent;

    public void someMethod()
    {
        OnSomeEvent();
    }

    protected void OnSomeEvent()
    {
        EventHandler handler = SomeEvent;
        if(handler != null)
            handler(this, someArgs);
    }
}

public class B : A
{
    public void someOtherMethod()
    {
        OnSomeEvent();
    }
}

Редактирование: Обновленный код, основанный на раздел Framework Design Guidelines 5.4 и напоминания другими.

37
ответ дан Community 27 November 2019 в 21:36
поделиться

Другие объяснили, как обойти проблему, но не, почему она подходит.

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

44
ответ дан Jon Skeet 27 November 2019 в 21:36
поделиться

Ответ Todd корректен. Часто Вы будете видеть реализованный всюду по платформе.NET как OnXXX(EventArgs) методы:

public class Foo
{
    public event EventHandler Click;

    protected virtual void OnClick(EventArgs e)
    {
        var click = Click;
        if (click != null)
            click(this, e);
    }
}

я сильно поощряю Вас рассматривать EventArgs<T> / EventHandler<T> шаблон , прежде чем Вы будете делать весь способ CustomEventArgs / CustomEventHandler для того, чтобы сгенерировать события.

5
ответ дан cfeduke 27 November 2019 в 21:36
поделиться

Причина исходный код не работает, состоит в том, потому что у Вас должен быть доступ к делегату события для повышения его, и C# сохраняет этого делегата private.

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

3
ответ дан Tim Robinson 27 November 2019 в 21:36
поделиться

Мой ответ был бы то, что Вам не придется сделать этого.

C# приятно осуществляет Только тип, объявляя/публикуя, что событие должно уволить/повысить его. , Если бы базовый класс доверял деривациям для имения возможности сгенерировать ее события, создатель представил бы защищенные методы сделать это. Если они не существуют, это - хорошая подсказка, что Вы, вероятно, не должны делать этого.

Мой изобретенный пример относительно того, насколько отличающийся мир был бы то, если бы производным типам позволили сгенерировать события в их предках.Примечание: это не допустимый код C#.. (все же..)

public class GoodVigilante
{
  public event EventHandler LaunchMissiles;

  public void Evaluate()
  {
    Action a = DetermineCourseOfAction(); // method that evaluates every possible
// non-violent solution before resorting to 'Unleashing the fury'

    if (null != a) 
    { a.Do(); }
    else
    {  if (null != LaunchMissiles) LaunchMissiles(this, EventArgs.Empty); }
  }

  virtual protected string WhatsTheTime()
  {  return DateTime.Now.ToString();  }
  ....   
}
public class TriggerHappy : GoodVigilante
{
  protected override string WhatsTheTime()
  {
    if (null != LaunchMissiles) LaunchMissiles(this, EventArgs.Empty);
  }

}

// client code
GoodVigilante a = new GoodVigilante();
a.LaunchMissiles += new EventHandler(FireAway);
GoodVigilante b = new TriggerHappy();             // rogue/imposter
b.LaunchMissiles += new EventHandler(FireAway);

private void FireAway(object sender, EventArgs e)
{
  // nuke 'em
}
2
ответ дан Gishu 27 November 2019 в 21:36
поделиться

Оберните его с защищенным виртуальным На... методе:

public class BaseClass
{
    public event EventHandler<MyArgs> SomeEvent;

    protected virtual void OnSomeEvent()
    {
        if(SomeEvent!= null)
            SomeEvent(this, new MyArgs(...) );
    }
}

Тогда переопределение это в производном классе

public class DerivedClass : BaseClass
{
    protected override void OnSomeEvent()
    {
        //do something

        base.OnSomeEvent();
    }
}

Вы установите этот шаблон на всем протяжении.Net - вся форма и веб-элементы управления следуют за ним.

не используют Повышение префикса... - это не согласовывается со стандартами MS и может вызвать беспорядок в другом месте.

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

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