C#委托的介绍(delegate、Action、Func、predicate)

1.委托的声明

  (1). delegate

        delegate我们常用到的一种声明

    Delegate至少0个参数,至多32个参数,可以无返回值,也可以指定返回值类型。

    例:public delegate int MethodtDelegate(int x, int y);表示有两个参数,并返回int型。

  (2). Action

       Action是无返回值的泛型委托。

   Action 表示无参,无返回值的委托

   Action<int,string> 表示有传入参数int,string无返回值的委托

   Action<int,string,bool> 表示有传入参数int,string,bool无返回值的委托

       Action<int,int,int,int> 表示有传入4个int型参数,无返回值的委托

   Action至少0个参数,至多16个参数,无返回值。

   例:

    public void Test<T>(Action<T> action,T p)
    {
       action(p);
    }

  (3). Func

   Func是有返回值的泛型委托

   Func<int> 表示无参,返回值为int的委托

   Func<object,string,int> 表示传入参数为object, string 返回值为int的委托

   Func<object,string,int> 表示传入参数为object, string 返回值为int的委托

   Func<T1,T2,,T3,int> 表示传入参数为T1,T2,,T3(泛型)返回值为int的委托

   Func至少0个参数,至多16个参数,根据返回值泛型返回。必须有返回值,不可void

      例:   

  public int Test<T1,T2>(Func<T1,T2,int>func,T1 a,T2 b)
  {
      return func(a, b);
  }

        (4) .predicate

   predicate 是返回bool型的泛型委托

   predicate<int> 表示传入参数为int 返回bool的委托

   Predicate有且只有一个参数,返回值固定为bool

   例:public delegate bool Predicate<T> (T obj)

具体范例

委托

我声明了一个委托,标明了它支持的方法的类型(参数和返回值)。相当于定义一个类MethodDelegate。然后我用这个类声明了一个函数指针MethodDelegate CalSum,并把它指向自定义的Add()函数。那么我就直接可以通过CalSum来使用Add方法。

输出 result=8。

    public delegate int MethodDelegate(int x, int y);

    MethodDelegate CalResult;
    public int Add(int x, int y)
    {
        return x + y;
    }

    void Start()
    {
        CalResult = Add;
     //判定委托是否为空
     if(CalResult!=null){
int result = CalResult(3, 5); Debug.Log("result=" + result);
} }

但是需要注意的是这个委托定义的函数指针是可以同时关联多个函数的。如果我使用+=而不是=,调用函数指针的时候会先后调用两个函数。返回值最终是后一个.

输出 result=-2。

public delegate int MethodDelegate(int x, int y);

    MethodDelegate CalResult;
    public int Add(int x, int y)
    {
        return x + y;
    }
    public int Sub(int x, int y)
    {
        return x - y;
    }

    void Start()
    {
        CalResult += Add;
        CalResult += Sub;
     //判定委托是否为空
     if(CalResult!=null){
     int result = CalResult(3, 5); 
     Debug.Log(
"result=" + result);
}
}

事件

委托是一个类型,事件修饰的是一个对象。其实事件是委托的一个修饰符,加了event(事件)修饰之后,委托就被阉割了,

 1 public class Calculate
 2 {
 3     public static int Sub(int x, int y)
 4     {
 5         return x - y;
 6     }
 7 }
 8 public class MyClass
 9 {
10     public delegate int MethodDelegate(int x, int y);
11     public MethodDelegate deleCalValue;
12     public event MethodDelegate eventHandler;
13 }
14 
15 public class ActionTest : MonoBehaviour
16 {
17     MyClass mine = new MyClass();
18     void Start()
19     {
20         mine.deleCalValue = Calculate.Sub;
21         mine.eventHandler = Calculate.Sub;//报错,提示事件“MyClass.eventHandler”只能出现在 += 或 -= 的左边(从类型“MyClass”中使用时除外)
22 
23         mine.deleCalValue(2, 4);
24         mine.eventHandler(2, 4);//报错同上
25     }
26 }

除非在声明事件的MyClass内部,否则不能对事件event修饰的委托赋值的。

而且事件也不能在外部类里直接调用委托。

回调

回调函数示例。其实就是委托。把想执行的函数当做参数传进去

 1  public Action<int,int> m_action;//定义回调
 2     void Start()
 3     {
 4         m_action = GetSum;//回调函数绑定
 5         DoAction(m_action);
 6     }
 7     //第三方函数
 8     void DoAction(Action<int,int> action)
 9     {
10         action(1,2);
11     }
12 
13     //想要回调的函数
14     void GetSum(int x, int y)
15     {
16         Debug.Log(x+y);
17     }

 但是如果加载有时间才回调,就会先输出"hhh",再输出3

 1     public Action<int,int> m_action;//定义回调
 2     void Start()
 3     {
 4         m_action = GetSum;//回调函数绑定
 5         DoAction(m_action);
 6         Debug.Log("hhh");
 7     }
 8     //第三方函数
 9     void DoAction(Action<int,int> action)
10     {
11         StartCoroutine(Do(action));
12     }
13     IEnumerator Do(Action<int, int> action)
14     {
15         yield return 2;
16         action(1, 2);
17     }
18 
19     //想要回调的函数
20     void GetSum(int x, int y)
21     {
22         Debug.Log(x+y);
23     }
原文地址:https://www.cnblogs.com/luxishi/p/8961360.html