匿名委托 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表达式的区别了。

..


你可能感兴趣的:(匿名委托 Invoke,Predicate 委托)