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
,是为了代码安全性,防止对事件本身进行操作。
只能使用+=
来添加方法,-=
来取消方法;重写了+=
和-=
,其实这两个就是Add
和Remove
方法,权限为public
。
当然,事件也是可以多播的。
Unity例子理解
例如一个游戏中,玩家死亡时要干的事就有这些:
- UI界面中将hp降低为0
- 播放玩家死亡动画
- 播放玩家死亡音效
- 怪物/敌人无法攻击或者停止攻击
而如果我们在每个地方都定义一个方法,在玩家死亡后挨个调用,就会破坏代码的高内聚低耦合。
而如果我们使用事件,就只需要在玩家内部声明一个事件,然后只调用这个事件即可。
为了更好的理解事件,我们来举个例子,为了简化流程,我就只写玩家,UI脚本了,当然在此之前我们还应该创建一个Unity项目,创建出玩家和UI。
1. 创建场景
在一个新的Unity项目中,我们使用一个Plane
来当做地板,颜色就随便搞一下,或者不搞,就不细细说了。
好了,完事了,一个简单的场景+玩家+UI就完事了,那么开始敲代码吧!
2. 编写脚本
就随便写写好了。
- 玩家脚本(记得托给玩家哦)
/**
* ==========================================
* 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();
- 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#委托与事件的主要内容,如果未能解决你的问题,请参考以下文章