@rotabor

How to fire a base class event from the descendant class? Как запустить событие базового класса из класса-потомка?

Following Microsoft documentation, "Events are a special kind of multicast delegate that can only be invoked from within the class (or derived classes) or struct where they are declared (the publisher class)". In fact, an event can't be directly raised from th...
Typical solution here it to create a protected method in the base class to fire the event. Then call this method from a descendant class to fire the event.
Is any alternative way?
В соответствии с документацией Microsoft: «События — это особый тип многоадресного делегата, который можно вызывать только из класса (или производных классов) или структуры, в которой они объявлены (класс издателя)». Но, по факту, запустить событие из класса-потомка непосредственно нельзя!
Типовое решение в этом случае — создать защищенный метод в базовом классе для запуска события. Затем вызывать этот метод из класса-потомка, чтобы запустить событие.
Есть ли какой-то альтернативный вариант?
  • Вопрос задан
  • 36 просмотров
Решения вопроса 1
@rotabor Автор вопроса
The easiest solution is just to remove the 'event' access modifier from the event declaration. It will operate the same way, but will be accessible from derived classes (or outside, consider it).
Самое простое решение — это удалить модификатор доступа «event» из объявления события. Всё будет работать так же, но будет доступно из производных классов непосредственно (или извне, учитывайте).
Example/Пример из How to raise base class events in derived classes ...:
using System;
using System.Collections.Generic;

namespace BaseClassEvents
{
    // Special EventArgs class to hold info about Shapes.
    public class ShapeEventArgs : EventArgs
    {
        private double area;
        public ShapeEventArgs(double aea) { area = aea; }
        public double NewArea { get { return area; } }
    }
    // Base class event publisher
    public abstract class Shape
    {
        protected double _area;
        public double Area { get { return _area; } set { _area = value; } }
        // The event. Note that by using the generic EventHandler<T> event type
        // we do not need to declare a separate delegate type.
        public EventHandler<ShapeEventArgs> ShapeChanged; // ЭТО ЗДЕСЬ! убрали event
        public abstract void Draw();
        //The event-invoking method that derived classes can override.
        protected virtual void OnShapeChanged(ShapeEventArgs e) // ЭТО БОЛЬШЕ НЕ НУЖНО!
        {
            // Safely raise the event for all subscribers
            ShapeChanged.Invoke(this, e);
        }
    }
    public class Circle : Shape
    {
        private double _radius;
        public Circle(double radius)
        {
            _radius = radius;
            _area = 3.14 * _radius * _radius;
        }
        public void Update(double d)
        {
            _radius = d;
            _area = 3.14 * _radius * _radius;
            ShapeChanged(this, new ShapeEventArgs(_area)); // ЗАПУСКАЕМ СОБЫТИЕ НАПРЯМУЮ!
        }
        protected override void OnShapeChanged(ShapeEventArgs e) // ЭТО БОЛЬШЕ НЕ НУЖНО!
        {
            // Do any circle-specific processing here.
            // Call the base class event invocation method.
            base.OnShapeChanged(e);
        }
        public override void Draw() { Console.WriteLine("Drawing a circle"); }
    }
    public class Rectangle : Shape
    {
        private double _length, _width;
        public Rectangle(double length, double width)
        {
            _length = length; _width = width; _area = _length * _width;
        }
        public void Update(double length, double width)
        {
            _length = length; _width = width; _area = _length * _width;
            ShapeChanged(this, new ShapeEventArgs(_area)); // ЗАПУСКАЕМ СОБЫТИЕ НАПРЯМУЮ!
        }
        protected override void OnShapeChanged(ShapeEventArgs e) // ЭТО БОЛЬШЕ НЕ НУЖНО!

        }
             // Do any rectangle-specific processing here.
            // Call the base class event invocation method.
            base.OnShapeChanged(e);
        }
    public override void Draw() { Console.WriteLine("Drawing a rectangle"); }
        }
        // Represents the surface on which the shapes are drawn
        // Subscribes to shape events so that it knows
        // when to redraw a shape.
        public class ShapeContainer
    {
        private readonly List<Shape> _list;
        public ShapeContainer() { _list = new List<Shape>(); }
        public void AddShape(Shape shape)
        {
            _list.Add(shape);
            // Subscribe to the base class event.
            shape.ShapeChanged += HandleShapeChanged;
        }
        // ...Other methods to draw, resize, etc.
        private void HandleShapeChanged(object sender, ShapeEventArgs e)
        {
            // Diagnostic message for demonstration purposes.
            Console.WriteLine("Received event. Shape area is now " + e.NewArea);
            // Redraw the shape here.
            ((Shape)sender).Draw();
        }
    }
    class Test
    {
        static void Main()
        {
            //Create the event publishers and subscriber
            var circle = new Circle(54);
            var rectangle = new Rectangle(12, 9);
            var container = new ShapeContainer();
            // Add the shapes to the container.
            container.AddShape(circle);
            container.AddShape(rectangle);
            // Cause some events to be raised.
            circle.Update(57);
            rectangle.Update(7, 7);
            // Keep the console window open in debug mode.
            Console.WriteLine("Press any key to continue...");
            Console.ReadKey();
        }
    }
}
Ответ написан
Комментировать
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

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