.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# 标准事件模式的更多相关文章

  1. W3C对DOM2.0定义的标准事件

    DOM2.0模型将事件处理流程分为三个阶段: 一.事件捕获阶段, 二.事件目标阶段, 三.事件起泡阶段. 具体如图(图片来源于网络,侵删) 事件捕获:当某个元素触发某个事件(如onclick),顶层对 ...

  2. C#代码:用事件模式实现通知

    事件提供了一种标准的机制来通知监听者..NET的事件模式使用了事件语法来实现观察者模式.任意数量的客户对象都可以将自己的处理函数注册到事件上,然后处理这些事件.这些客户对象不需要再编译期就给出.时间也 ...

  3. 【转载】详细解读C#中的 .NET 弱事件模式

    你可能知道,事件处理是内存泄漏的一个常见来源,它由不再使用的对象存留产生,你也许认为它们应该已经被回收了,但不是,并有充分的理由. 在这个短文中(期望如此),我会在 .Net 框架的上下文事件处理中展 ...

  4. C#中的 .NET 弱事件模式

    引言 你可能知道,事件处理是内存泄漏的一个常见来源,它由不再使用的对象存留产生,你也许认为它们应该已经被回收了,但不是,并有充分的理由. 在这个短文中(期望如此),我会在 .Net 框架的上下文事件处 ...

  5. 标准IDispose模式浅析

    DoNet资源 众所周知,.Net内存管理分托管资源和非托管资源,把内存中的对象按照这两种资源划分,然后由GC负责回收托管资源(Managed Resource),而对于非托管资源来讲,就需要程序员手 ...

  6. CUDA 标准编程模式

    前言 本文将介绍 CUDA 编程的基本模式,所有 CUDA 程序都基于此模式编写,即使是调用库,库的底层也是这个模式实现的. 模式描述 1. 定义需要在 device 端执行的核函数.( 函数声明前加 ...

  7. 如何给ActiveX控件添加“事件”“属性”“标准事件”“自定义事件”等一些相关操作

    上一篇小编带大家熟悉了一下ActiveX的建立以及相关的概念,(http://blog.csdn.net/u014028070/article/details/38424611) 本文介绍下如何给控件 ...

  8. C#的内存管理原理解析+标准Dispose模式的实现

    本文内容是本人参考多本经典C#书籍和一些前辈的博文做的总结 尽管.NET运行库负责处理大部分内存管理工作,但C#程序员仍然必须理解内存管理的工作原理,了解如何高效地处理非托管的资源,才能在非常注重性能 ...

  9. [转]改善C#程序的建议4:C#中标准Dispose模式的实现

    需要明确一下C#程序(或者说.NET)中的资源.简单的说来,C#中的每一个类型都代表一种资源,而资源又分为两类: 托管资源:由CLR管理分配和释放的资源,即由CLR里new出来的对象: 非托管资源:不 ...

随机推荐

  1. keras—多层感知器MLP—MNIST手写数字识别

    一.手写数字识别 现在就来说说如何使用神经网络实现手写数字识别. 在这里我使用mind manager工具绘制了要实现手写数字识别需要的模块以及模块的功能:  其中隐含层节点数量(即神经细胞数量)计算 ...

  2. C++ volatile

    volatile的位置与const相同——都是作为类型的附加修饰符 使用volatile的主要目的是提示编译器该对象的值可能在编辑器未监测的情况下被改变,因此编译器不能武断地对引用这些对象的代码作优化 ...

  3. hover

    hover - Bing dictionary US[ˈhɒvə(r)] v.盘旋:徘徊:犹豫:巡弋 网络翱翔:悬停:盘旋于

  4. Python错误:close failed in file object destructor

    我遇到的情况: 二进制程序调shell再调Python后,shell退出,Python进程挂到init上(不是僵尸进程),但 此时二进制程序未退出,这时候中断而二进制程序出现此提示. 经查询: 应该是 ...

  5. [udemy]WebDevelopment_How the Internet Works

    Browsing the web Enter google.com, who is this google.com This question gets asked all the way down ...

  6. 提交代码到远程GIT仓库,代码自动同步到远程服务器上。

    现在一般都会通过github,gitlab,gitee来管理我们的代码.我们希望只要我本地push了代码,远程服务器能自动拉取git仓库的代码,进行同步. 这就需要用到各仓库为我们提供的webhook ...

  7. pip安装python模块方法

    网上搜索了很多,主流的配置方法分为两种: 摘自 1.http://www.jb51.net/article/83617.htm 安装pip的包并确定pip安装时的镜像源地址,国内常用的地址有: htt ...

  8. ubuntu查找命令比较

    1. find find是最常见和最强大的查找命令,你可以用它找到任何你想找的文件.    find的使用格式如下:     $ find <指定目录> <指定条件> < ...

  9. QFileInfo

    https://www.cnblogs.com/findumars/p/10247573.html

  10. 深入浅出 JMS(一) - JMS 基本概念

    深入浅出 JMS(一) - JMS 基本概念 一.JMS 是个什么鬼 JMS 是 Java Message Service 的简称,即 Java 消息服务.什么是消息服务呢,我们来看一下 Oracle ...