Unity中C#委托与事件

C#学习中,随着深入学习,总会遇到委托和事件。但是往往以为理解了,运用时又容易陷入困惑,写不出来了。

为此,我根据我自己的理解与编写思路做了个总结。

首先理解下委托,委托是什么?

我理解委托为:它就是定义了一种函数的类型,凡是与定义的所谓委托具有相同类型的函数,都可以通过委托来进行调用。而所谓函数与委托类型相同,其实就是它们的参数是否相同。

如何使用委托?

1、定义一个委托,或者说是声明委托。这一步就像变量的声明一样,变量也是先声明再赋值,再使用。

格式是:修饰符(public/private)  delegate(关键字)  void(关键字)   委托名(name)  (参数1,参数2...);

例:public delegate void MyHandler();--无参类型的

       private delegate void MyHandler(string a);--有参类型的

通常我们定义一个委托把它们定义在类之前,所以我们可以跨类对这个委托使用。尤其我们在定义事件的时候,我们可以根据这种格式的委托,在不同的类中都可以定义事件。

2、定义的与委托参数一样的函数

例:public void DoSomething(){ 函数体... }  //无参    public void DoSomething1(){ 函数体... }  //无参 

       public void DoSomething(string b){ 函数体...} //有参

3、实例化委托(相当于绑定要调用的方法)

方法:使用new 关键字 

例:使用上面定义的委托和函数  MyHandler AA = new MyHandler(DoSomething);  //有参无参的实例化中函数都是只需函数名DoSometing

假如使用匿名方法,那么可以忽略第2步且不需要new关键字,例:MyHandler AA = delegate{函数体...}; //无参

MyHandler AA = delegate(string a){函数体...}; //有参

使用+= 实例化还可依次绑定多个函数方法;

例:MyHandler AA = new MyHandler(DoSomething); 

       AA += new MyHandler(DoSomething1);

//这样实例化的AA就绑定了两个函数了

例:AA += new 

4、委托的调用

使用实例化后的委托调用,调用方法类似于函数的调用。

例:AA(); //无参

       AA("字符串"); //有参,带上参数值

除了用delegate定义的委托,还有两个特殊的委托,它们是Action/Func

Action的用法:

相比于delegate,Action是直接忽略了第1步的定义,我们直接实例化,再进行调用就可以了。

Action无参的实例化与调用:

例:Action MyactionHandler = new Action(DoSomething);  //无参的实例化

       MyactionHandler(); //调用

Action有参的实例化与调用:

实例化格式:Action<参数类型1,参数类型2...> 实例化委托名 = new Action<参数类型1,参数类型2...>(函数名)

例:Action<string> MyactionHandler = new Action<string>(DoSomething); //有参实例化

      MyactionHandler("字符串"); //有参调用,带上参数值

Func的用法:

Func跟Action一样,都忽略第1步,也直接实例化然后进行调用,但是Func跟Action的区别是Func必须有返回数值。

Func无参的实例化与调用:

例:Func<string> MyfuncHandler = new Func<string>(DoSomething2);   //所定义的第1个参数类型为返回参数类型

      public string DoSomething2()

     {
            return "无参实例化";

     }

     MyfuncHandler(); //调用

Func有参的实例化与调用:

例:Func<string,string> MyfuncHandler = new Func<string,string>(DoSomething3);   //所定义的第1个参数类型为返回参数类型

      public string DoSomething3(string aa)

     {
            return aa;

     }

     MyfuncHandler("有参实例化"); //调用

Lambda表达式

在 2.0 之前的 C# 版本中,声明委托的唯一方法是使用命名方法。 C# 2.0 引入了匿名方法,而在 C# 3.0 及更高版本中,Lambda 表达式取代了匿名方法,作为编写内联代码的首选方式,实际上是委托变得越来越简洁的递进。

使用Lambda表达式是把第2步放在了第3步一起进行实例化,并且简化第3步,用=>取代右侧的“new 委托名”部分。

例:MyHandler AA = (){函数体...};  //无参

      MyHandle  AA =(x,y){函数体...}; //有参

委托的作用是啥?

我的理解是传递参数或者定义事件。

事件是什么?

事件是基于委托的。我理解的事件是用于传递参数的或者在响应事件时执行命令的。

1、定义事件

结构:修饰符(public/private) event(关键字) 委托名  事件名;//事件是在类中定义的并在类中调用

例:public event MyHandler MyHandlerEvent;

2、订阅事件

方法:事件名 += new 委托名(执行函数的函数名);

          事件名 += 执行函数的函数名;//简化

例:MyHandlerEvent += DoSomething;

3、事件的调用

方法:用Invoke或直接调用,跟函数调用方法类似

例:MyHandlerEvent.Invoke(6);

       MyHandlerEvent();  //无参

       MyHandlerEvent("调用");  //有参

Unity有一个系统自带的委托EventHandler:System.EventHandler.

System.EventHandler是IDE提供的封装好含有2个参数(object sender ,EventArgs e)的委托,前面参数是事件发送者object sender,后面是事件详情标签(传递事件的细节)EventArgs e;

直接用案例来理解:

1、先在一个类中定义事件:

using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Ueventhandler : MonoBehaviour {

    public event EventHandler U_HandlerEvent;  //定义一个EventHandler事件

    //调用方法
    //第一个参数为Unity中的一个对象
    //后面一个参数表示要传递的参数,类型为EventArgs,自定义也要以它为基类
    public void Beginthat(GameObject obj, MyEventArgs e)      
    {
        if (U_HandlerEvent != null)
        {
            U_HandlerEvent(obj, e);
        }
    }    
}

2、我需要传递参数,所以要自定义一个参数类,可根据需要灵活处理(没有要传递的参数则忽略此步)

using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class MyEventArgs : EventArgs
{
    private string message;    
    public string Message { get { return message; } private set { message = value; } }   
    public MyEventArgs(string _message)
    {        
        Message = _message;
    }
}

3、订阅事件与调用事件

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System;

public class DoSomething : MonoBehaviour {
    public Ueventhandler uEventHandler;
	// Use this for initialization
	void Start () {
        uEventHandler.U_HandlerEvent += doSomething;
    }
	
	// Update is called once per frame
	void Update () {
		if(Input.GetMouseButton(0))
        {
            uEventHandler.Beginthat(gameObject,new MyEventArgs("一些信息"));//没有参数则用EventArgs.Empty
        }
	}
    private void doSomething(object sender,EventArgs e) //这里定义格式是固定的,因为要跟委托类型一致
    {
        GameObject obj = (GameObject)sender;
        MyEventArgs message = (MyEventArgs)e; //强制转换事件信息
        Debug.Log("Unity对象:" + obj.name+" "+"传输信息:"+message.Message);        
    }
}

个人理解,有不足欢迎指正或互相交流学习!

微信交流:wxid_084gqad9geox22

 
原创文章 3 获赞 3 访问量 146

猜你喜欢

转载自blog.csdn.net/mr_five55/article/details/105938723