Contents

委托和事件

委托和事件

委托是什么

  • 委托 函数(方法)的容器
  • 用来 存储、传递函数(方法)
  • 委托的本质是一个类 用来定义函数(方法)的类型(返回值和参数的类型)
  • 不同的 函数(方法)必须对应各自"格式"一致的委托
  • 委托常用于类的成员或作为函数的参数使用
  • 委托变量可以存储多个函数

委托基本语法

  • 关键字:delegate
  • 语法:访问修饰符 delegate 返回值 委托名(参数列表);
  • 可以声明在namespace中或class中 一般写在namespace中
  • 委托的访问修饰符 默认为public
  • 不可以有同名委托(不存在重载这个概念)

定义自定义委托

无参无返回值

//声明一个 可以用来存储无参无返回值函数的容器
public delegate void MyFun();
//使用委托
MyFun f1 = new MyFun();
//另一种写法
//My Fun f1 = ()=>{Console.WirteLin("我没有参数和返回值")};  
f1 += ()=>{Console.WirteLin("我没有参数和返回值")};

//委托的调用
f1();//方法1
f1.Invoke();//方法2

有参数 有返回值

//声明一个 可以用来存储无参无返回值函数的容器
public delegate int MyFun(int value);
//使用委托
MyFun f2 = new MyFun((value)=>{return value+1});
int a = f2(3);
Console.WriteLine(a);//4

委托可以使用复合运算符

public void Fun(){
	Console.WriteLine("吃肉");
}
f2 += Fun; //吃肉
f2 = f2+Fun;//吃肉 吃肉
//从容器中移除函数
f2 = f2-Fun;//吃肉

系统提供的委托

//泛型委托 可以指定返回值
Func<int> func = new Func<int>();
//无参无返回值的委托
Action action = new Action();

//可以传n个参数的 无返回值委托
Action<int,string> action2 = new Action<int,string>();
action2 += (a,b)=>{Console.WriteLine(a+b)};
//可以传n个参数 并且有返回值的
//第一个是参数 后面的是返回值
//int返回值 有两个string参数
Func<int,string,string> fun3;

事件

  • 事件是基于委托的存在
  • 事件是基于委托的安全包裹 让委托的使用更具安全性
  • 事件是一种特殊的变量类型

事件的语法

  • 事件使用event关键字声明
  • 事件的声明:访问修饰符 event 委托类型 事件名;
  • 事件是作为 成员变量存在于类中
  • 委托怎么使用 事件就怎么使用
  • 委托和事件的不同点
    • 不能再类外部去赋值
    • 不能再类外部去调用
  • 注意:它只能作为成员存在于类、接口以及结构体中
  • 不可以声明在namespace中 也不可以声明在方法体中
class Test{
    //委托声明
    public Action MyFunc;
    //事件声明
    public event Action MyEvent;    
    
    Test(){
        //事件可以在类内部赋值
        MyEvent = new Action();
    } 
    
    public void DoEvent(){
        if(MyEvent == null) return;
        MyEvent();
    }
}

class Test2{
    
    public void Test(){
        Console.WriteLine("测试");
    }
    
   	static void Main(){
        Test t1 = new Test();
        Test2 t2 = new Test2();
        //委托可以直接赋值
        t1.MyFunc = t2.test;
        
        //事件不可以直接赋值
        t1.MyEvent = t2.Test;//报错
       	t1.Myevent = null;//报错
        
        //事件可以 使用复合运算符 去增加移除函数
        t1.Myevent += t2.Test;
        t1.Myevent -= t2.Test;
        
        //委托可以在外部调用
        t1.myFunc();
        //事件不可以在外部调用
        t2.myEvent();//报错
        //想要在外部调用 只可以在类的内部封装 然后再外部调用
        t2.DoEvent();
        
        //委托可以生命在函数中
        Aciton a = new Action();
        //事件不可以
        event Action a2 = new Action();//报错
    }
}

为什么有事件

  • 防止外部随意置空委托
  • 防止外部随意调用委托
  • 事件相当于对委托进行了一个封装 使其更加安全

匿名函数

  • 没有名字的函数
  • 匿名函数主要是配合委托和事件使用
  • 脱离委托和事件 是不会使用匿名函数的
  • 缺点:添加到委托或者事件容器后 不记录 无法被单独移除

基本语法

Action a = delegate(参数){
	//函数逻辑
};

//有返回值的
Action<string> a1 = delegate(){
    retrun "阿拉拉";
}

Unity自带委托

UnityAction action;
action = ()=>{};
//带参数的委托
UnityAction<string> action;