【.NET基础】--委托、事件、线程(2)
本文介绍event的使用以及原理,本文接上一篇文章的Demo继续【下载上一篇Demo】
上一篇我们在类(dg_SayHi.cs)里面定义代理了4个Delegate,然后在Button的后台事件中 新建委托对象并初始化,这样去使用委托。本文我们看一下event的使用以及原理.
1,现在我们在Person类里面 定义一个dg_SayHi委托变量,这样新建person类对象后就可以操作这个委托变量
A,Person类添加委托变量
public class Person
{
#region 姓名
string name; public string Name
{
get { return name; }
set { name = value; }
}
#endregion #region 年龄
int age; public int Age
{
get { return age; }
set { age = value; }
}
#endregion //定义委托变量
public dg_SayHi dgSayHi; }
B,添加按钮btnPerson以及btnPersonDelegate_Click事件,事件中我们使用委托对象
private void btnPersonDelegate_Click(object sender, EventArgs e)
{
Person per = new Person(); //创建委托对象并赋值给person对象的dgSayHi对象
per.dgSayHi = new dg_SayHi(SayHiCN);
per.dgSayHi += SayHiEN; //调用委托对象
per.dgSayHi();
}
C,这样点击按钮的时候,调用SayHiCN和SayHiEN方法,分别先后弹出窗口 “你好上海” 和 “hi shanghai”。
D,由于是直接操作委托对象dgSayHi, 这样就可以直接把添加过方法的委托对象给清空或者重置,我们更新button后台事件如下:
private void btnPersonDelegate_Click(object sender, EventArgs e)
{
Person per = new Person(); //创建委托对象并赋值给person对象的dgSayHi对象
per.dgSayHi = new dg_SayHi(SayHiCN);
per.dgSayHi += SayHiEN; //下面的代码把之前添加在委托里的方法给清空了,然后把委托对象给重置了
per.dgSayHi = null;
per.dgSayHi = new dg_SayHi(SayHiEN); //调用委托对象
per.dgSayHi();
}
E,上面这样,委托对象在运行的过程中就会被不合理清空掉,这样是不安全的。
2,为了对委托对象的操作进行限制,我们把委托对象定义为私有,然后添加像属性一样的操作委托对象的方法
A,更新Person类,把委托变为私有,并添加操作私有变量的方法
public class Person
{
#region 姓名
string name; public string Name
{
get { return name; }
set { name = value; }
}
#endregion #region 年龄
int age; public int Age
{
get { return age; }
set { age = value; }
}
#endregion #region 实现对委托变量的保护
//定义委托变量
private dg_SayHi dgSayHi; public void AddMethod(dg_SayHi Para_dgSayHi)
{
dgSayHi += Para_dgSayHi;
} public void RemoveMethod(dg_SayHi Para_dgSayHi)
{
dgSayHi -= Para_dgSayHi;
} public void PrintMethod()
{
dgSayHi();
}
#endregion
}
B,这样,我们就不能直接操作委托对象了,只有借助类似属性的两个方法去给委托对象添加、移除方法,更新Button事件如下:
private void btnPersonDelegate_Click(object sender, EventArgs e)
{
Person per = new Person(); per.AddMethod(SayHiCN);
per.AddMethod(SayHiEN);
per.PrintMethod();
}
C,上面这样我们无法直接操作委托对象,从而实现了对委托对象的保护。
3,实际上.net的event帮我们做好了像步骤2一样的封装,从而实现对委托对象的保护
A,我们在Person类中再次添加event声明的委托如下:
//定义事件,实现和上面的封装一样的功能
public event dg_SayHi dgSayHiByEvent; public void PrintMethodEvent()
{
dgSayHiByEvent();
}
B,button后台事件中,我们对委托对象的操作也就只能去添加移除方法、而不能去清空或者New,如下:
private void btnPersonDelegate_Click(object sender, EventArgs e)
{
Person per = new Person(); ////创建委托对象并赋值给person对象的dgSayHi对象
//per.dgSayHi = new dg_SayHi(SayHiCN);
//per.dgSayHi += SayHiEN;
////下面的代码把之前添加在委托里的方法给清空了,然后把委托对象给重置了
//per.dgSayHi = null;
//per.dgSayHi = new dg_SayHi(SayHiEN); per.dgSayHiByEvent += SayHiCN; //事件实现了对委托对象的保护,可以+=、-=;但是不能再像上面初始化或者是清空
per.dgSayHiByEvent += SayHiEN; //不可以直接调用委托对象,而是通过对象的方法调用;不可以这样写: per.dgSayHiByEvent();
per.PrintMethodEvent(); }
C,.NET Reflector中我们查看一下,我们加event的委托,实际上是 1,创建了Private dgSayHiByEvent 委托对象 2, event事件中添加了两个方法:add和remove方法;这两个方法去操作Private dgSayHiByEvent委托对象。(和set,get类似)

D,所以event关键字本质就是做了两个事情,从而实现对委托对象的保护:
1,创建了一个对应的Private委托对象
2,然后添加Add和Remove方法访问、操作这个Private委托对象。

4,委托和事件的对比:
A, 委托是类,只定义委托对象的话,没法实现对委托对象的保护,外部可以清空和新建
B, 事件是委托对象,事件自身实现了对委托对象的保护,并提供了供外部访问的两个方法
C,事件只能对add,remove自己,不能赋值。事件只能"注册自己 += " , “注销自己 -= ” 不能=,外界不可以注销其他注册者,外界不可以主动触发事件。
【本文Demo下载】
【.NET基础】--委托、事件、线程(2)的更多相关文章
- c#基础学习笔记-----------委托事件
这里有一个比较简单的委托实例应用(跨窗体操作控件) http://blog.csdn.net/bdstjk/article/details/7004035 还有一个比较详细的介绍并深入理解委托事件的讲 ...
- C# 基础 - 委托、事件
1. 委托 sequenceDiagram 方法->>委托: 返回值和入参一样 委托->>方法: 调用委托就是调用绑定的方法 delegate int NumTest(int ...
- [.net 面向对象编程基础] (22) 事件
[.net 面向对象编程基础] (22) 事件 事件(Event)是学习.net面向对象编程很重要的一部分,在学习事件之前,我们实际上已经在很多地方使用了事件,比如控件的click事件等,这些都是. ...
- C# ~ 从 委托事件 到 观察者模式 - Observer
委托和事件的部分基础知识可参见 C#/.NET 基础学习 之 [委托-事件] 部分: 参考 [1]. 初识事件 到 自定义事件: [2]. 从类型不安全的委托 到 类型安全的事件: [3]. 函数指针 ...
- 谈.Net委托与线程——解决窗体假死
转自:http://www.cnblogs.com/smartls/archive/2011/04/08/2008981.html#2457370 引言 在之前的<创建无阻塞的异步调用> ...
- C#基础知识回顾--线程传参
C#基础知识回顾--线程传参 在不传递参数情况下,一般大家都使用ThreadStart代理来连接执行函数,ThreadStart委托接收的函数不能有参数, 也不能有返回值.如果希望传递参数给执行函数, ...
- SQL Server 扩展事件(Extented Events)从入门到进阶(2)——在GUI中创建基础扩展事件
本文属于 SQL Server 扩展事件(Extented Events)从入门到进阶 系列 第一篇文章中提到了如何在Profiler中创建跟踪(trace),并以服务器端(server-side)跟 ...
- C#基础委托回顾
C#基础委托回顾 前言 快忘记了. 委托的特点 委托类似于 C++ 函数指针,但它们是类型安全的. 委托允许将方法作为参数进行传递. 委托可用于定义回调方法. 委托可以链接在一起:例如,可以对一个事件 ...
- C#基础之事件(2)
在“C#基础之事件(1)”中已对事件有了一个大概,这里对事件进行更深入的学习. 本节按以下内容展开: 1.事件拥有者与事件响应者的关系: 2.事件订阅的多种写法: 3.事件的订阅和取消订阅: 4.多事 ...
- C# 利用委托事件进行窗体间的传值(新手必看)
引言: 窗体间传值是每个学习WinForm新手的常见问题,最初级的方法就是 在窗体中先获取到要接受值窗体.然后通过.得到某个空间或者属性,直接赋值,这个需要接收放的窗体属性或者空间必须是public ...
随机推荐
- IE6/IE7/IE8 FF常见问题解决
(从已经死了一次又一次终于挂掉的百度空间人工抢救出来的,发表日期2014-04-08) <style type="text/css" > *{ margin:0px a ...
- Find n‘th number in a number system with only 3 and 4
这是在看geeksforgeeks时看到的一道题,挺不错的,题目是 Given a number system with only 3 and 4. Find the nth number in th ...
- SCCM符合性设置
符合性设置--可以针对注册表值.脚本.文件系统.补丁更新情况进行符合性检查,除了在报表中查看结果外,还可以在CCM客户端 的 配置 中查看符合性评估结果,适合排错1.配置项目---新建针对 注册表值. ...
- 【M10】在构造方法内阻止资源泄漏
1.类中没有指针,如果对象构造过程中出现异常,C++保证已经构造好的那一部分自动销毁.注意:这里不是调用析构方法,而是编译器在你的构造方法中插入了一些代码,保证对已经构造好的对象析构. 2.类中有指针 ...
- Navicat 导入数据报错 --- 1153 - Got a packet bigger than 'max_allowed_packet' bytes
在用Navicat导入SQL文件时报错:MySql 错误 Err [Imp] 1153 - Got a packet bigger than 'max_allowed_packet' bytes 查了 ...
- Codeforces Round #312 (Div. 2) C. Amr and Chemistry 暴力
C. Amr and Chemistry Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://codeforces.com/contest/558/ ...
- hdu 4828 Grids(拓展欧几里得+卡特兰数)
题目链接:hdu 4828 Grids 题目大意:略. 解题思路:将上一行看成是入栈,下一行看成是出栈,那么执着的方案就是卡特兰数,用递推的方式求解. #include <cstdio> ...
- OS_TASK.C
/*************************************************************************************************** ...
- MyBatis学习练习
转自:http://ccchhhlll1988-163-com.iteye.com/blog/1415621 基本目的:利用Mybatis完成对一个表简单的select.insert.update.d ...
- LinQ—Lambda表达式
概述 本篇博客主要解说lambda表达式,在这里将它的来龙去脉,主要是从托付,匿名函数这些方面过度讲的,当然,在讲托付和匿名函数的时候,主要是从Lambda的角度出发讲的,可能它们还具有其他的一些作用 ...