下面开始委托进阶部分的分享在此我分3个部分来说明表述1.带返回值的委托2.泛型委托3.委托的异步处理下面正式进入我们的主题委托进阶一、带有返回值的委托问:委托需要承载哪些信息呢?通过前面与大家分享的委托帖子中,不难答出,它存储了方法名,还有参数列表(方法签名).如://============================public delegate void testDelegate(int num);//============================其实,仔细看看上面语句,就会发现委托还同时承载了返回的类型,我把上面语句格式化下,相信大家就会明白了//=================================public delegate 返回类型ProcessDelegate(int num);//=================================上面委托定义的蓝色部分是声明委托的关键字,红色部分是返回的类型,黑色部分为委托的类型名,最后小括号中的就是参数部分啦.因此,要实现该委托就得满足下面2个条件:1、方法的返回类型和委托的返回类型必须一致;2、方法的参数也必须跟委托相同,这里是int类型.OK,就然我们一起尝试下吧!文章来自【狗刨学习网】代码如下:using UnityEngine;using System.Collections;public class babyTest : MonoBehaviour{// 定义具有返回值bool的委托public delegate bool ComparisonEventHandler(int cryid);public int cryid = 0;public GameObject[] objs;// Use this for initializationvoid Start (){ComparisonEventHandler _Comparison = Comparison01; //newComparisonEventHandler(new Test().Comparison01);_Comparison(cryid);}/// <summary>/// 方法01/// </summary>/// <param name="cryid"></param>/// <returns></returns>public bool Comparison01(int cryid){//...操作一些东西int num = 1;if (num == cryid){objs[0].SetActive(false);objs[1].SetActive(false);Debug.Log(string.Format("返回为true,恭喜找到baby哭的原因."));return true;}else{Debug.Log(string.Format("返回为false,未找到baby哭的原因"));return false;}}}运行如下:当我设置babyid为2的时候,获取返回值为false.当我设置设置baby为1的时候,获取返回值为true.二、泛型委托泛型(generic)是C#语言2.0和通用语言运行时(CLR)的一个新特性。
泛型为.NET框架引入了类型参数(type parameters)的概念。
类型参数使得设计类和方法时,不必确定一个或多个具体参数,其的具体参数可延迟到客户代码中声明、实现。
这意味着使用泛型的类型参数T,写一个类MyList<T>,客户代码可以这样调用:MyList<int>,MyList<string>或MyList<MyClass>。
这避免了运行时类型转换或装箱操作的代价和风险。
泛型的委托,就是参数的类型不确定,例如代码改写为:using UnityEngine;using System.Collections;public class delegateTest : MonoBehaviour{// 定义具有返回值bool的委托,参数采用泛型改写public delegate bool ComparisonEventHandler<T>(T cryID);public int cryid = 0;public GameObject[] objs;// Use this for initializationvoid Start(){// 给委托类型的变量赋值ComparisonEventHandler<int> _Comparison = Comparison01; bool iscry= _Comparison(cryid);//给此委托变量再绑定一个返回bool的方法ComparisonEventHandler<bool> _Comparisons = Comparison02; _Comparisons(iscry);}/// <summary>/// 方法01/// </summary>/// <param name="cryid"></param>/// <returns></returns>public bool Comparison01(int cryid){//...操作一些东西int num = 1;if (num == cryid){objs[0].SetActive(false);objs[1].SetActive(false);Debug.Log(string.Format("返回为true,恭喜找到baby哭的原因."));return true;}else{Debug.Log(string.Format("返回为false,未找到baby哭的原因"));return false;}}/// <summary>/// 方法02/// </summary>/// <param name="cryid"></param>/// <returns></returns>public bool Comparison02(bool iscry){//...操作一些东西if (iscry){Debug.Log(string.Format("baby心情不错,增加亲密度+60."));return true;}else{Debug.Log(string.Format("baby心情很差,降低亲密度-20."));return false;}}}注:在上面代码中//==================ComparisonEventHandler<int> _Comparison = Comparison01; ComparisonEventHandler<bool> _Comparisons = Comparison02;//==================红色的部分,泛型委托,在给委托变量绑定方法时,委托ComparisonEventHandler后一定要跟一个类型参数,且该参数与将要被绑定方法的参数一样的类型。
如果不写,将报错运行如下:ok,没问题使用泛型类型可以最大限度地重用代码、保护类型的安全以及提高性能。
三、方法和委托异步调用通常情况下,如果需要异步执行一个耗时的操作,我们会新起一个线程,然后让这个线程去执行代码。
但是对于每一个异步调用都通过创建线程来进行操作显然会对性能产生一定的影响,同时操作也相对繁琐一些。
c# 中可以通过委托进行方法的异步调用,就是说客户端在异步调用方法时,本身并不会因为方法的调用而中断,而是从线程池中抓取一个线程去执行该方法,自身线程(主线程)在完成抓取线程这一过程之后,继续执行下面的代码,这样就实现了代码的并行执行。
使用线程池的好处就是避免了频繁进行异步调用时创建、销毁线程的开销。
而当使用异步调用时,更多情况下是为了提升系统的性能,而在这种情况下使用异步编程时,就需要进行更多的控制,比如:当异步执行方法的方法结束时通知客户端、返回异步执行方法的返回值等。
这里我就对BeginInvoke()方法、EndInvoke()方法和其相关的IAysncResult做一个简单的介绍。
先看一段不使用异步调用的通常情况using UnityEngine;using System.Collections;using System.Threading;using System;public class test : MonoBehaviour{// Use this for initializationvoid Start(){Debug.Log("程序开始运行:"); = "Main Thread"; Calculator cal = new Calculator();int result = cal.Add(6, 8);Debug.Log(string.Format("结果为: {0}\n", result)); // 做某些其它的事情,模拟需要执行3 秒钟for (int i = 1; i <= 3; i++){Thread.Sleep(TimeSpan.FromSeconds(i));Debug.Log(string.Format("线程:{0}: 执行了 {1} s 时间(s).", , i));}Debug.Log("其它的事情完成");}public class Calculator{public int Add(int x, int y){if (Thread.CurrentThread.IsThreadPoolThread){ = "Pool Thread";}Debug.Log(string.Format("开始计算{0}+{1}=?",x,y));// 执行某些事情,模拟需要执行2 秒钟for (int i = 1; i <= 2; i++){Thread.Sleep(TimeSpan.FromSeconds(i));Debug.Log(string.Format("线程:{0}: 添加执行了{1}s 时间(s).", , i));}Debug.Log("计算成功!");return x + y;}}}注:如果你确实执行了这段代码,会看到这些输出并不是一瞬间输出的,而是执行了大概十多秒的时间才显示那是因为线程是串行执行的,所以在执行完Add()方法之后才会继续Start中剩下的代码。