首页 > 其他分享 >delegate 委托

delegate 委托

时间:2022-11-05 21:24:05浏览次数:39  
标签:委托 Invoke void public delegate class

委托

delegate关键词

event关键字,添加后将委托封装成事件。

事件和委托区别:事件相对于委托来说更加安全。

四种类型委托

// 自定义无参无返回值
public delegate void ActionX();
// 自定义有参无返回值
public delegate void ActionY(int a);
// 自定义有参无返回值
public delegate void ActionZ<T>(T a);
// 自定义有参有返回值
public delegate int ActionU(int a,int b);

class Teacher {
    // (自定义无参无返回值委托)
    public ActionX action1;
    // (自定义有参无返回值委托)
    public ActionY action2;
    // (自定义有参无返回值委托)
    public ActionZ<string> action3;
    // (自定义有参有返回值委托)
    public ActionU action4;
    // 将委托封装成事件
    public event ActionX action5;
     
    // (系统自带无参无返回值委托)
    public Action action6;
    // (系统自带有参无返回值委托)
    public Action<int> action7;
    // (系统自带有参有返回值委托)
    // 前面的是参数,最后一个是返回值
    public Func<int, int, int> action8;

    public void Test(int a,int b) {
        action1?.Invoke();
        action2?.Invoke(a);
        action3?.Invoke(a.ToString());
        action4?.Invoke(a, b);

        action6?.Invoke();
        action7?.Invoke(a);
        action8?.Invoke(a, b);
    }
}

class Teacher2 {
    public Teacher2(Teacher teacher) {
        teacher.action1 += Test;
        teacher.action1 = Test;

        teacher.action5 += Test;
        // 将委托封装成事件后,外部调用只能通过 += 和 -= 进行调用不能够使用 = 但在内部可以使用
        //teacher.action5 = Test;
    }

    private void Test() {
        
    }
}

自定义委托类型

public delegate void Lecture();
    class Teacher {
    public Lecture lecture;
    public Teacher() {
        /*注册委托的四种方式,其中方法二和方法四较为常用,剩下两种尽量掌握,防止遇见不认识*/
        // 注册委托方法一
        lecture += new Lecture(action1);
        // 注册委托方法二
        lecture += action2;
        // 注册委托方法三
        lecture += delegate () { Console.WriteLine("我是注册的第三种委托,不常用"); };
        // 注册委托方法四
        lecture += () => { Console.WriteLine("我是注册的第四种委托,常用"); };

        /*委托单播和多播*/

        // 委托多播,委托方法执行,像委托中注册的多个函数都会执行,就称为多播。
        lecture += action1;
        lecture += action2;

        // 委托单播,委托方法执行,只会执行最后等号的函数,称为单播,但若是在后面再添加其他函数后添加的函数也是会执行的
        lecture = action1;

        // 委托事件删除,和数组删除单个元素类似
        lecture -= action1;

        // 委托事件清空,和清空数组类似
        lecture = null;
    }

    private void action1() {
        Console.WriteLine("我是注册的第一种委托,不常见");
    }

    private void action2() {
        Console.WriteLine("我是注册的第二种委托,常见");
    }
}

案例一:利用委托实现玩家扣血,UI刷新功能

玩家血量逻辑

/*玩家的数据,通过向外部暴露一个委托,从而减少代码之间的耦合度*/
using UnityEngine;

// 声明一个血量变动的委托
public delegate void HpChange(float curHp, float maxHp);

public class Player : MonoBehaviour
{
    // 将声明的委托进行实例化
    public HpChange Hurt;
    // 当前血量
    float curHp;
    // 最大血量
    float maxHp;
     
    void Start() {
        // 初始化赋值
        curHp = maxHp = 100;
        // 首次执行,刷新委托,防止显示不正确
        Hurt?.Invoke(CurHp,maxHp);
    }

    public float CurHp {
        get => curHp;
        set {
            // 血量变动
            curHp = value;
            // 执行委托方法
            Hurt?.Invoke(CurHp,maxHp);
        }
    }

    // 测试逻辑
    [ContextMenu("扣血")]
    public void HurtTest() {
        CurHp -= 10;
    }
}

UI显示逻辑

/*显示UI脚本,通过向玩家的委托中注册事件,无需获得玩家的对应数据也可以获得相应的显示效果*/
using UnityEngine;
using UnityEngine.UI;

// 玩家血量UI
public class PlayerHpUI : MonoBehaviour
{
    // 玩家
    Player player;
    // 血量Image
    Image imageHp;
    // 血量Text
    Text textHp;

    void Awake() {
        // 获得要显示的UI
        imageHp = GameObject.Find("HpImage").GetComponent<Image>();
        textHp = GameObject.Find("HpImage/Hp").GetComponent<Text>();
        // 获得对应的游戏物体
        player = FindObjectOfType<Player>();
        // 向游戏物体中的委托注册血量变动的方法
        player.Hurt += hpShow;
    }

    //血量显示,当游戏物体上的委托调用,这里也会相应的调用
    private void hpShow(float curHp, float maxHp) {
        imageHp.fillAmount = curHp / maxHp;
        textHp.text = curHp + "/" + maxHp;
    }    
}

案例二:做家务

using System;

namespace BigTalk {
    class Program {
        static void Main(string[] args) {
            Mom mom = new Mom();
            Dad dad = new Dad(mom);
            My my = new My(mom);
            mom.StartKeepHouse();
        }
    }

    // 声明一个做家务的委托
    public delegate void KeepHouse();

    class Mom {
        public KeepHouse KeepHouse;

        public Mom() {
            KeepHouse += washSheets;
        }

        private void washSheets() {
            Console.WriteLine("我今天的家务活就是洗床单");
        }

        // 开始做家务
        public void StartKeepHouse() {
            KeepHouse?.Invoke();
        }
    }

    class Dad {
        public Dad(Mom mom) {
            mom.KeepHouse += mopTheFloor;
        }

        private void mopTheFloor() {
            Console.WriteLine("我今天的家务活就是拖地板");
        }
    }

    class My {
        public My(Mom mom) {
            mom.KeepHouse += residue;
        }

        private void residue() {
            Console.WriteLine("剩余的家务活都是我的");
        }
    }
}

委托的其他用法

class Program {
    static void Main(string[] args) {
        Teacher teacher = new Teacher();
        teacher.Calculate(4,5,add);
    }

    private  static void add(int arg1, int arg2) {
        Console.WriteLine(arg1 + arg2);
    }
}

class Teacher {
    public void Calculate(int a, int b, Action<int, int> callback) {
        callback?.Invoke(a, b);
    }
}

系统自带的委托都可以通过自定义委托进行实现
开发时减少彼此代码之间的耦合度

标签:委托,Invoke,void,public,delegate,class
From: https://www.cnblogs.com/wuzhongke/p/16861325.html

相关文章

  • Android kotlin 类委托 by,by lazy关键
    前言接触kotlin语言也有几年时间了。日常开发工作中也推荐使用kotlin,但是对于一些kotlin语言语法的细节没有进行系统学习。碎片的知识点让工作中屡屡碰壁,前些天开始学习comp......
  • 委托+方法+lambda优雅用法
    usingSystem;usingSystem.Collections.Generic;usingSystem.Linq;usingSystem.Text;usingSystem.Threading.Tasks;namespaceConsoleApp.DDUP{publiccl......
  • C#委托和窗体之间的方法调用
    usingSystem;usingSystem.Collections.Generic;usingSystem.ComponentModel;usingSystem.Data;usingSystem.Drawing;usingSystem.Linq;usingSystem.Text;usingSyst......
  • QCombobox应用QStyledItemDelegate小Demo
    效果是这样的:QComboBox是个很基础的控件,也是继承自QWidget。①我们先建立代理类,继承自QStyledItemDelegate:1、头文件:#ifndefITEMDELEGATE_H#defineITEMDELEGATE_H#inclu......
  • 温故知新,CSharp遇见事件和事件(Event/Delegate),从编译后源码的角度来聊本质
    事件和委托的区别到底是什么揭秘事件一探究竟在控制台程序中定义一个事件OrderCompletedinternalclassProgram{///<summary>///订单完成事件///......
  • 无法将delegate(委托)转换为泛型类型T
    为什么我们不能将委托的实例强制转换为通用类型T?考虑一个实用程序方法CreateDelegate,它创建一个T实例,它是一个委托,即从MulticastDelegate派生的类型。TCreateDelegate......
  • 使用delegate给方法传递参数,或返回delegate对象
    第一次在博客园写文章。最近遇到一个问题,用到了多线程,以前用的时候线程启动时不需要传递参数,可现在需要时却被难了一把。。还是先说说delegate吧delegate是C#中的一种......
  • UEC 利用代理/委托写一个生命组件
    首先基于ActorComponent创建一个组件HealthComponent,将需要的变量与函数创建#include"CoreMinimal.h"#include"Components/ActorComponent.h"#include"HealthCompo......
  • C#新语法进阶委托泛型LinqLambda表达式
    学习C#开发的程序员们,相信大家也有自己的困惑。C#对于我们来说,一会很熟悉,一会很陌生,当你熟悉的时候,你阅读源码能一目十行,当你很陌生的时候,你十天能看懂一行代码。我们总是伴......
  • C#中的委托delegate和Lambda表达式
    委托:委托别人去帮我完成某件事情。自定义委托AddDelegateAD=newAddDelegate(Add);//获取需要委托的方法详细,参数返回值和定义委托参数返回值都必须一样。stringst......