C#委托与事件

Posted 布小禅

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了C#委托与事件相关的知识,希望对你有一定的参考价值。

文章目录

前言

本教程参考菜鸟教程,本人也是依赖菜鸟教程学习的C# 当你已经有其他的编程经验的时候,你再去学习别的语言,我觉得菜鸟教程是个不错的选择,你只需要把语言基础看完,然后就可以放心的去实战了,个中的语言细节是教不会的,需要你自己去实践

委托与事件

1. 委托

委托就是一个函数模板,或者你也可以理解为是一个变量,不同的是一般的变量是存储值的,而委托存储的是方法。

在你需要使用某个方法的时候,就可以通过委托调用。

1.1 委托的定义和简单使用

在C#中,委托是使用delegate来定义的,它看起来像一个虚方法,但是却不是。

委托的定义格式:

delegate 返回类型 委托名();//委托明遵循变量名定义规则

在简单的使用就是需要声明委托,赋值,再使用

using System;
namespace HelloWorldApplication

    class HelloWorld
    
		public delegate int OneNum(int a);//定义一个委托,表示只能给这个委托赋值的方法的返回值是int类型,有一个int类型的参数
		private static int DoubleNum(int a)
		
			//这个方法是让指定的数字变成二倍,随便定义的
			return a*2;
		
        static void Main(string[] args)
        
            //声明
			OneNum oneNum = null;
			//赋值
			oneNum = DoubleNum;
			//或者直接声明+赋值
			//OneNum oneNum = DoubleNum;
			//或者
			//OneNum oneNum = new OneNum(DoubleNum);
			//使用
			Console.WriteLine(oneNum(10));
        
    

输出的结果就是:20

1.2 Action和Func

Action和Func是系统已经定义好的委托,能够让我们来随意调用,是使用泛型来定义的,能够支持我们大部分使用委托的场景。

区别是,Action是返回值为void,里面有n个参数,使用重载的方法来定义n个参数,到目前为止,最多能有16个参数,足够我们去使用了。

而Func是具有返回类型,n个参数的委托。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Action和Func

    internal class Action和Func
    
        //为使用Action创建的方法
        static void NullPar()
        
            Console.WriteLine("没有参数的方法");
        
        static void OnePar(int a)
        
            Console.WriteLine("只有一个参数的方法:" + a);
        
        static void TwoPar(int a, int b)
        
            Console.WriteLine("具有两个参数的方法:" + a + b);
        
        //为使用Func创建的方法
        static int OneNum(int a)
        
            return a * 2;
        
        static float TwoNum(int a, float b)
        
            return a / b;
        
        static void Main(string[] args)
        
            Action nullPar = NullPar;
            Action<int> onePar = OnePar;
            Action<int, int> twoPar = TwoPar;
            
            Func<int,int> oneNum = OneNum;
            Func<int,float,float> twoNum = TwoNum;

            nullPar();
            onePar(10);
            twoPar(10, 20);

            Console.WriteLine("数的二倍:" + oneNum(10));
            Console.WriteLine("两数相除:" + twoNum(10, 2.5f));

        
    

1.3 多播委托

委托分为多播委托和单播委托,单播委托就是我们上面所说的,里面只含有一个方法,所以我们通过委托调用的时候,也是只调用那一个方法。

而多播委托其实就是一个方法集合,放你调用多播委托的时候,就会将多播委托这个集合遍历,挨个调用里面的方法。

其实单播委托也可以看成是只有一个成员的多播委托。

使用多播委托的方法就是:委托变量 += 方法;

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Action和Func

    internal class MoreActiion
    
        static void Test1()
        
            Console.WriteLine("Test1");
        
        static void Test2()
        
            Console.WriteLine("Test2");
        
        static void Main(string[] args)
        
            Action action = null;
            action += Test1;//也可以action = Test1;但是最好使用+=。
            action += Test2;
            action();
        
    

就是这样使用。

多播委托最好使用返回类型为void的,因为多播委托只能返回最后一个方法的返回类型。

而将方法从多播委托中移除的方法就是使用-=符号。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Action和Func

    internal class MoreActiion
    
        static void Test1()
        
            Console.WriteLine("Test1");
        
        static void Test2()
        
            Console.WriteLine("Test2");
        
        static void Main(string[] args)
        
            Action action = Test1;
            action += Test2;
            Console.WriteLine("未移除时:");
            action();
            Console.WriteLine("移除后:");
            action -= Test1;
            action();
        
    

2. 事件

事件用通俗的话说就是:

当某个条件发生时,该干什么事。

在Unity中比较常见的有:鼠标点击事件,键盘点击事件等。

而事件其实本质上也是一种委托,所以在使用事件的时候其实也是使用委托。

在C#中使用事件的关键词是:event

event是用在声明委托变量时,写在委托类型的前面,下面看这个例子

public delegate void ATest();//定义一个委托
public static event ATest aTest;//声明一个事件,也是委托变量,区别就在于even关键字

在学习过委托后我们知道,使用委托需要给委托变量进行赋值,使用=号来进行赋值。

而如果是事件的话,就不能使用=号来赋值了,因为事件重写了=号的权限为private,是为了代码安全性,防止对事件本身进行操作。

只能使用+=来添加方法,-=来取消方法;重写了+=-=,其实这两个就是AddRemove方法,权限为public

当然,事件也是可以多播的。

Unity例子理解

例如一个游戏中,玩家死亡时要干的事就有这些:

  1. UI界面中将hp降低为0
  2. 播放玩家死亡动画
  3. 播放玩家死亡音效
  4. 怪物/敌人无法攻击或者停止攻击

而如果我们在每个地方都定义一个方法,在玩家死亡后挨个调用,就会破坏代码的高内聚低耦合。

而如果我们使用事件,就只需要在玩家内部声明一个事件,然后只调用这个事件即可。

为了更好的理解事件,我们来举个例子,为了简化流程,我就只写玩家,UI脚本了,当然在此之前我们还应该创建一个Unity项目,创建出玩家和UI。

1. 创建场景

在一个新的Unity项目中,我们使用一个Plane来当做地板,颜色就随便搞一下,或者不搞,就不细细说了。

好了,完事了,一个简单的场景+玩家+UI就完事了,那么开始敲代码吧!

2. 编写脚本

就随便写写好了。

  1. 玩家脚本(记得托给玩家哦)
/**
 * ==========================================
 * FileName:#FileName#
 * Author:#Name#
 * CreatTime:#CreateTime#
 * NowPath:#path#
 * ==========================================
 */
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Player : MonoBehaviour

    public float hp;
    public delegate void Dead();
    public static event Dead Death;
    // Start is called before the first frame update
    void Start()
    
        hp = 100;
    

    // Update is called once per frame
    void Update()
    
        if (Input.GetKeyDown(KeyCode.Space))
        
            hp = 0;
            Death();
        
    

  1. UI脚本
/**
 * ==========================================
 * FileName:#FileName#
 * Author:#Name#
 * CreatTime:#CreateTime#
 * NowPath:#path#
 * ==========================================
 */
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;//引用UI

public class UI : MonoBehaviour

    Text hpText;
    float hp;
    // Start is called before the first frame update
    void Start()
    
        hpText = GameObject.Find("Hp").GetComponent<Text>();
        hpText.text = "100";
    
    private void OnEnable()
    
        Player.Death += HpFor0;
    
    // Update is called once per frame
    void HpFor0()
    
        hpText.text = hp.ToString();
    
    

3. 效果展示

好了看看效果:

当然,你可以记住这句话:使用事件是为了代码安全性,使用委托是为了低耦合高内聚,当然事件也是特殊的委托。

结语

成功的光彩靓丽之后是廉价的泪水和眼泪

欢迎喜爱Python,Unity(游戏开发引擎)的爱好者,让我们一步步走向大神,成功离得不远,也就两个字,坚持罢了!!

Unity游戏引擎宣言:

你是否热爱游戏呢?

你是否曾经幻想着有一天自己做出一款属于自己的游戏呢?

不要犹豫了,赶快学习吧!

点击链接查看Python社区:Python交流社区

点击链接查看Unity社区:游戏开发爱好者

以上是关于C#委托与事件的主要内容,如果未能解决你的问题,请参考以下文章

Unity游戏开发C#基础委托与事件

委托与事件——C#版本

C#委托与事件

C#多播委托和事件有啥区别

C#里事件和委托有啥区别啊??

C#委托与事件初探