C#里的委托相当于C#的函数接口对象(C语言可称为函数指针,C++可称为函数对象),是C#的一个比较重要的特性。

而观察者模式是一种常见的设计模式,在C#里往往使用委托等相关语法搭配来实现观察者模式。

因此很需要搞懂 delegate(委托),event(事件),Action/Func的语法及区别。

此外观察者模式的原理很易懂,不作多讲,本文纯粹用于记录C#委托/时间/Lambda表达式语法。

delegate(委托)

//声明没有参数,没有返回值的委托类型XXXX
public delegate void XXXX();

声明一个委托类型(类似typedef XXXX C++/C的函数类型)

注:不是产生一个对象。

然后利用声明出来的委托类型,我们可以利用它的对象,赋予其对应类型的函数。

从而实现出类似调用函数指针的效果。

//委托类型XXXX的对象
public XXXX delegateObj1; public void func1(){}
public void func2(){}
public void func3(int a){}
//可将某个同样类型的函数赋给该对象
delegateObj1 = func1; //调用委托对象等同于调用它代表的函数
delegateObj1();//等价于func1(); delegateObj1 = func2;
delegateObj1();//等价于func2(); delegateObj1 = func3;//类型不匹配,语法错误

event(事件)

单纯用委托的话只能一对一调用(一次调用,一个函数触发)。

而通过利用事件机制,我们可以实现一对多的调用(一次调用,多个相关事件(函数)触发)。

而且它添加/移除委托对象(相当于观察者模式里的观察者)的操作十分方便,使用+=或-=即可。

//先声明一个委托类型
public delegate void XXXX();
//委托事件对象
public event XXXX EventObj1;//此处比一般委托多了个event
EventObj1 += func1; //添加
EventObj1 += func2; //添加 EventObj1(); //调用func1(),func2() EventObj1 -= func1; //移除
EventObj1(); //调用func2()

Action/Func

Action/Func主要是为了简化委托(delegate)语法,它们本质都是委托。

//无返还值,不带参数的委托对象
public delegate void XXXX();
public XXXX obj1;

在上面我们看到委托语法,必须为委托类型命名(声明委托),才能使用该委托类型。

但是使用Action/Func可以无需声明委托类型的语句,直接利用Action<...>/Func<...>来用自己想要的委托类型。

Action和Func的源码底层实际也是delegate的封装

  • Action<...>用于无返还值的委托类型
  • Func<...,T>用于有返回值的委托类型,最后一个类型参数 T 代表返还值类型。
//无返还值,不带参数的委托对象
public Action obj3;
//无返还值,带int参数的委托对象
public Action<int> obj4; //double返还值,无参数的委托对象
public Func<double> obj5;
//int返还值,带string,double参数的委托对象
public Func<string,double,int> obj6; //将Action应用至事件
public event Action<int> EventObj1;
EventObj1 += obj4;
EventObj1 += func1;
EventObj1 += func2;
EventObj1();//调用obj4(),func1(),func2()

Lambda表达式

Lambda表达式是用于简便快速写简单函数的语法,而且这些函数往往要用于委托对象。

Lambda表达式基本形式:

(参数...) => { 函数内容... }

参数在它的类型可自动推导的情况下,才可以省略参数类型。如果谨慎起见,可以不省略,从而避免隐式类型转换。

Action obj1;
obj1 = () => { Debug.Log("FGNB"); }; Action<int> obj2;
obj2 = (int x) => { Debug.Log(x); };
obj2 = (x) => { Debug.Log(x+233); };//也可以省略参数类型 Func<int,int> obj3 = (int x) => { return x; };

结论

  • 为了简化语法,可使用Action/Func而不是直接使用delegate,除非你想强调特殊的委托类型。
  • 实现观察者模式,可以使用event和委托(Action/Func/delegate)搭配。更加完善的做法则是再搭配Dictionary,通过Key找到想要的委托事件对象列表,然后可以添加/移除/通知该对象的观察者。
  • Lambda表达式适用于快速编写简短的函数,复杂的函数应该做成类方法方便调试。

Unity C#笔记 委托&事件的更多相关文章

  1. c#基础学习笔记-----------委托事件

    这里有一个比较简单的委托实例应用(跨窗体操作控件) http://blog.csdn.net/bdstjk/article/details/7004035 还有一个比较详细的介绍并深入理解委托事件的讲 ...

  2. Unity C# 多态 委托 事件 匿名委托 Lambda表达式 观察者模式 .NET 框架中的委托和事件

    一.多态 里氏替换原则: 任何能用基类的地方,可以用子类代替,反过来不行.子类能够在基类的基础上增加新的行为.面向对象设计的基本原则之一. 开放封闭原则: 对扩展开放,意味着有新的需求或变化时,可以对 ...

  3. C# ~ 从 委托事件 到 观察者模式 - Observer

    委托和事件的部分基础知识可参见 C#/.NET 基础学习 之 [委托-事件] 部分: 参考 [1]. 初识事件 到 自定义事件: [2]. 从类型不安全的委托 到 类型安全的事件: [3]. 函数指针 ...

  4. Unity 项目中委托Delegate用法案例

    Unity中Delegate的用法场景 本文提供全流程,中文翻译. Chinar 坚持将简单的生活方式,带给世人!(拥有更好的阅读体验 -- 高分辨率用户请根据需求调整网页缩放比例) Chinar - ...

  5. C#委托,事件理解入门 (译稿)

    原文地址:http://www.codeproject.com/Articles/4773/Events-and-Delegates-Simplified 引用翻译地址:http://www.cnbl ...

  6. 关于ios使用jquery的on,委托事件失效

    $('.parents').on("click",'.child',function(){}); 类似上面这种,在ios上点击"child"元素不会起作用,解决 ...

  7. Observer设计模式中-委托事件-应用在消息在窗体上显示

    Observer设计模式:监视者模式.在类中的方法中处理的结果或者消息通过事件委托 的方式发送给主窗体. 因为在其它类中直接访问主窗体类,显示内容是不能直接调用控件赋值的,当然也有别的类似查阅控件名, ...

  8. Asp.net用户控件和委托事件

    在Asp.net系统制作过程中,门户类型的网站,我们可以用DIV+CSS+JS+Ajax全部搞定,但是一旦遇到界面元素比较复杂的时候,还是UserControl比较方便一些,各种封装,各种处理,然后拖 ...

  9. jQuery里面的普通绑定事件和on委托事件

    以click事件为例: 普通绑定事件:$('.btn1').click(function(){}绑定 on绑定事件:$(document).on('click','.btn2',function(){ ...

随机推荐

  1. Navicat永久激活步骤,激活工具,解决注册码无效的问题

    Navicat for MySQL是一套管理和开发MySQL或MariaDB的理想解决方案,支持单一程序,可同时连接到MySQL和MariaDB.这个功能齐备的前端软件为数据库管理.开发和维护提供了直 ...

  2. Zookeeper + Dubbo + SpringMVC + dubbo-admin

    第一步:在CentOS/Windows上安装Zookeeper[前提] A:CentOS     Zookeeper作为Dubbo服务的注册中心,Dubbo原先基于数据库的注册中心,没采用Zookee ...

  3. Spring使用 --- 基本概念(一):DI,依赖注入

    Table of Contents 什么是依赖注入 怎样使用 什么时候使用 好处 本文讲述sprint基本概念之一: DI, 即依赖注入. 什么是依赖注入 说类A依赖于类B,最简单的例子是类A有一个类 ...

  4. 深入理解.net - 3.类型Type

    说到类型,.NET技术是基于通用类型系统(CTS,Common Type System)的,而CTS又是构建于公共语言架构(CLI,Common Language Infrastructure)之上, ...

  5. CSS学习笔记三:自定义单选框,复选框,开关

    一点一点学习CCS,这次学习了如何自定义单选框,复选框以及开关. 一.单选框 1.先写好body里面的样式,先写几个框 <body> <div class="radio-1 ...

  6. 解密TTY

    本文内容来自The TTY demystified ,讲述了*NIX系统中TTY的历史与工作原理,看完后解决了我很多疑惑,于是做此翻译,与大家分享. 译者:李秋豪 江家伟 审校: V1.0 Sun M ...

  7. ES6 中的 iterator

    [简介] 遍历器/迭代器.任何数据结构只要部署 Iterator 接口,就可以完成遍历操作.这种数据结构是“可遍历的”(iterable). 如何判断是否可遍历? typeof target[Symb ...

  8. String的replaceAll()用法详解

    使用replaceAll实现字符串替换,即把字符串某些字符全部替换成别的 // 将str中的所有数字替换为"数字"二字 String str = "abc123bcd45 ...

  9. EasyUI集成Kindeditor使用

    在实际的项目中,我们需要在项目中集成富文本编辑器,而kindeditor作为一款优良的编辑器,在项目中或多或少都会用到! 实际效果图     使用方法: 1.首先下载Kindeditor编辑器,我这里 ...

  10. CentOS6.5系统挂载NTFS分区的硬盘

    下载rpmforge,下载对应的版本,就是对应CentOS版本,还有32位与64位也要对应上.rpmforge拥有4000多种CentOS的软件包,被CentOS社区认为是最安全也是最稳定的一个软件仓 ...