匿名委託 Invoke,Predicate 委託

1、控件的Invoke不能直接調用匿名委託,需要一個MethodInvoker對象

Invoke定義原型:

public object Invoke(Delegate method);
public object Invoke(Delegate method, params object[] args);

MethodInvoker定義原型:public delegate void MethodInvoker();

this.button1.Invoke(new MethodInvoker(delegate(){ 
this.txtUserID.Focus(); 
})); 

或者

 label1.Invoke(new EventHandler(delegate(object o, EventArgs e)
  {
                label1.Text = "ceshi";
  }));

2、委託

     public delegate void StateChangedEventHandle(bool isConnected);

     public event StateChangedEventHandle ServerStateChanged;


2.1、匿名委託 / 匿名方法

C#爲委託提供一種機制,可以爲委託定義匿名方法,匿名方法沒有名稱,編譯器會定指定一個名稱

匿名方法中不能使用跳轉語句跳轉到該匿名方法的外部,也不能跳轉到該方法的內部。

也不能在匿名方法外部使用的ref和out參數


    //用匿名方法定義委託,匿名委託
    class Program
    {
        delegate string MyDelagate(string val);

        static void Main(string[] args)
        {
            string str1 = " 匿名方法外部 ";

            //中括號部分定義來了一個方法,沒有名稱,編譯器會定指定一個名稱,my爲委託的名稱
            MyDelagate my = delegate(string param)
            {
                string str2 = " 匿名方法內部 ";
                return param + str1 + str2;
            };
            
            //調用委託的匿名方法
            Console.WriteLine(my(" 參數 "));

            //從結果可以看到,匿名方法同樣達到了爲委託定義方法的效果

            Console.Read();
        }
    }

2.2、實名委託

        private void Form1_Load(object sender, EventArgs e)
        {
            string str1 = " 匿名方法外部 ";
            MyDelagate my = new MyDelagate(fun);
            //調用委託的匿名方法
            Console.WriteLine(my(str1));
            Console.Read();
       
        }
        private string fun(string param)
        {
            string str2 = " 匿名方法內部 ";
            return param + str2;

        }

#region 委託的應用

    //委託的定義
    public delegate string  deleRate(string year);

    //三個方法的定義,以供委託調用
    public string year_2009(string s)
    { Response.Write("2009" + s); return "2009" + s; }

    //三個方法的定義,以供委託調用
    public string year_2008(string s)
    { Response.Write("2008" + s); return "2008" + s; }

    //三個方法的定義,以供委託調用
    public string year_2007(string s)
    { Response.Write("2007" + s); return "2007" + s; }

    protected void Button1_Click(object sender, EventArgs e)
    {
        deleRate dr = new deleRate(year_2009);
        dr += year_2008;
        dr += year_2007;

        //直接用委託實例調用方法
        Label1.Text = dr("年");

        //使用委託實現方法調用方法
        Label1.Text = getYear(dr, "年");

        //使用委託實現方法調用方法,方法名作爲參數
        Label1.Text = getYear(year_2008, "年");
    }

    //執行委託的過程,把參數 year2 傳入實際執行的方法中去
    public static string getYear(deleRate dr, string year2)
    { return dr(year2); }

    #endregion


3、Predicate<T> 委託

Predicate<T> 委託:表示定義一組條件並確定指定對象是否符合這些條件的方法。

下面的代碼示例使用帶有 Array.Find<T> 方法的 Predicate<T> 委託搜索 Point 結構的數組。如果 X 和 Y 字段的產品大於 100,000,則該代理所代表的方法 ProductGT10 將返回 true Find<T> 方法調用數組的每個元素的代理,從而在第一個滿足測試條件的點停止。

非泛型類Array使用Predicate<T> 委託,實名委託

public class Example
{
    public static void Main()
    {
     
        Point[] points = { new Point(100, 200), 
            new Point(150, 250), new Point(250, 375), 
            new Point(275, 395), new Point(295, 450) };
        Point first = Array.Find(points, ProductGT10);
        Console.WriteLine("Found: X = {0}, Y = {1}", first.X, first.Y);
    }

    // This method implements the test condition for the Find
    // method.
    private static bool ProductGT10(Point p)
    {
        if (p.X * p.Y > 100000)
        {
            return true;
        }
        else
        {
            return false;
        }
    }
}

/* This code example produces the following output:

Found: X = 275, Y = 395
 */

泛型類List<T> 使用 Predicate<T> 委託,匿名委託

        private void Form1_Load(object sender, EventArgs e)
        {
            List<int> lst = new List<int>(){0,2,3,8,9};
            List<int> newlst = lst.FindAll(delegate(int x) { return x >= 3; });
            List<Person> lstp = new List<Person> { new Person("sunsan", 14), 
                new Person("hellon", 12),new Person("lili",30) };
            int index = lstp.FindIndex(delegate(Person p) { return p.Age == 12; });
        }
    public class Person
    {
        public Person(string name,int age)
        {
            this.Name = name;
            this.Age = age;
        }
       public string Name;
       public int Age;
    }

(1)、泛型還是非泛型使用Predicate<T> 委託,都可以用匿名或者實名委託。

(2)、但是非泛型類要傳入 泛型數組 T[] array,   泛型List<T>不需要傳入

(3)、方法原型

        public static T Find<T>(T[] array, Predicate<T> match);
        public static int FindIndex<T>(T[] array, Predicate<T> match);
        public List<T> FindAll(Predicate<T> match);
        public int FindIndex(Predicate<T> match);

4、Lambda表達式

參見  http://www.cnblogs.com/daxnet/archive/2008/11/14/1687010.html

     從委託的角度來看,Lambda表達式與匿名方法沒有區別。在【C#基礎:匿名方法】一文中,我使用了匿名方法來調用List<T>的FindAll方法。從C# 3.0開始,在使用匿名方法的地方,完全可以用Lambda表達式來代替。Lambda表達式的定義方式爲:“([參數列表]) => 表達式”。運算符“=>”是一種與賦值運算“=”具有相同優先級的右結合運算符,在英語裏讀作:“goes to”。

現在回過頭來看我們的例子。下面的代碼與【C#基礎:匿名方法】一文中的代碼具有相同的效果:

class Program   
   {   
    static void Main(string[] args)   
    {   
        List<string> names = new List<string>();   
        names.Add("Sunny Chen");   
        names.Add("Kitty Wang");   
        names.Add("Sunny Crystal");   
        List<string> found = names.FindAll   
            (   
            // Lambda Expression Implementation   
            name => name.StartsWith(   
                "sunny",    
                StringComparison.OrdinalIgnoreCase)   
            );   
        if (found != null)   
        {   
            foreach (string str in found)   
                Console.WriteLine(str);   
        }   
    }   
}   

上面的Lambda Expression Implementation在效果上與匿名方法沒有任何區別,“=>”左邊的name定義了參數(當參數個數爲1的時候,圓括號可以省略),“=>”右邊定義執行體。由於C# 3.0編譯器具有Type Inference的能力,參數類型與返回值都將由編譯器通過上下文判定,因此與匿名方法不同,Lambda表達式的參數可以不給定參數類型。當所表示的匿名方法沒有任何參數時,Lambda表達式也同樣可以使用,只需在“=>”左邊用一對圓括號表示即可。即:

  1. () => Console.WriteLine("Hello!");   

事實上,“Lambda表達式”這一詞比較籠統,事實上“=>”運算符既可以表示Lambda表達式,也可以表示Lambda語句。Lambda語句由代碼塊組成,形式上很像匿名方法。請看下面的例子:

class Program   
{   
    static void Main(string[] args)   
    {   
        // Lambda 表達式   
        Func<int, bool> dele1 = n => n > 10;   
        // Lambda 語句   
        Func<int, bool> dele2 = (int n) => { return n > 10; };   
        Console.WriteLine(dele1(16));   
        Console.WriteLine(dele1(8));   
    }   
}   

兩種定義方法同樣可以正確地輸出結果。請注意,當我們希望構建表達式樹的時候,情況卻完全不同了:

  1. // ok   
  2. Expression<Func<intbool>> expr1 = n => n > 10;   
  3. // error: cannot converted to an expression tree   
  4. Expression<Func<intbool>> expr2 = (int n) => { return n > 10; };   

由此可見,在構建表達式樹的時候,不能用Lambda語句(帶有代碼語句的Lambda表達式),而應該使用Lambda表達式。從這裏就可以看出匿名方法與Lambda表達式的區別了。

..


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章