认识委托
委托其实是C#中一种类型安全的回调函数机制(函数指针),委托要确定一个回调方法签名,包括参数以及返回值类型等。下面介绍委托的特点
1、方法组转换机制,支持从方法到兼容的委托类型的隐式转换(重载)
using UnityEngine;
using System.Collections;
public class DelegateScript: MonoBehaviour
{
//声明两个委托类型,它的实例引用一个方法
delegate void MyDelegate1(int num);
delegate void MyDelegate2(int num, int num1);
MyDelegate1 myDelegate1;
MyDelegate2 myDelegate2;
void Start()
{
//构造函数的方式创建委托实例并引用方法
//myDelegate1 = new myDelegate1(PrintNum);
//myDelegate1(10);
//方法组转换机制
//委托类型MyDelegate1的实例myDelegate1的引用方法是PrintNum
myDelegate1 = PrintNum;
myDelegate1(10);
//委托类型MyDelegate2的实例myDelegate2的引用方法是PrintNum的重载版本
myDelegate2 = PrintNum;
myDelegate2(20, 30);
}
void PrintNum(int num)
{
Debug.Log("print num===>" + num);
}
void PrintNum(int num1, int num2)
{
int r = num1 + num2;
Debug.Log("result num===>" + r);
}
}
2、委托参数的逆变性和委托返回类型的协变性。协变性指方法的返回类型可以是从委托返回类型派生的一个派生类;逆变性指方法获取的参数的类型可以是委托的参数类型的基类。
比如有基础单位(BaseClass),士兵(SoldierClass),英雄(HeroClass),其中BaseClass作为基类派生出士兵和英雄,那么委托可以这么定义:
delegate Object TellName(SoldierClass s);
方法可以这么定义:
string TellNameMethod(BaseClass b);
其中string是object的派生类。另外协变性和逆变性仅仅支持引用类型,不支持值类型。
委托的多方法调用
委托的多方法调用即委托链,是委托对象的集合,代码如下:
using UnityEngine;
using System;
using System.Collections;
public class DelegateScript: MonoBehaviour
{
delegate void MyDelegate(int num);
void Start()
{
//创建3个委托实例
MyDelegate md1 = new MyDelegate(this.printNum);
MyDelegate md2 = new MyDelegate(this.printDoubleNum);
MyDelegate md1 = new MyDelegate(this.printTripleNum);
MyDelegate mds = null;
//使用静态方法Combine
mds = (MyDelegate)Delegate.Combine(mds, md1);
mds = (MyDelegate)Delegate.Combine(mds, md2);
mds = (MyDelegate)Delegate.Combine(mds, md3);
//C#编译器为委托类型重载了“+=”
MyDelegate mud;
mud += new MyDelegate(this.printNum);
//允许通过制定回调方法名称而省略构造委托类型实例,其实编译器在幕后仍然会创建实例
mud += this.printDoubleNum;
mds(1);
mud(2);
}
void printNum(int num){}
void printDoubleNum(int num){}
void printTripleNum(int num){}
}
泛型委托
- 适用于无返回值类型:
public delegate void Action();
public delegate void Action<T1>(T1 args);
- 适用于有返回值类型:
public delegate TResult Func<TResult>();
public delegate TResult Func<T1, TResult>(T1 args);
- 返回值为bool的预置委托类型
public delegate bool Predicate<T>(T args);
- 排序的预置委托类型
public delegate int Comparison(int T)(T x, T y)
举例匿名方法委托:
using UnityEngine;
using System;
using System.Collections;
using System.Collections.Generic;
public class DelegateScript: MonoBehaviour
{
void Start()
{
//#1
Action<string> tellName = delegate(string name){
string intro = "my name is ";
Debug.Log(intro + name);
}
tellName("sam");
//#1-1:Lambda表达式,匿名方法的进一步演化和简化
Action<string> tellName1 = (string name) => {
string intro = "my name is ";
Debug.Log(intro + name);
}
tellName1("tom");
//#2
List<Vector3> list = new List<Vector3>();
list.Add(new Vector3(1f,2f,4f));
list.Add(new Vector3(4f,3f,6f));
list.Add(new Vector3(5f,7f,8f));
list.ForEach(delegate(Vector3 obj){
Debug.Log(obj);
});
//#2-1:Lambda表达式,匿名方法的进一步演化和简化
list.ForEach(
obj => Debug.Log(obj)
);
//#3
Func<string, string> tellName = delegate(string name){
string intro = "my name is ";
return intro + name;
}
Debug.Log(tellName("same"));
}
}
委托主要应用案例为观察者模式,关于事件和观察者模式不清楚的可以度娘
现在只是记录了委托的一些基本的知识点,项目中的具体应用后续会补上来。
关于delegate、Action和Func
action和func都是delegate的封装,delegate是默认的委托;action是系统自定义的委托,可以有参数也可以无参数;Func是带有返回值的委托
认识事件
事件是对委托的封装,事件是基于委托的存在,事件是委托的安全包裹 让委托的使用更具有安全性。
未完待续…