An event can be raised only from the declaration space in which it is declared. Therefore, a class cannot raise events from any other class, even one from which it is derived.

事件只能在它被声明的声明空间(类)中使用。所以不能从任何其他类引发,即使该类是事件所在类的继承类。

那我们如何才可以引发基类中的事件,给个实例大家一看就明白了。

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
*/

 

参考

How to: Raise Base Class Events in Derived Classes (C# Programming Guide)

C#基础-事件 继承类无法直接引发基类的事件的更多相关文章

  1. WPF 之 创建继承自Window 基类的自定义窗口基类

    开发项目时,按照美工的设计其外边框(包括最大化,最小化,关闭等按钮)自然不同于 Window 自身的,但窗口的外边框及窗口移动.最小化等标题栏操作基本都是一样的.所以通过查看资料,可按如下方法创建继承 ...

  2. C++ 虚继承实现原理(虚基类表指针与虚基类表)

    虚继承和虚函数是完全无相关的两个概念. 虚继承是解决C++多重继承问题的一种手段,从不同途径继承来的同一基类,会在子类中存在多份拷贝.这将存在两个问题:其一,浪费存储空间:第二,存在二义性问题,通常可 ...

  3. 类转json的基类实现

    类转json的基类实现 项目地址 github地址 实现原理 使用反射获取类的属性名和属性内容.具体原理可以自己查一下资料 对一个类调用getClass().getDeclaredFields()可以 ...

  4. 编写高质量代码改善C#程序的157个建议——建议128:考虑让派生类的名字以基类名字作为后缀

    建议128:考虑让派生类的名字以基类名字作为后缀 派生类的名字可以考虑以基类名字作为后缀.这带来的好处是,从类型的名字上我们就知道它包含在哪一个继承体系中. Exception及其子类就是这样一个典型 ...

  5. C++派生类中如何初始化基类对象(五段代码)

    今天收到盛大的面试,问我一个问题,关于派生类中如何初始化基类对象,我在想派生类对于构造函数不都是先构造基类对象,然后在构造子类对象,但是如果我们在成员初始化列表先初始化派生类的私有成员,在函数内去调用 ...

  6. c++,派生类对象可以对基类赋值,基类对派生类不可以赋值

    派生类对象可以对基类对象赋值,赋值时属于派生类独有的部分就舍弃不用. #include <iostream> using namespace std; class DemoA { publ ...

  7. C++类继承--构造函数时先构造基类

    以下说明继承类函数构造时,先构造基类: 析构基类时,若没加上virtual,只析构基类,不析构派生类: 析构派生类时,同时会析构基类: 1. 基类析构函数有virtual #include <s ...

  8. C#继承机制 访问与隐藏基类成员

    (1) 访问基类成员 通过base 关键字访问基类的成员:   调用基类上已被其他方法重写的方法.  指定创建派生类实例时应调用的基类构造函数.  基类访问只能在构造函数.实例方法或实例属性访问器中进 ...

  9. C++primer原书中的一个错误(派生类using声明对基类权限的影响)

    在C++primer 第4版的 15章 15.2.5中有以下这样一段提示: "注解:派生类能够恢复继承成员的訪问级别,但不能使訪问级别比基类中原来指定的更严格或者更宽松." 在vs ...

随机推荐

  1. 多说使用ua-parser-js显示浏览器和系统信息

    前言 昨天博客接入了评论系统,使用的是国内的多说. 之前看到过有些利用该评论系统的有浏览器和系统信息的显示,感觉很不错. 所以,也想有这样的效果. 问题 多说如何显示浏览器和系统的信息? 解决方法 经 ...

  2. C#~异步编程再续~await与async引起的w3wp.exe崩溃

    返回目录 最近怪事又开始发生了,IIS的应用程序池无做挂掉,都指向同一个矛头,async,threadPool,Task,还有一个System.NullReferenceException,所以这些都 ...

  3. Mybatis中javaType和jdbcType对应关系

    JDBC Type           Java Type CHAR                  String VARCHAR            String LONGVARCHAR    ...

  4. Professional JavaScript for Web Developers 3rd Edition ---读书笔记

    1. DOMContentLoaded DOM树构建完成时触发该事件 load 页面加载完毕触发 原生js document.addEventListener('DOMContentLoaded', ...

  5. discuz 3.x 核心文件class_core.php解析

    class_core.php是discuz 3.x的核心文件,几乎所有PHP脚本都有引用此文件初始化论坛运行环境.以下解析引用3.2版discuz. line 12-15:常量定义IN_DISCUZ: ...

  6. 基于mybatis-generator-core 1.3.5项目的修订版以及源码剖析

    项目简单说明 mybatis-generator,是根据数据库表.字段反向生成实体类等代码文件.我在国庆时候,没事剖析了mybatis-generator-core源码,写了相当详细的中文注释,可以去 ...

  7. 提交留言HTML模板代码

    <!DOCTYPE html> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <t ...

  8. webpack初入

    序言:前面已经倒腾了grunt.gulp.fis3,今天来通过一个例子玩玩webpack!最终预览 通过下面的例子,能够了解以下几点: 1.如何安装webpack 2.如何使用webpack 3.如何 ...

  9. 软件开发流程 Software development process

    软件开发流程(Software development process)即软件设计思路和方法的一般过程,包括设计软件的功能和实现的算法和方法.软件的总体结构设计和模块设计.编程和调试.程序联调和测试以 ...

  10. jQuery siteslider 动画幻灯片

    在线实例 效果一 效果二 使用方法 <div class="container demo-1">             <div id="slider ...