文档章节

Unity3D学习资源:委托和lambda表达式一

浩浩老师
 浩浩老师
发布于 2015/09/17 13:50
字数 2047
阅读 255
收藏 0
 

一.在C#中我们可以使用delegate关键字来声明一个委托,声明的格式如下:

delegate <函数返回类型> <委托名> (<函数参数>)

下面我们来看一下代码是如何来写的:

[C] 纯文本查看 复制代码

using System;
using System.Collections.Generic;

namespace demo
{
        //声明一个委托,两个int类型的参数,一个int类型的返回值
        delegate int MyDelegate(int x,int y);
        class Test
        {
                //求两个数的和,两个int类型的参数,int类型的返回值;
                public int Sum(int a, int b)
                {
                        return a + b;
                }
                //两个数的差,两个int类型的参数,int类型的返回值
                static public int Min(int a, int b)
                {
                        return a - b;
                }
        }

        class MainClass
        {
                

                public static void Main(string[] args)
                {
                        //创建Test类的一个对象
                        Test test = new Test();

                        //声明一个MyDelegate类型的变量,由于该类型的委托在声明时有两个int类型的参数和int类型的返回值
                        //其格式与Test类中Sum和Min两个方法的格式一样,故可以直接把这两个方法赋值给该委托类型的变量mydel
                        //这时可以说委托绑定了方法,它不仅可以绑定类方法,也可以绑定实例方法
                        MyDelegate mydel = Test.Min;//绑定了类方法
                        MyDelegate mydel1 = test.Sum;//绑定了实例方法
                        //委托变量的使用与方法的使用是一样的,也要带参数,也有返回值
                        Console.WriteLine(mydel1(2, 3));
                }
        }
}

在名字空间内部,类的外部创建一个委托类型MyDelegate,其声明的格式为:返回值int类型,参数有两个,都是int类型.大家可以看到该委托的格式与Test类里面的Sum和Min方法在格式外形上来看是一致的.在Main方法里面,我们就可以把Sum方法直接赋值给MyDelegate的一个变量,此时我们可以说把一个方法绑定给了一个委托变量,从上面的代码中可以看到,委托不仅可以绑定类方法,也可以绑定实例方法.

从上面的代码我们可以得到如下的结论:

1.在声明委托时有一定的格式,我们就可以把与该委托格式一样的方法名直接赋值给该委托的一个变量;

2.从某种意义上来讲,委托相当于一个方法模版,把与该模版相同的方法赋值给委托变量后,使用委托变量时,本质上来讲就是使用其所绑定的方法;

3.委托变量的使用与方法的使用是一样的,如果有参数,委托变量后面一定要带小括号,里面要加参数,并且个数和类型要一致,如果没有参数,也要加小括号;

(其它三种格式的委托大家可以自己练习试着做一下)

委托不仅可以绑定一个方法,还可以绑定多个方法,如下代码:

[C] 纯文本查看 复制代码

using System;
using System.Collections.Generic;

namespace demo
{
        //声明一个委托,一个string类型的参数,无返回值
        delegate void GreetDelegate(string str);
        class Test
        {
                //一个string类型的参数,无返回值
                public void ChineseGreet(string name)
                {
                        Console.WriteLine("早上好!!" + name);
                }
                //一个string类型的参数,无返回值
                public void EnglishGreet(string name)
                {
                        Console.WriteLine("Good morning!!" + name);
                }
        }

        class MainClass
        {
                

                public static void Main(string[] args)
                {
                        //创建Test类的一个对象
                        Test test = new Test();

                        //绑定了第一个方法
                        GreetDelegate greet = test.ChineseGreet;
                        //绑定第二个方法,用+=运算符,通常称为委托合并
                        greet += test.EnglishGreet;
                        greet("lisi");

                }
        }
}

我们在给委托变量绑定第一个方法时,直接用赋值运算符,这样才可以使委托变量进行实例化,否则是不能用的,绑定第二个方法时,用+=运算符,这样委托变量就同时绑定了两个方法,通常也称为委托合并,在Main方法里面使用委托时,会调用所绑定的两个方法,把结果打印出来,所绑定的方法是有先后顺序的,先绑定的方法会先执行.使用委托时只需要记住一点:即委托所绑定的方法从格式上二者要一致.

以上的两个例子,委托在绑定方法时,都会先把方法创建好,下面讲另外两种委托,匿名委托和lambda表达,这样就不用再创建方法了.下面的代码是把上面的例子用匿名委托改写的,代码如下:

[C] 纯文本查看 复制代码

public static void Main(string[] args)
                {
                        Greet greet = delegate(string str)
                        {
                                        Console.WriteLine("早上好!!" + str);
                        };
                        greet += delegate(string str)
                        {
                                        Console.WriteLine("Good Morning!!" + str);
                        };
                        greet("小李");
                }

其结果与上面的一样,使用匿名委托时其格式为:delegate(){};小括号里面为参数,大括号里面是方法体,具体是否有返回值,以及参数个数和参数类型要与其所赋值的委托格式一致,如果有返回值,则只需要在大括号里面return一个返回值即可;如把上面的第一个例子用匿名委托更改如下:

[C] 纯文本查看 复制代码

MyDelegate mydele = delegate(int a, int b)
                        {
                                return a + b;
                        };

由于MyDelegate的格式为:返回值为int类型,参数2个,都是int类型,所以匿名委托的参数也要有两个并且都是int类型,在{}里面要有一个返回值.下面再看另外一种匿名委托,lambda表达式,其在C++中称为闭包,其格式如下: (()=>{}),具体的使用方法请看以下代码:

[C] 纯文本查看 复制代码

MyDelegate mydele = ((int a, int b) =>
                        {
                                return a + b;
                        });
                        Console.WriteLine(mydele(2, 3));

结果和上面的例子是一样的.大家只需要记住其格式即可,(()=>{}),小括号里时面是参数,大括号里面是方法体.只要大家看得多了,就会习惯这种编程方法了.

下面一种委托是Func委托,格式为Func<形参1类型,形参2类型...返回值类型> 委托变量名;<>里面的最后一个为返回值类型,前面的都是参数类型,该委托一定要有返回值.具体的代码如下:

[C] 纯文本查看 复制代码

Func<int,int,int> s = test.Sum;
                        Console.WriteLine(s(3, 4));

最后一种委托是Action委托,格式为Action<形参类型> 委托变量名;<>里面是形参类型,参数可以有多个,此委托没有返回值,具体的用法如下代码:

[C] 纯文本查看 复制代码

Action<string> action = test.ChineseGreet;
                        action("lisi");

二.上面的例子我们看到,定义的委托都是在类外面,名字空间下面的,所有的类都可以用该委托,这与我们讲的面向对象的三大特性封装是相违背的,此时我们就把委托放到类里面,然后在类里面创建一个public修饰的委托变量,然后在类的外面就可以拿到该委托变量,进而使用它.具体的代码如下:

[C] 纯文本查看 复制代码

class Test
        {
                public delegate void PrintDelegate();

                public PrintDelegate printdel;
public void Print()
                {
                        Console.WriteLine("蓝鸥科技");
                }
}

//下面是Main方法
public static void Main(string[] args)
                {

                        //创建Test类的一个对象
                        Test test = new Test();
                        test.printdel = test.Print;
                        test.printdel();
}

具体的其它用法同上面;

三.event关键字如果类里面的一个委托变量用public event来修饰,在类的外面可以直接拿到该委托变量,并且在绑定方法的时候,只能用+=运算符,即使绑定第一个方法,也要用+=运算符,但是有一点,绑定方法以后,不能够直接使用,必须把该委托变量放到类里面的方法里面.具体的代码如下:

[C] 纯文本查看 复制代码

class Test
        {
                public delegate void PrintDelegate();
                public  PrintDelegate printdel;
                //用event修饰委托变量
                public event PrintDelegate eventdelegate;
//调用该方法,才可以执行方法里面的委托
 public void EventPrint(){
                        eventdelegate();
                }
                public void Print()
                {
                        Console.WriteLine("蓝鸥科技");
                }
}
        public static void Main(string[] args)
                {

                        //创建Test类的一个对象
                        Test test = new Test();
test.eventdelegate += test.Print;
                        test.EventPrint();

}
event修饰的委托也可以绑定多个方法,用法同上;


本文转载自:http://bbs.lanou3g.com/forum.php?mod=viewthread&tid=5849

浩浩老师
粉丝 1
博文 80
码字总数 0
作品 0
海淀
程序员
私信 提问
Unity脚本运行时更新带来了什么?

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/zhenghongzhi6/article/details/82705584 洪流学堂,让你快人几步!本文首发于洪流学堂微信公众号。 本文是该...

关尔Manic
2018/09/14
0
0
2019年Unity学习资源指南[精心整理]

前言 进入一个领域,最直接有效的方法就是,寻找相关综述性文章,首先你需要对你入门的领域有个概括性的了解,这些包括: 目录 一、Unity官方学习资源 二、Unity 基础篇—— C# 学习资源 三、...

天马yp
2019/10/31
0
0
Unity C#笔记 委托&事件

C#的委托与事件搭配,即是观察者模式的一种实现。 因为观察者模式的原理很易懂,不作多讲,本文纯粹用于记录语法。 # delegate(委托) 声明一个委托类型(类似typedef XXXX C++/C的函数类型...

KillerAery
2019/03/10
0
0
【Unity】多线程和主线程交互使用类——Loom工具分享(转载)

作者:D.S.Qiu 原文:Unity多线程(Thread)和主线程(MainThread)交互使用类——Loom工具分享 熟悉Unity的developer都知道在Unity中的线程不能使用Unity的对象,但可以使用Unity的值类型变...

何三思
2018/04/12
0
0
[Unity脚本运行时更新]C#6新特性

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/zhenghongzhi6/article/details/82882462 洪流学堂,让你快人几步!本文首发于洪流学堂微信公众号。 本文是该...

关尔Manic
2018/09/28
0
0

没有更多内容

加载失败,请刷新页面

加载更多

Java中的原生关键字是什么?

在玩这个谜题 (这是Java关键字琐事游戏)时,我遇到了native关键字。 Java中的native关键字用于什么? #1楼 实现本机代码的函数被声明为本机。 Java本机接口(JNI)是一个编程框架,使在Jav...

技术盛宴
今天
54
0
博通与苹果达成150亿美元协议,覆盖未来3年苹果产品

  据外媒报道,芯片供应商博通(Broadcom)宣布已与苹果公司签署了一份协议,为其提供“高性能的无线组件和模块”,博通表示,这些芯片将在未来 3 年半的时间内用于自 2020 年 1 月份以后发...

水果黄瓜
今天
95
0
《算法》笔记 17 - 数据压缩

读写二进制数据 基因组数据的压缩 游程编码 位图 霍夫曼压缩 前缀码和单词查找树 构造前缀码的单词查找树 写入和读取单词查找树 使用前缀码压缩 使用前缀码展开 LZW压缩 LZW的单词查找树 LZ...

zhixin9001
今天
55
0
#技术分享# 再论DDD之【实体】建模

2020年春节第一天,早早醒来,出去晨跑一下,目前武汉以及周边的疫情处于红色报警状态,今年春节宅家是最安全的做法。闲暇之余,还需要探索技术,跑步中忽然想到了【忒修斯之船】的小故事,感...

边缘行者
今天
88
0
工作自由--2020年开篇,开启一个项目:工作自由 worksolo.cn

新年伊始,我突发奇想,也是很多人敢想而不敢做的事情,下面我以一个多年软件开发从业者的角度去思考,去设计这个项目,当然希望看到这篇文章的你可以给我更多思路: 项目名称:工作自由 域名...

_aron_
今天
51
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部