随风_委托浅析

1、什么是委托

如果我们要把方法当做参数来传递的话,就要用到委托。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class CSharp_学习委托 : MonoBehaviour
{
    private delegate void MyDelegate(string name);
    // Start is called before the first frame update
    void Start()
    {
        MyDelegate a = new MyDelegate(Method);
        a("HelloWorld!");
    }
    public void Method(string str)
    {
        print(str);
    }
}

2、Action委托和Func委托

  • 除了我们自己定义的委托之外,系统还给我们提供了一个内置的委托类型,Action和Func
using System;
using UnityEngine;
/*
 * Action委托引用了一个Void返回类型的方法,
 * Func委托引用了一个带有返回值的方法
 */
public class CSharp_学习委托 : MonoBehaviour
{
    private void Get()
    {
        print("***");
    }
    private void GetString(string str)
    {
        print(str);
    }
    private void GetInt(int i1,int i2)
    {
        print(i1+i2);
    }
    // Start is called before the first frame update
    void Start()
    {
        //Action可以指向一个没有返回值没有参数的方法
        Action o = Get;
        o();
        //Action可以指向一个没有返回值有一个或多个参数的方法
        Action<string> a = GetString;
        a("HelloWorld!");
        Action<int, int> b = GetInt;
        b(6, 8);

        //Func可以指向一个有返回值没有参数的方法
        Func<int> c = FInt;
        print(c());
        //Func可以指向一个有返回值有一个或多个参数的方法
        Func<int, string> d = FString;
        print(d(3));
        Func<int, int, string> e = FuncString;
        print(e(6, 8));
    }
    private int FInt()
    {
        return 1;
    }
    private string FString(int i)
    {
        return "Hello:"+i;
    }
    private string FuncString(int i1,int i2)
    {
        return ("World:" +( i1 + i2));
    }
}

3、拓展的冒泡排序

using UnityEngine;
using System;
/*
 * 给自定义的类型做排序
 */
public class EmployList : MonoBehaviour
{
    //定义一个排序雇员薪水的方法,参数1:雇员类型的数组  
    //参数2:返回值为bool还有两个Employ参数的Func委托
    static void ComEmp(Employ[] array, Func<Employ, Employ, bool> CompareF)
    {
        for(int i = 0; i < array.Length - 2; i++)
        {
            for(int j = 0; j < array.Length - 1; j++)
            {
                if (CompareF(array[j], array[j + 1])==true)
                {
                    var tem = array[j];
                    array[j] = array[j + 1];
                    array[j + 1] = tem;
                }
            }
        }
        foreach (Employ item in array)
        {
            print("名字:" + item.Name + " , " + "薪水:" + item.Salary);
        }
    }
    // Start is called before the first frame update
    void Start()
    {
        //声明一个Employ类型的数组
        Employ[] eArray = new Employ[]
        {
            new Employ("aaa",4500m),
            new Employ("bbb",8300m),
            new Employ("ccc",3700m),
            new Employ("ddd",10500m),
            new Employ("eee",7800m),
        };
        //调用ComEmp方法
        ComEmp(eArray, Employ.Compare);
    }
}
//雇员类,有名字和薪水两种属性
class Employ
{
    private string name;
    private decimal salary;
    public string Name
    {
        get { return name; }
        set { name = value; }
    }
    public decimal Salary
    {
        get { return salary; }
        set { salary = value; }
    }
    //定义一个有两个参数的构造方法
    public Employ(string name,decimal salary)
    {
        this.Name = name;
        this.Salary = salary;
    }
    //定义一个被Func委托CompareF指定的方法,比较两个对象的薪资的大小
    public static bool Compare(Employ e1, Employ e2)
    {
        if (e1.Salary > e2.Salary)
        {
            return true;
        }
        else
        {
            return false;
        }
    }
}

4、多播委托

前面使用的委托都只包含一个方法的调用,但是委托也可以包含多个方法,这种委托叫做多播委托。
  • 使用多播委托可以按照顺序调用多个方法;
  • 多播委托只能得到调用的最后一个方法的返回值,因此我们一般把多播委托的返回类型声明为void。
    void A1()
    {
        print("A1");
    }
    void A2()
    {
        print("A2");
    }
    private void Start()
    {
        Action a = A1;
        a += A2;
        a();   //输出a1、a2
        a -= A1;
        //如果a为空会报错
        if (a != null)
        {
            a();   //输出a2
        }
        //取得多播委托中所有方法的委托
        Delegate[] del = a.GetInvocationList();
        del[0].DynamicInvoke();
    }

5、Lambda表达式

相当于匿名方法的简写形式。
    delegate int Del(int i1, int i2);
    private int A2(int i,int f)
    {
        return i + f;
    }
    private void Start()
    {
        //方法一  常规方式
        Del d = new Del(A2); 
        print(d(45, 36));
    }
  • Lambda表达式的参数只有一个时,可以不加括号,当函数体的语句只有一句时,可以不加大括号和return
    private void Start()
    {
        //方法二  使用Lambda表达式  不需要定义A2方法,相当于匿名方法
        //Lambda运算符"=>"左边列出了需要的参数,参数是不需要声明类型的
        Del d = new Del((arg1, arg2) => { return arg1 + arg2; });
        print(d(5, 8));
        Func<int, int> func = i => i * 2;
        print(func(5));
    }

6、事件

  • 事件(enent)基于委托,为委托提供了一个发布/订阅机制,我们可以说事件是一种具有特殊签名的委托。
    //声明一个委托
    public delegate void MyDelegate();
    //事件的声明:public event 委托类型 事件名;
    public event MyDelegate myDelegateEvent;
为方便理解,举个小例子:
  • 观察者设计模式:有一只猫和两只老鼠,当猫叫的时候触发事件(CatShout),然后两只老鼠开始逃跑(MouseRun)。
using System;
using UnityEngine;

public class CSharp_学习委托02 : MonoBehaviour
{
    private void Start()
    {
        //方法一
        //Cat c1 = new Cat("Tom");
        //Mouse m1 = new Mouse("Jie");
        //c1.GetCome += m1.MouseRun;
        //Mouse m2 = new Mouse("Rui");
        //c1.GetCome += m2.MouseRun;
        //c1.CatShout();
        //方法二
        Cat c1 = new Cat("Tom");
        Mouse m1 = new Mouse("Jie",c1);
        Mouse m2 = new Mouse("Rui",c1);
        c1.CatShout();
    }
}
class Cat
{
    public string name;
    public Cat(string str)
    {
        this.name = str;
    }
    public void CatShout()
    {
        Debug.Log("猫"+name+"在叫");
        if (GetCome != null)
            GetCome();
    }
    public event Action GetCome;  //声明一个事件(用来发布消息)
}
class Mouse
{
    public string name;
    //方法一
    //public Mouse(string str)
    //{
    //    this.name = str;
    //}
    //方法二
    public Mouse(string str, Cat cat)
    {
        this.name = str;
        cat.GetCome += this.MouseRun;  //把自身的逃跑方法注册进猫GetCome 事件里面(订阅消息)
    }
    public void MouseRun()
    {
        Debug.Log("老鼠"+name+"跑了");
    }
}
事件和委托的区别和联系
  • 事件是一种特殊的委托,是委托的一种特殊应用,只能施加"+="(注册事件)"-="(移除事件)操作符,二者本质上是一样的;
  • 事件和委托唯一的区别就是:事件不能在类的外部触发,只能在类的内部触发;委托在外部、内部都能触发,但是最好不要在外部触发一个委托。
  • 委托常用来表达回调,事件表达外发的接口。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Android是一种基于Linux内核(不包含GNU组件)的自由及开放源代码的移动操作系统,主要应用于移动设备,如智能手机和平板电脑。该系统最初由安迪·鲁宾开发,后被Google公司收购并注资,随后与多家硬件制造商、软件开发商及电信营运商共同研发改良。 Android操作系统的特点包括: 开放源代码:Android系统采用开放源代码模式,允许开发者自由访问、修改和定制操作系统,这促进了技术的创新和发展,使得Android系统具有高度的灵活性和可定制性。 多任务处理:Android允许用户同时运行多个应用程序,并且可以轻松地在不同应用程序之间切换,提高了效率和便利性。 丰富的应用生态系统:Android系统拥有庞大的应用程序生态系统,用户可以从Google Play商店或其他第三方应用市场下载和安装各种各样的应用程序,满足各种需求。 可定制性:Android操作系统可以根据用户的个人喜好进行定制,用户可以更改主题、小部件和图标等,以使其界面更符合个人风格和偏好。 多种设备支持:Android操作系统可以运行在多种不同类型的设备上,包括手机、平板电脑、智能电视、汽车导航系统等。 此外,Android系统还有一些常见的问题,如应用崩溃、电池耗电过快、Wi-Fi连接问题、存储空间不足、更新问题等。针对这些问题,用户可以尝试一些基本的解决方法,如清除应用缓存和数据、降低屏幕亮度、关闭没有使用的连接和传感器、限制后台运行的应用、删除不需要的文件和应用等。 随着Android系统的不断发展,其功能和性能也在不断提升。例如,最新的Android版本引入了更多的安全性和隐私保护功能,以及更流畅的用户界面和更强大的性能。此外,Android系统也在不断探索新的应用场景,如智能家居、虚拟现实、人工智能等领域。 总之,Android系统是一种功能强大、灵活可定制、拥有丰富应用生态系统的移动操作系统,在全球范围内拥有广泛的用户基础。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值