C#中Delegate,Action,Func,Predicate的使用与区别

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/weixin_37608784/article/details/88555606

Unity C#中Delegate,Action,Func,Predicate的使用与区别

目的:C# 内置了几个常用委托 Action,Action,Func,Predicate,一般我们要用到委托的时候,尽量不要自己再定义一个委托了,就用系统内置的这几个已经能够满足大部分需求,且让代码符合规范。

C# 4.0 之后,Lamda ,Linq 表达式等许多新的程序写法层次不穷。与之相关的 Delegate,Action,Func,Predicate 的使用和区别让人迷惑。

委托 Delegate

匿名函数是针对 delegate 使用的。

泛型

private T GetData <T> where T:Object,new()
{
 T t=new T;
return t;
}

<> 表示当前函数为泛型。

public delegate void Action<in T>(T obj);

之前必须将 Delegate 声明到类外面,作为全局的才能在其他地方看见并使用。

Action 无返回值

Action 没有参数也没有返回值。

Action < T > 无返回值

Action,Func 改变了这个状态,说白了就是系统定义好的 Delegate ,他有很多重载的方法,便于各种应用情况下的调用。因为在系统 System 命名空间下,因此全局可见。

Action: 封装了一个方法,该方法只有一个参数并没有返回值。T 是可接受的任何类型。

Action 多个重载就是 <> 中可以添加多个类型。

扫描二维码关注公众号,回复: 5535411 查看本文章

在实际应用中,Action 要比原来定义 Delegate 灵活,方便很多。

Func<in T,out Tresult> 返回值是定义的类型

封装一个具有一个参数并返回 Tresult 参数指定的类型值的方法。

Func 和 Action 区别很明显,也很直接。

二者都是委托,但 Func 能返回函数执行结果,而 Action 返回类型是 void,这个区别很明显,也很容易确定该使用哪个。

Predicate < T > 返回值总是 bool 值

也是一种委托,表示定义一组条件并确定指定对象是否符合这些条件的方法。此方法常在集合的查找中被用到。

参考:https://www.jianshu.com/p/619a930d75b3

总结:

  • 如果要委托的方法没有参数也没有返回值就想到Action
  • 有参数但没有返回值就想到Action
  • 无参数有返回值、有参数且有返回值就想到Func
  • 有bool类型的返回值,多用在比较器的方法,要委托这个方法就想到用Predicate
  • 参考 https://www.cnblogs.com/maitian-lf/p/3671782.html

参考脚本,帮助理解:

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

/// <summary>
///  system 系统中声明了一个全局的委托泛型,
///  <T> T 表示你可以定义这个泛型为任意类型的委托,
///  而在脚本中声明 Action<string> myAction 表示,定义这个泛型委托具体为 string 类型委托
///  脚本中的变量就是这个 string 类型委托的具体变量
/// </summary>
public class TestAction : MonoBehaviour
{

    #region  delegate 基础
    public delegate void ShowDel(int a);//定义委托类
    ShowDel showDel;//委托类对象
    void Start()
    {
        //函数的内存地址给了showDel
        showDel = new ShowDel(ShowMyData);//初始化委托指向函数
        showDel(1);//直接调用委托,找到内存地址调用函数


        //底层是一个数组,调用的时候遍历一下
        showDel += ShowMyData2;//初始化委托指向函数
        showDel += ShowMyData1;
        //showDel-=ShowMyData1; 取消委托
        showDel(1);//三个函数都会调用
    }
    void ShowMyData(int a)
    {
        Debug.Log(a);
    }
    void ShowMyData1(int a)
    {
        Debug.Log(a);
    }
    void ShowMyData2(int a)
    {
        Debug.Log(a);
    }


    #endregion

    #region Action
    //Action 封装的方法没有参数也没有返回值
    public void Alert()
    {
        Debug.Log("Action test");
    }

    void StartAction()
    {
        Action ac = new Action(Alert);
        Action t = () => { Debug.Log("Action test"); };//语句简短也可以使用 Lambda 表达式
        ac();//调用 委托
        t();
    }
    
    #endregion 

    #region Action<T> 
    public string myName;
    Action<string> myAction;
    //
    public TestAction()
    {
        // 三种 Action 使用方法   调用委托  注意第一种方法和第三种只是 delegate,=> 的区别
        myAction = delegate (string curName) { myName = curName; };//匿名委托
        myAction = new Action<string>(SetAction);//指定一个实际方法
        myAction = curname => { myName = curname; };//使用 Lamda 表达式。     //匿名函数就是没有函数体,直接 参数 => 具体方法语句
    }
    void SetAction(string name)
    {
        myName = name;
    }
    #endregion

    #region Func<in T,T Tresult>
    public string Name;
    Func<string, string> myFunc;
    
    public void UseFunc()
    {
        //三种使用 Func 的方式
        myFunc = delegate (string curName) { return curName.ToUpper(); };
        myFunc = new Func<string, string>(SetFunc);
        myFunc = mName => { return mName.ToUpper(); };//匿名函数的优点,就是根据使用当前函数出现的变量,代码更简洁,但可能有些不易读
    }

    string SetFunc(string name)
    {
        return name.ToUpper();
    }

   /// <summary>
   /// 注意这个用法
   /// </summary>
   /// <param name="curName"></param>
    public void StartFunc(string curName)
    {
        Name = myFunc(curName);
    }
    #endregion

    #region Predicate<T>
    Predicate<int> myPredicate;
    int[] myNum = new int[8] { 12, 33, 89, 21, 15, 29, 40, 52 };
    public int[] myResult;

    public void TestPredicate()
    {
        myPredicate = delegate (int curNum) 
        {
            if (curNum % 2 == 0)
                return true;
            else
                return false;
        };
    }
    /// <summary>
    /// 第二个参数就是 Predicate,在具体的执行中,每一个数组的元素都会执行特定的方法,如果满足要求返回 true,
    /// 并会被存在在结果集中,不符合的被踢出,最终返回的集合,即是判断后想要的集合。此方法感觉像是迭代中的 yield 。也可以用上面三种写法
    /// </summary>
    public void StartPredicate()
    {
        myResult = Array.FindAll(myNum, myPredicate);
        
    }
    #endregion
}


猜你喜欢

转载自blog.csdn.net/weixin_37608784/article/details/88555606