在c#的学习过程中,学到委托与事件总会迷糊一段时间,迷糊过后自然而就似懂非懂了~,所以最近我打算把以前所学的迷糊过的知识总结,温故知新,总结记录下来。

首先,我们来看一下msdn对委托的定义:

delegate 关键字用于声明可用来封装命名方法的引用类型。委托大致类似于 C++ 中的函数指针;但是,委托是类型安全和可靠的。

delegate 可让您传递一个函数作为参数。委托的类型安全要求作为 delegate 传递的函数具有与 delegate 声明相同的签名。

委托是事件的基础。

我们都知道,c++中的函数是可以通过函数指针来当做参数使用的,c#中没有指针这种东西,怎么办?所以弄出一个delegate出来。

但与函数指针相比,delegate有许多函数指针不具备的优点。 首先,函数指针只能指向静态函数,而delegate既可以引用静态函数,又可以引用非静态成员函数。

在引用非静态成员函数时,delegate不但保存了对此函数入口指针的引用,而且还保存了调用此函数的类实例的引用。 其次,与函数指针相比,delegate是面向对象、类型安全、可靠的受控(managed)对象。

也就是说,runtime能够保证delegate指向一个有效的方法,你无须担心delegate会指向无效地址或者越界地址。

接下来,我们看看c#代码如何声明、实例化、使用一个委托:

private delegate void MyDelegate(string msg);

static void Notify(string name)
{
  Console.WriteLine("Notification received for: {0}", name);
} MyDelegate mydelegate=new MyDelegate(Notify); mydelegate("yoyoyo!");

其中要注意的是:

1、委托不能被定义为static的。

2、返回类型,函数参数一定要和被委托函数一样(继承时)。

3、委托可以链接在一起;例如,可以对一个事件调用多个方法。通过+=,-=操作。


看到这里,我们大致知道“委托”是个什么东西了,但是,相信初学者还有一大堆疑问,委托具体到底是拿来干什么的呢???写程序的时候怎么用它才合适?这些问题也困扰了我许久。

从字面意思看“委托”:把事情托付给别人或别的机构办理,举日常生活中例子:

中午午餐时间,由于工作还没做完,所以叫同事帮带一份午餐,这是一种“委托”。

玩游戏升级太慢,哪有那么多时间升级,果断找人帮代练~又快又舒心~满级之后再把号给我,这也是一种“委托”。

总之,就是在你忙的时候叫其他人帮你做事,这让我们想到了什么?-----异步编程!,例如在做一些耗时操作时,在不影响主线程情况下异步,特别是UI线程,声明一个委托然后BeginInvoke,帮我做事吧~在大多数情况下,就是用来在异步编程中充当“跑腿的”。

在这里我们就不讨论异步编程,也不涉及异步编程,否则就扯远了,下面就让我们通过实例体会delegate的基本作用吧。

有这么一个场景:

早恋是许多家长关心的问题啊,最近家长A貌似发现自己的孩子LiLei对家长B的孩子HanMeiMei有意思,同时家长B也发现了,为了确认情况,双方父母私下委托老师发现真实情况的时候通知一声,提早纠正学生的观念~。

简单代码模拟场景:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks; namespace Delegate
{
class Program
{
static void Main(string[] args)
{
//家长A,B,他们不可能一天去学校监视孩子吧?委托给老师咯,自己还要去上班呢
Parent pa = new Parent();
Parent pb = new Parent(); //家长A,B分别委托老师发现早恋情况时通知他们
Teacher teacher = new Teacher();
teacher.NotifyStudentLove = pa.ReceiveMsg;
teacher.NotifyStudentLove += pb.ReceiveMsg; //老师开始检查早恋情况
teacher.CheckLove(); }
}
}

老师类:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks; namespace Delegate
{
public class Teacher
{
//声明一个委托类型,通知家长
public delegate void NotifyDelegate(string msg); //老师被吩咐了1个委托
//声明委托:在发现早恋时时通知家长
private NotifyDelegate NotifyStudentLove; //如果还想委托老师发现学生玩手机的时候通知一声,再声明一个委托即可
private NotifyDelegate NotifyStudentPlayMobile; //封装委托,使其符合面向对象
public void add_NotifyStudentLove(NotifyDelegate newdelegate)
{
NotifyStudentLove += newdelegate;
} public void CheckLove()
{
//某一天AB同学突然发生纠纷!被老师发现啦!
string msg = "A同学和B同学早恋啦!!";
//检查是否有人委托老师办事
if (NotifyStudentLove != null)
{
//果断通知家长
NotifyStudentLove(msg);
}
}
}
}

家长类:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks; namespace Delegate
{
public class Parent
{
/// <summary>
/// 接收消息
/// </summary>
/// <param name="msg">通知消息</param>
public void ReceiveMsg(string msg)
{
Console.WriteLine("家长收到通知:" + msg);
}
}
}

运行结果:

家长收到通知:A同学和B同学早恋啦!!
家长收到通知:A同学和B同学早恋啦!!


看完上面的代码场景可知相信对delegate有了更深入的理解,就是“帮我办事”,同时是不是还隐约感觉到了观察者模式

没错,如果仅仅只用delegate是可以实现观察者模式的,但是,就面向对象而言,对外部对象赋予了delegate太多的方法,又是实例化new,又是+=,-=,甚至你还可以=null。

对于观察者模式来说,观察者不能也不应该有权限实例化事件发布者的消息列表,同时观察者也不应该能控制事件发布者对事件的通知,这些所有的操作应该都是发布者内部的事件而不能交由外部对象来控制

上面的模拟场景,可以在场景内随意调用teacher.NotifyStudentLove();但是原则上应该是只能在teacher.CheckLove()函数内部才调用的。

有些同学就想了,那我们再封装一次NotifyStudentLove委托不就行了?例如:

private NotifyDelegate NotifyStudentLove;
public void add_NotifyStudentLove(NotifyDelegate newdelegate)
{
  NotifyStudentLove += newdelegate;
}

没错,我们确实可以这样做~这也是关键字event替我们做的事情。

添加了event关键字之后,.net会通过一系列方法将这个delegate包裹起来从而封装了一部分本来就不应该暴露的行为,就像语法糖{get;set;}一样。

此时,“委托”摇身一变成了“事件”~!但是别以为你穿上马甲我就不认识你了。

下篇将会讲述【温故知新】c#事件event,欢迎拍砖。

【温故知新】C#委托delegate的更多相关文章

  1. [.NET] C# 知识回顾 - 委托 delegate (续)

    C# 知识回顾 - 委托 delegate (续) [博主]反骨仔 [原文]http://www.cnblogs.com/liqingwen/p/6046171.html 序 上篇<C# 知识回 ...

  2. [C#] C# 知识回顾 - 委托 delegate

    C# 知识回顾 - 委托 delegate [博主]反骨仔 [原文]http://www.cnblogs.com/liqingwen/p/6031892.html 目录 What's 委托 委托的属性 ...

  3. C# 委托Delegate(一) 基础介绍&用法

    本文是根据书本&网络 前人总结的. 1. 前言 定义&介绍: 委托Delegate是一个类,定义了方法的类型, 使得可以将方法当做另一个方法的参数来进行传递,这种将方法动态地赋给参数的 ...

  4. 为什么不能把委托(delegate)放在一个接口(interface)当中?

    stackoverflow上有人问,为什么不能把委托放在一个接口当中? 投票最多的第一个答案第一句话说,“A Delegate is just another type, so you don't g ...

  5. C# 代理/委托 Delegate

    本文转载自努力,努力,努力 1. 委托的定义:委托是函数的封装,它代表一"类"函数.他们都符合一定的签名:拥有相同的参数列表,返回值类型.同时,委托也可以看成是对函数的抽象,是函数 ...

  6. c# 委托 delegate

    委托是一种存储函数引用的类型,在事件和事件的处理时有重要的用途 通俗的说,委托是一个可以引用方法的类型,当创建一个委托,也就创建一个引用方法的变量,进而就可以调用那个方法,即委托可以调用它所指的方法. ...

  7. 理解委托(delegate)及为什么要使用委托

    理解委托(delegate)及为什么要使用委托 委托:是一种定义方法签名的类型. 当实例化委托时,您可以将其实例与任何具有兼容签名的方法相关联. 您可以通过委托实例调用方法. 上述为官方说法,理解起来 ...

  8. 深入理解委托(Delegate)

    前言 委托其实一直以来都感觉自己应该挺熟悉的,直到最近又去翻了翻 CLR via C#,感觉我之前的理解可能还有失偏颇.在这记录一下. 之前文章的链接: 接口和委托的泛型可变性 C#高级编程笔记 De ...

  9. C# -- 使用委托 delegate 执行异步操作

    C# -- 使用委托 delegate 执行异步操作 委托是一种安全地封装方法的类型,它与 C 和 C++ 中的函数指针类似. 与 C 中的函数指针不同,委托是面向对象的.类型安全的和保险的. 委托的 ...

  10. 委托delegate

    委托delegate没有函数体.委托可以指向函数(要与指向的函数格式.类型相一致) namespace demo { public delegate double MyDelegate(double ...

随机推荐

  1. JavaScript之substring()方法讲解

    定义和用法 substring() 方法用于提取字符串中介于两个指定下标之间的字符. 语法 stringObject.substring(start,stop) 参数 描述 start 必需.一个非负 ...

  2. 在centos 6.5 在virtual box 上 安装增强版工具

    centos 6.5 在virtual box 上 安装增强版工具: 出现:centos unable to find the source of your current linux kernel ...

  3. Apache CXF实现Web Service(4)——Tomcat容器和Spring实现JAX-RS(RESTful) web service

    准备 我们仍然使用 Apache CXF实现Web Service(2)——不借助重量级Web容器和Spring实现一个纯的JAX-RS(RESTful) web service 中的代码作为基础,并 ...

  4. IT架构之IT架构模型——思维导图

    参考: [日] 野村综合研究所系统咨询事业本部. 图解CIO工作指南. 周自恒译 人民邮电出版社,2014

  5. Sqli-labs less 51

    Less-51 本关的sql语句为    $sql="SELECT * FROM users ORDER BY '$id'"; 我们此处要进行stacked injection,要 ...

  6. APM终端用户体验监控分析(下)

    一.前言 [APM 终端用户体验监控分析(上)][1]从 APM 终端用户产品特性.使用建议.以及从[真实用户体验][2]和[模拟性能监控][3]两方面入手给大家进行了简单的分享. 本文为下篇,将给大 ...

  7. Using an Interface as a Type

    When you define a new interface, you are defining a new reference data type. You can use interface n ...

  8. HDU 1828 / POJ 1177 Picture (线段树扫描线,求矩阵并的周长,经典题)

    做这道题之前,建议先做POJ 1151  Atlantis,经典的扫描线求矩阵的面积并 参考连接: http://www.cnblogs.com/scau20110726/archive/2013/0 ...

  9. Services学习(一)

    对于需要长期运行,例如播放音乐.长期和服务器的连接,即使已不是屏幕当前的activity仍需要运行的情况,采用服务方式.服务将通过API触发启动或者通过IPC(Interprocess Communi ...

  10. 如何在Windows7(IIS7)环境下安装 PHP

    一.安装IIS7 打开(1)[程序和功能],然后点击(2)[打开或关闭Windows功能] 勾选(1)[IIS管理控制台]和(2)CGI,然后点击[确定]按钮,等待安装完成.这个过程可能需要系统安装光 ...