在派生类中引发基类事件
(1)事件是特殊的委托,所以只可以在声明它的类中调用。在基类中声明一个事件,所以可以在基类中调用,而不能在派生类中直接调用。但有些情况下,需要在派生类中引用基类事件,实现方法是,在基类中定义一个受保护的方法引用事件,然后在派生类中重写基类方法,利用base关键字实现间接调用基类事件。
(2)派生类调用基类事件。
class DerivedClassEvent { static void Main(string[] args) { Circle c = new Circle(10); Console.WriteLine("Circle area is {0}", c.Area); Shape shape = c; shape.ShapeChanged += HandleShapeChanged; c.Update(100); Console.Read(); } private static void HandleShapeChanged(object sender,ShapeEventArgs e) { Shape s=(Shape)sender; Console.WriteLine("Received event.Shape area is now {0}", e.NewArea); s.Draw(); } } public class ShapeEventArgs : EventArgs { private double newArea; public double NewArea { get { return newArea; } } public ShapeEventArgs(double s) { newArea = s; } } /// <summary> /// 定义一个图形抽象类 /// 在该抽象类中声明一个事件 /// 并定义在图形发生改变时,触发一个事件 /// </summary> public abstract class Shape { protected double area; public double Area { get { return area; } set { area = value; } } public event EventHandler<ShapeEventArgs> ShapeChanged; public abstract void Draw(); protected virtual void OnShapeChanged(ShapeEventArgs e) { EventHandler<ShapeEventArgs> handler = ShapeChanged; if (handler != null) { handler(this, e); } } } /// <summary> /// 定义一个关于圆的类继承图形抽象类 /// </summary> public class Circle : Shape { private double radius; public Circle(double d) { radius = d; area = 3.14 * radius * radius; } public void Update(double d) { radius = d; area = 3.14 * radius * radius; OnShapeChanged(new ShapeEventArgs(area)); } /// <summary> /// 重写基类方法,然后用base关键字调用基类方法 /// 间接实现在子类中调用事件 /// </summary> /// <param name="e"></param> protected override void OnShapeChanged(ShapeEventArgs e) { base.OnShapeChanged(e); } public override void Draw() { Console.WriteLine("Drawing a circle"); } }
(3)msdn原例
namespace BaseClassEvents { using System; using System.Collections.Generic; // Special EventArgs class to hold info about Shapes. public class ShapeEventArgs : EventArgs { private double newArea; public ShapeEventArgs(double d) { newArea = d; } public double NewArea { get { return newArea; } } } // 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 event EventHandler<ShapeEventArgs> ShapeChanged; public abstract void Draw(); //The event-invoking method that derived classes can override. protected virtual void OnShapeChanged(ShapeEventArgs e) { // Make a temporary copy of the event to avoid possibility of // a race condition if the last subscriber unsubscribes // immediately after the null check and before the event is raised. EventHandler<ShapeEventArgs> handler = ShapeChanged; if (handler != null) { handler(this, e); } } } public class Circle : Shape { private double radius; public Circle(double d) { radius = d; area = 3.14 * radius * radius; } public void Update(double d) { radius = d; area = 3.14 * radius * radius; OnShapeChanged(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; private double width; public Rectangle(double length, double width) { this.length = length; this.width = width; area = length * width; } public void Update(double length, double width) { this.length = length; this.width = width; area = length * width; OnShapeChanged(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 { List<Shape> _list; public ShapeContainer() { _list = new List<Shape>(); } public void AddShape(Shape s) { _list.Add(s); // Subscribe to the base class event. s.ShapeChanged += HandleShapeChanged; } // ...Other methods to draw, resize, etc. private void HandleShapeChanged(object sender, ShapeEventArgs e) { Shape s = (Shape)sender; // Diagnostic message for demonstration purposes. Console.WriteLine("Received event. Shape area is now {0}", e.NewArea); // Redraw the shape here. s.Draw(); } } class Test { static void Main(string[] args) { //Create the event publishers and subscriber Circle c1 = new Circle(54); Rectangle r1 = new Rectangle(12, 9); ShapeContainer sc = new ShapeContainer(); // Add the shapes to the container. sc.AddShape(c1); sc.AddShape(r1); // Cause some events to be raised. c1.Update(57); r1.Update(7, 7); // Keep the console window open in debug mode. System.Console.WriteLine("Press any key to exit."); System.Console.ReadKey(); } } } /* Output: Received event. Shape area is now 10201.86 Drawing a circle Received event. Shape area is now 49 Drawing a rectangle */