在创建可用作其他类的基类的类时,应考虑如下事实:事件是特殊类型的委托,只可以从声明它们的类中调用。派生类无法直接调用基类中声明的事件。尽管有时需要事件仅由基类引发,但在大多数情形下,应该允许派生类调用基类事件。(注:之所以可以在父类引发,是因为运行时状态下父类只是指向子类的指针,这样即使给事件传递参数this,也是子类而不是父类)为此,您可以在包含该事件的基类中创建一个受保护的调用方法。通过调用或重写此调用方法,派生类便可以间接调用该事件。 关键:1、基类中定义事件、并且定义虚方法触发事件,例子中OnShapeChanged() 2、子类可以通过调用或重写OnShapeChanged间接触发基类事件。 namespace ConsoleApplication1{ class Program { static void Main(string[] args) { Circle c1 = new Circle(); ShapeContainer sc = new ShapeContainer(); // Add the shapes to the container. sc.AddShape(c1); // Cause some events to be raised. c1.Update(57); } } public abstract class Shape { // 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;
// 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. protected virtual void OnShapeChanged(ShapeEventArgs e) { EventHandler<ShapeEventArgs> handle = ShapeChanged; if (handle != null) { handle(this, e); } } public abstract void Draw(); } public class Circle : Shape { public override void Draw() { // throw new NotImplementedException(); } protected override void OnShapeChanged(ShapeEventArgs e) { // Call the base class event invocation method. base.OnShapeChanged(e); } public void Update(double d) { OnShapeChanged(new ShapeEventArgs(100)); } } 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(); } } public class ShapeEventArgs : EventArgs { private double newArea; public ShapeEventArgs(double d) { newArea = d; } public double NewArea { get { return newArea; } } }} |
|