1、什么是委托
如果我们要把方法当做参数来传递的话,就要用到委托。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class CSharp_学习委托 : MonoBehaviour
{
private delegate void MyDelegate(string name);
void Start()
{
MyDelegate a = new MyDelegate(Method);
a("HelloWorld!");
}
public void Method(string str)
{
print(str);
}
}
2、Action委托和Func委托
除了我们自己定义的委托之外,系统还给我们提供了一个内置的委托类型,Action和Func
using System;
using UnityEngine;
public class CSharp_学习委托 : MonoBehaviour
{
private void Get()
{
print("***");
}
private void GetString(string str)
{
print(str);
}
private void GetInt(int i1,int i2)
{
print(i1+i2);
}
void Start()
{
Action o = Get;
o();
Action<string> a = GetString;
a("HelloWorld!");
Action<int, int> b = GetInt;
b(6, 8);
Func<int> c = FInt;
print(c());
Func<int, string> d = FString;
print(d(3));
Func<int, int, string> e = FuncString;
print(e(6, 8));
}
private int FInt()
{
return 1;
}
private string FString(int i)
{
return "Hello:"+i;
}
private string FuncString(int i1,int i2)
{
return ("World:" +( i1 + i2));
}
}
3、拓展的冒泡排序
using UnityEngine;
using System;
public class EmployList : MonoBehaviour
{
static void ComEmp(Employ[] array, Func<Employ, Employ, bool> CompareF)
{
for(int i = 0; i < array.Length - 2; i++)
{
for(int j = 0; j < array.Length - 1; j++)
{
if (CompareF(array[j], array[j + 1])==true)
{
var tem = array[j];
array[j] = array[j + 1];
array[j + 1] = tem;
}
}
}
foreach (Employ item in array)
{
print("名字:" + item.Name + " , " + "薪水:" + item.Salary);
}
}
void Start()
{
Employ[] eArray = new Employ[]
{
new Employ("aaa",4500m),
new Employ("bbb",8300m),
new Employ("ccc",3700m),
new Employ("ddd",10500m),
new Employ("eee",7800m),
};
ComEmp(eArray, Employ.Compare);
}
}
class Employ
{
private string name;
private decimal salary;
public string Name
{
get { return name; }
set { name = value; }
}
public decimal Salary
{
get { return salary; }
set { salary = value; }
}
public Employ(string name,decimal salary)
{
this.Name = name;
this.Salary = salary;
}
public static bool Compare(Employ e1, Employ e2)
{
if (e1.Salary > e2.Salary)
{
return true;
}
else
{
return false;
}
}
}
4、多播委托
前面使用的委托都只包含一个方法的调用,但是委托也可以包含多个方法,这种委托叫做多播委托。
使用多播委托可以按照顺序调用多个方法;多播委托只能得到调用的最后一个方法的返回值,因此我们一般把多播委托的返回类型声明为void。
void A1()
{
print("A1");
}
void A2()
{
print("A2");
}
private void Start()
{
Action a = A1;
a += A2;
a();
a -= A1;
if (a != null)
{
a();
}
Delegate[] del = a.GetInvocationList();
del[0].DynamicInvoke();
}
5、Lambda表达式
相当于匿名方法的简写形式。
delegate int Del(int i1, int i2);
private int A2(int i,int f)
{
return i + f;
}
private void Start()
{
Del d = new Del(A2);
print(d(45, 36));
}
Lambda表达式的参数只有一个时,可以不加括号,当函数体的语句只有一句时,可以不加大括号和return
private void Start()
{
Del d = new Del((arg1, arg2) => { return arg1 + arg2; });
print(d(5, 8));
Func<int, int> func = i => i * 2;
print(func(5));
}
6、事件
事件(enent)基于委托,为委托提供了一个发布/订阅机制,我们可以说事件是一种具有特殊签名的委托。
public delegate void MyDelegate();
public event MyDelegate myDelegateEvent;
为方便理解,举个小例子:
观察者设计模式:有一只猫和两只老鼠,当猫叫的时候触发事件(CatShout),然后两只老鼠开始逃跑(MouseRun)。
using System;
using UnityEngine;
public class CSharp_学习委托02 : MonoBehaviour
{
private void Start()
{
Cat c1 = new Cat("Tom");
Mouse m1 = new Mouse("Jie",c1);
Mouse m2 = new Mouse("Rui",c1);
c1.CatShout();
}
}
class Cat
{
public string name;
public Cat(string str)
{
this.name = str;
}
public void CatShout()
{
Debug.Log("猫"+name+"在叫");
if (GetCome != null)
GetCome();
}
public event Action GetCome;
}
class Mouse
{
public string name;
public Mouse(string str, Cat cat)
{
this.name = str;
cat.GetCome += this.MouseRun;
}
public void MouseRun()
{
Debug.Log("老鼠"+name+"跑了");
}
}
事件和委托的区别和联系
事件是一种特殊的委托,是委托的一种特殊应用,只能施加"+="(注册事件)"-="(移除事件)操作符,二者本质上是一样的;事件和委托唯一的区别就是:事件不能在类的外部触发,只能在类的内部触发;委托在外部、内部都能触发,但是最好不要在外部触发一个委托。委托常用来表达回调,事件表达外发的接口。
转载请注明原文地址:https://ipadbbs.8miu.com/read-60482.html