C# 标准事件模式
.NET框架为事件定义了一个标准模式,它的目的是保持框架和用户代码之间的一致性。
标准事件的模式核心是SystemEventArgs——预定义的没有成员的框架类(不同于静态Empty属性)
EventArgs表示包含事件数据的类的基类,并提供用于不包含事件数据的事件的值。用于为事件传递信息的基类。
在下面例子中,我们定义EventArgs的子类,用于事件PriceChanged被引发时,传递新旧Price值:
public class PriceChangedEventArgs : EventArgs
{
public readonly decimal LastPrice;
public readonly decimal NewPrice; public PriceChangedEventArgs(decimal lastPrice, decimal newPrice)
{
LastPrice=lastPrice;
NewPrice= newPrice;
}
}
考虑到复用性,EventArgs子类根据它包含的内容命名(而非根据将被使用的事件命名)。
选择或定义事件的委托,需遵循三条原则:
- 委托必须以void作为返回值
- 委托必须接受两个参数:第一个是object类,第二个是EventArgs的子类。
- 委托的名称必须以EventHandler结尾
完整例子:
class Test
public static void Main()
{
InitializeComponent();
Stock stock = new Stock("THPW");
stock.Price = 27.10M;
//注册PriceChanged事件
stock.PriceChanged += stock_PriceChanged;
stock.Price = 31.59M;
} static void stock_PriceChanged(object sender, PriceChangedEventArgs e)
{
if ((e.NewPrice - e.LastPrice) / e.LastPrice > 0.1M)
{
Console.WriteLine("Alert,10% stock increase!");
}
}
} public class Stock
{
string symbol;
decimal price; public Stock(string symbol)
{
this.symbol = symbol;
}
//定义委托事件
public event EventHandler<PriceChangedEventArgs> PriceChanged;
protected virtual void OnPriceChanged(PriceChangedEventArgs e)
{
if (PriceChanged != null) PriceChanged(this, e);
} public decimal Price
{
get { return price; }
set
{
if (price == value) return;
price = value;
OnPriceChanged(new PriceChangedEventArgs(price, value));
}
}
}
public class PriceChangedEventArgs : EventArgs
{
public readonly decimal LastPrice;
public readonly decimal NewPrice;
public PriceChangedEventArgs(decimal lastPrice, decimal newPrice)
{
LastPrice=lastPrice;
NewPrice= newPrice;
}
}
如果事件不传递额外的信息,可以使用预定义的非泛化委托EventHandler。如下所示:
class Test
{
public static void Main()
{
InitializeComponent();
Stock stock = new Stock();
stock.Price = 27.10M;
//注册PriceChanged事件
stock.PriceChanged += stock_PriceChanged;
stock.Price = 31.59M;
} static void stock_PriceChanged(object sender, EventArgs e)
{
Console.WriteLine("价格变换了!");
}
} public class Stock
{
decimal price; public event EventHandler PriceChanged; protected virtual void OnPriceChanged(EventArgs e)
{
if (PriceChanged != null) PriceChanged(this, e);
} public decimal Price
{
get { return price; }
set
{
if (price == value) return;
price = value; //OnPriceChanged(new EventArgs()); OnPriceChanged(EventArgs.Empty);
}
}
}
注意:
上面例子中事件除了传递已发生信息,没有传递其他信息。
你可以使用 OnPriceChanged(new EventArgs()) 来完成事件的传递。
为了避免对EventArgs不必要的初始化,建议使用EventArgs.Empty属性。使用这样一个“空的”静态引用的对象,避免多余地去创建一个新对象。
微软的大部分控件所抛出的事件都有两个参数,第一个是 object 类型的,第二个是 EventArgs 类型的。

你从EventArgs e那里得不到任何此次事件相关需要传递的信息,真正传递的信息都在sender中。
C# 标准事件模式的更多相关文章
- W3C对DOM2.0定义的标准事件
DOM2.0模型将事件处理流程分为三个阶段: 一.事件捕获阶段, 二.事件目标阶段, 三.事件起泡阶段. 具体如图(图片来源于网络,侵删) 事件捕获:当某个元素触发某个事件(如onclick),顶层对 ...
- C#代码:用事件模式实现通知
事件提供了一种标准的机制来通知监听者..NET的事件模式使用了事件语法来实现观察者模式.任意数量的客户对象都可以将自己的处理函数注册到事件上,然后处理这些事件.这些客户对象不需要再编译期就给出.时间也 ...
- 【转载】详细解读C#中的 .NET 弱事件模式
你可能知道,事件处理是内存泄漏的一个常见来源,它由不再使用的对象存留产生,你也许认为它们应该已经被回收了,但不是,并有充分的理由. 在这个短文中(期望如此),我会在 .Net 框架的上下文事件处理中展 ...
- C#中的 .NET 弱事件模式
引言 你可能知道,事件处理是内存泄漏的一个常见来源,它由不再使用的对象存留产生,你也许认为它们应该已经被回收了,但不是,并有充分的理由. 在这个短文中(期望如此),我会在 .Net 框架的上下文事件处 ...
- 标准IDispose模式浅析
DoNet资源 众所周知,.Net内存管理分托管资源和非托管资源,把内存中的对象按照这两种资源划分,然后由GC负责回收托管资源(Managed Resource),而对于非托管资源来讲,就需要程序员手 ...
- CUDA 标准编程模式
前言 本文将介绍 CUDA 编程的基本模式,所有 CUDA 程序都基于此模式编写,即使是调用库,库的底层也是这个模式实现的. 模式描述 1. 定义需要在 device 端执行的核函数.( 函数声明前加 ...
- 如何给ActiveX控件添加“事件”“属性”“标准事件”“自定义事件”等一些相关操作
上一篇小编带大家熟悉了一下ActiveX的建立以及相关的概念,(http://blog.csdn.net/u014028070/article/details/38424611) 本文介绍下如何给控件 ...
- C#的内存管理原理解析+标准Dispose模式的实现
本文内容是本人参考多本经典C#书籍和一些前辈的博文做的总结 尽管.NET运行库负责处理大部分内存管理工作,但C#程序员仍然必须理解内存管理的工作原理,了解如何高效地处理非托管的资源,才能在非常注重性能 ...
- [转]改善C#程序的建议4:C#中标准Dispose模式的实现
需要明确一下C#程序(或者说.NET)中的资源.简单的说来,C#中的每一个类型都代表一种资源,而资源又分为两类: 托管资源:由CLR管理分配和释放的资源,即由CLR里new出来的对象: 非托管资源:不 ...
随机推荐
- [leetcode]496. Next Greater Element I下一个较大元素
You are given two arrays (without duplicates) nums1 and nums2 where nums1’s elements are subset of n ...
- phpcms与discuz的ucenter整合
1.安装phpcms系统,域名为pc.me 2.安装discuz,并选择安上uc_server,域名为dz.me 3.在phpcms下phpsso的系统设置 4.到ucenter管理中心- ...
- dddddddddddddddddd
PacificA: Replication in log-based distributed storage systemshttp://research.microsoft.com:8082/pub ...
- 相机拍摄时最重要的三个参数——光圈、快门、ISO
注:这篇文章我四年前发布在其他地方,现在移过来. 如果你对相机只有很少了解,那么看这篇文章再好不过啦,我结合很多资料,力图用最通俗易懂的方式进行讲解. 相机拍摄时最重要的3个参数就是——光圈.快门.I ...
- Halcon中数据的四舍五入、取整、有效数字以及和字符串之间的转换
*此代码可直接复制到HDevelop中运行 a:= 3.456 *取整.取最近的整数 int_a := int(a) //取整数部分,结果是3 round_a := round(a) //将输入元组转 ...
- Xcode.Subproject.And.Framework
1. Easy Xcode Static Library Subprojects and Submodules http://www.blog.montgomerie.net/easy-xcode-s ...
- 一名优秀的UI设计师应该具备哪些条件?
想做好一个好的UI设计师除了应该具有一定的审美能力,还要了解整个产品的开发过程,因为目前国内的软件行业还不能对UI设计形成应有的重视度,所以对我们的要求就更高了,你要能作出夺人眼球的东西,还要站在用户 ...
- linux 常用压缩打包和解压命令
## zcvf gzip jcvf bzip2 gunzip tar zxvf jxvf
- 20155335俞昆《java程序设计》第七周总结
学号 2016-2017-2 <Java程序设计>第X周学习总结 ## 教材学习内容总结 Lambda 的语法概览 String[] names={“Justin”,”cater ...
- 类内初始值(c++11)
1.概念 1)可以为数据成员提供一个类内初始值,创建对象时,类内初始值用于初始化数据成员,没有初始值的成员将被默认初始化 2)类内初始值和赋值类似,或者放在花括号里(如数组),或者放在等号右边,不能使 ...