C# Action 和 Func 區別


前言:

  1.委托是一個類,定義了方法的類型,使得可以將方法當作另一個方法的參數來進行傳遞。

     把一個 參數類型 返回值 相同 方法名不同 的方法當變量 的方法 叫委托。

   為了實現程序的六大設計中的開閉原則:解耦,對修改關閉,對擴展開放。邏輯分離。

      直接調用函數和使用委托調用函數的區別就是是否方便對外擴展。

     當我們窗體傳值、線程啟動時綁定方法、lambda表達式、異步等等情況下需要用到。

  2.事件是一種特殊的委托,本質就是委托,事件是回調機制的一種應用。

     當委托調用的函數達到某種條件時,可以通過回調通知調用者。

一:委托的申明

  1. delegate  ,至少0個參數,至多32個參數,可以無返回值,可以指定返回值類型

       eg: public delegate int MethodDelegate(int x,int y);    //兩個參數,返回int類型

  2. Action  ,至少0個參數,無返回值的泛型委托

    Action<int,string,bool> ,有傳入int、string、bool類型的參數,無返回值的委托

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

  3. Func  ,至少0個參數,至多16個參數,必須有返回值的泛型委托

    Func<object,string,int> ,傳入參數為object、string類型的參數,返回值為int的委托

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

  4.Predicate  ,有且只有一個參數,返回值只為 bool 類型

    predicate<int> 表示傳入為int類型的參數,返回bool類型的委托。

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

二:委托的使用

  1. delegate 

    public delegate int MethodDelegate(int x,int y);
    private static MethodDelegate method;
    static void Main(string[]  args)
    {
      method = new MethodDelegate(Add);
      method(10,20);  
    }
       private static int Add(int x, int y)
    {
      return x +y;
    }

  2. Action 

    static void Main(string[] args)
    {
      Test<string>(Action, "Hello World");
      Test<string>(p => { Console.WriteLine("{0}", p); }, "Hello World" );
    }
    public static void Action(string s)
    {
      Console.WriteLine(s);
    }
    public static void Test<T>(Action<T> action,T p)
    {
      action(p);  
    }

  3. Func的使用

    static void Main(string[] args)
    {
      Test<int, int>(Fun, 100, 200);
    }
    public static int Test <T1, T2>(Func<T1, T2, int>func, T1 a,T2 b)
    {
      return func(a ,b);
    }
    private static int Fun(int a ,int b)
    {
      return a + b;
    }

  4. predicate 的使用

   static void Main(string[] args)
   {
      Point[] points = {
        new Point(100,200) ,
        new Point(250,375),
        new Point(150,250),
        new Point(275,395),
        new Point(295,450)
      };
      Point first = Array.Find(points,ProductGT10) ;
      Console.WriteLine("Found: X = {0},Y = {1}", frist.x, frist.Y);
   }
   private static bool ProductGT10(Point p)
   {
      if(p.X * p.Y > 100000)
      {
        return true;
      }
      else
      {
        return false;
      }
   }

三:委托的清空

  1.在類中循環去除委托引用

    public MethodDelegate OnDelegate;
   public void ClearDelegate()
   {
      while(this.OnDelegate != null)
      {
        this.OnDelegate -= this.OnDelegate;
      }
   }

  2.在方法中查詢出委托后去除

  public MethodDelegate OnDelegate;
  static void  Main(string[] args)
  {
    Program test = new Program();
    if(test.OnDelegate != null)
    {
       System.Delegate[] dels = test.OnDelegate.GetInvocationList();
       for(int 1 = 0; i < dels.Length; i++)
        {
         test.OnDelegate -= dels[i] as MethodDelegate;
       }
    }
  }

 PS:下面三種方式屬於老式委托的使用,就不要用了。C#3.5之后都用  Action Func

 WithParaNoReturnEventHandler _WithParaNoReturnEventHandler = new WithParaNoReturnEventHandler(MyDelegate.SayChinese);
 MyDelegate.Say("張三",_WithParaNoReturnEventHandler);  //C#1.0 傳統調用
 MyDelegate.Say("張三", delegate(string name) { Console.WriteLine("你好," + name); }); //C#2.0 匿名方法
 MyDelegate.Say("張三", (name) => { Console.WriteLine("你好," + name); }); //C#3.0 lambda表達式

 

  

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM