1、 在创建基类时,若涉及到事件,事件是特殊类型的委托,只可以从声明它们的类中调用,派生类无法直接调用基类中声明的事件,但是在多数情况,会需要允许派生类调用基类事件,这时,可以再包含该事件的基类中创建一个受保护的虚调用方法,通过调用或重写此调用方法,派生类便可以间接调用该事件。
注:不要在基类中声明虚拟事件,也不要在派生类中重写这些事件,C#编译器无法正确处理这些事件,并且无法预知该派生的事件的用户是否真正订阅了基类事件。
和下面的程序示例都来自:https://msdn.microsoft.com/zh-cn/library/hy3sefw3.aspx
2、 插入知识点:virtual和abstract的区别:
virtual和abstract都是用来修饰父类的,通过覆盖父类的定义,让子类重新定义(子类方法前都必须添加override),因此虚拟方法和抽象方法都不能是私有的;
virtual修饰的方法必须有实现(哪怕是仅仅添加一对大括号),而abstract修饰的方法一定不能实现;
virtual可以被子类重写,而abstract必须被子类重写;
如果类成员被abstract修饰,则该类前必须添加abstract,因为只有抽象类才可以有抽象方法;
无法创建abstract类的实例;
3、示例程序
1 namespace Test0301 2 { 3 class Program 4 { 5 static void Main(string[] args) 6 { 7 Circle c1 = new Circle(7); 8 Rectangle r1 = new Rectangle(12, 9); 9 ShapeContainer sc = new ShapeContainer(); 10 11 sc.AddShape(c1); 12 sc.AddShape(r1); 13 14 c1.Update(1); 15 r1.Update(7, 7); 16 17 Console.WriteLine("Press any key to ecit..."); 18 Console.ReadKey(); 19 } 20 } 21 22 public class ShapeEventArgs : EventArgs 23 { 24 private double newArea; 25 26 public ShapeEventArgs(double d) 27 { 28 newArea = d; 29 } 30 31 public double NewArea 32 { 33 get { return newArea; } 34 } 35 } 36 37 public abstract class Shape 38 { 39 protected double area; 40 41 public double Area 42 { 43 get { return area; } 44 set { area = value; } 45 } 46 47 public event EventHandler<ShapeEventArgs> ShapeChanged; 48 49 public abstract void Draw();//abstract和类定义的abstract对应,在派生类中必须实现 50 51 //基类可以重载此函数,实现实际对象类型的此函数 52 //此函数为事件句柄的实现函数 53 protected virtual void OnShapeChanged(ShapeEventArgs e) 54 { 55 Console.WriteLine("基类事件处理函数被{0}调用", this.ToString()); 56 57 EventHandler<ShapeEventArgs> handler = ShapeChanged; 58 if (handler != null) 59 { 60 handler(this, e); //this为调用此函数的派生类对象 61 } 62 } 63 } 64 65 public class Circle : Shape 66 { 67 private double radius; 68 69 public Circle(double d) 70 { 71 radius = d; 72 area = 3.14 * radius * radius; 73 } 74 75 public void Update(double d) 76 { 77 radius = d; 78 area = 3.14 * radius * radius; 79 OnShapeChanged(new ShapeEventArgs(area)); 80 } 81 82 protected override void OnShapeChanged(ShapeEventArgs e) 83 { 84 //具体类的处理 85 Console.WriteLine("Circle's radius changed!"); 86 87 //调用基类的函数 88 base.OnShapeChanged(e); 89 } 90 91 public override void Draw() 92 { 93 Console.WriteLine("Drawing a circle"); 94 Console.WriteLine(); 95 } 96 } 97 98 public class Rectangle : Shape 99 { 100 private double length; 101 private double width; 102 103 public Rectangle(double length,double width) 104 { 105 this.length = length; 106 this.width = width; 107 area = length * width; 108 } 109 110 public void Update(double length, double width) 111 { 112 this.length = length; 113 this.width = width; 114 area = length * width; 115 OnShapeChanged(new ShapeEventArgs(area)); 116 } 117 118 protected override void OnShapeChanged(ShapeEventArgs e) 119 { 120 Console.WriteLine("Rectangle's radius changed!"); 121 base.OnShapeChanged(e); 122 } 123 124 public override void Draw() 125 { 126 Console.WriteLine("Drawing a rectangle!"); 127 Console.WriteLine(); 128 } 129 } 130 131 public class ShapeContainer 132 { 133 List<Shape> _list; 134 135 public ShapeContainer() 136 { 137 _list = new List<Shape>(); 138 } 139 140 public void AddShape(Shape s) 141 { 142 _list.Add(s); 143 //订阅基类事件 144 s.ShapeChanged += HandleShapeChanged; 145 } 146 147 private void HandleShapeChanged(object sender, ShapeEventArgs e) 148 { 149 Shape s = (Shape)sender; 150 151 Console.WriteLine("Receicved event,Shape area is now {0}", e.NewArea); 152 153 s.Draw(); 154 } 155 } 156 }