1. 委托简介   

2. 委托组合与分解   

3. 泛型委托   

4.匿名方法和Lambda表达式   

 

1.委托简介

说来惭愧,做开发也有好几年了,但对委托依然一知半解,项目中也很少用到,这周在家仔细的看了下,写了点心得体会。

.net framework 基类库大量地使用了委托,那么什么是委托呢?

大家熟悉的常用数据类型(如int)的使用方法:先定义一个变量,然后给他赋值,如

Int I;//定义变量

I=100;//给变量赋值

类似的委托也可以看成是一种数据类型,可以用于定义变量,但它所定义的变量能接收的值只能是一个方法。

举个例子FirstDelegateExample:

//类MathOpt,定义了一下Add方法

Public cass MathOpt

{

Public int Add(int argument1,int argument2)

{

    Return argument1+argument2;

}

}

//定义一个委托数据类型MathOptDelegate

Public delegate int MathOptDelegate(int value1,int value2)

上述委托跟前面定义的Add方法,两者都接收两个int参数,返回一个int数值,它们是不是”长得很像”,确实,这种相似不是偶然的

定义好委托数据类型后,就可以如此使用它。

MathOptDelegate oppDel; //定义此委托类型变量

MathOpt obj=new MathOpt();//实例化类

oppDel=obj.Add; //委托变量接收一个方法, 注意add后面没有括号

oppDel(1,2); //赋值之后委托变量可以当成普通方法一样使用,等同于Add(1,2)

此项目可以得出一个直观印像:委托可以看成是一个方法的”容器”,将某一具体的方法”装入”后,就可以把它当成方法一样使用。

那么是不是所有方法都可以赋值给oppDe变量呢?

仔细看MathOptDelegate定义语句,只能接收这样的方法,拥有两个int参数,并且返回值也是int。

所以只要满足上述要求,不管其名字如何,也不管它是静态还是实例,都可以赋值给oppDel,定义委托类型时对方法的要求被称为方法的”签名”

 示例项目DynamicInvokeMethodForCS,用户输入两个操作数,再选择运算方法,程序即可算出结果。这个示例的关键之处在于它使用委托在运行时动态的调用不同方法

示例程序UseDelegateForm:点击从窗体按钮,主窗体会记录下对按钮的单击次数,这个示例关键在于主从窗间信息的传送用到了ShowInfoDelegate

 

 

2.委托组合与分解

从上面介绍的内容可知,委托变量可以引用某一方法,调用它就相当于调用这个方法

仔细想想,是不是会有以下疑惑:

如果委托仅仅是方法调用的另一种方式,那何必多此一举引入委托这一特性?直接调用方法不是更简洁明了?

其实委托不仅可以引用一个方法,还可以组合多个方法并批量执行它们,看以下示例

    delegate void MyDelegate(string s);

    class Program

    {

        static void Main(string[] args)

        {

            MyDelegate a,b,c,d;

            a=MyClass.Hello;

            Console.WriteLine("调用托变量a");

            a("a");

 

            b = MyClass.GoodBye;

            Console.WriteLine("调用托变量b");

            b("b");

 

            c = a + b;

            Console.WriteLine("调用托变量c");

            c("a+b");

 

            d = c - a;

            Console.WriteLine("调用托变量d");

            d("c-a");

 

            Console.ReadKey();

        }

    }

    class MyClass

    {

        public static void Hello(string s)

        {

            Console.WriteLine("您好,{0}", s);

        }

        public static void GoodBye(string s)

        {

            Console.WriteLine("再见,{0}", s);

        }

    }

执行结果:

上述代码委托变量c组合了委托变量a+b,因而拥有了两个方法,当执行c(“a+b”)时将导致MyClass类的两个静态方法都被执行

像这样的委托变量称为”多路委托变量”

可以用加法运算符来给合单个委托变量为多路委托变量,同样的用减法运算符从一个多路委托变量中除移某个委托变量

委托之所以有这种特性,是因为它内部可以包含多个方法引用,这些方法引用被称为”委托调用列表”

 

3.泛型委托

首先通过一个示例

  class Program

    {

        static void Main(string[] args)

        {

            MyGenericDelegate<int> del = MyFunc;

            Console.WriteLine(del(10));

            Console.ReadKey();

 

        }

        static int MyFunc(int value)

        {

            return value;

        }

    }

    public delegate T MyGenericDelegate<T>(T obj);

泛型委托跟普通委托类似,不同之处在于使用泛型委托时需要指定泛型参数,除此之外没任何神秘之处。

为了方便开发,.NET基类库针对在实际开发中最常用的情形提供了几个预定义好的委托

Func系列委托用于引用一个有返回值的方法

Func委托声明的最后一个泛型参数是委托所接收方法的返回值类型,前面的泛型类型参数(如果有的话)就是委托所接收方法的形参类型

示例如下:

class Program

    {

        static void Main(string[] args)

        {

            Func<int, int, long> func = Add;

            Console.WriteLine(func(10, 20));

 

            Func<string, string, string> func1 = LinkStr;

            Console.WriteLine(func1("你好:", "鱼"));

            Console.ReadKey();

        }

        static long Add(int x, int y)

        {

            return x + y;

        }

        static string LinkStr(string a, string b)

        {

            return a + b;

        }

 

    }

 还有另外常用的预定义委托,大家自行查阅资料

Action系列委托:接收返回为void的方法

Predicate委托:引用一个返回bool值的方法

 

 4.匿名方法和Lambda表达式

总结一下上面的使用委托步骤

1.定义委托类型

2.定义一个或多个符合委托类型要求的方法

3.定义委托类型的变量

4.将2中定义的方法引用”挂接”到3步中定义的变量,构建一个委托调用列表

5.能过委托变量间接调用方法

上述步骤是不是很烦锁,基于上述简化开发的考虑,C#引入了匿名方法和Lambda表达式

示例代码如下注意加粗字:

    class Program

    {

        static void Main(string[] args)

        {

            AddDelegate del = delegate(int i, int j)

            {

                return i + j;

            };

            Console.WriteLine(del(10, 20));

            Console.ReadKey();

        }

    }

    public delegate int AddDelegate(int i,int j);

匿名方法其实是将方法定义与委托变量赋值两个步骤合在一起,从而省掉了单独定义一个方法的麻烦

上面的代码如果用Lambda表达式,可以如此简化

    class Program
    {
        static void Main(string[] args)
        {
            SomeDelegateType del2 = argument => { return argument.ToString(); };
            Console.WriteLine(del2(10));
            Console.ReadKey();
        }
    }
    public delegate string SomeDelegateType(int argument);

Lambda表达式其实就是匿名方法的进一步简化,可以用于定义一个匿名函数,并将其传送给一个委托变量

Lambda有两种基本格式

1.(input parameter)=>表达式

2.(input parameter)=>{语句1;语句2;}

1)只有一个参数时,括号是可选的,Lambda表达式只有一条return语句时,return关键字也可省

Func<int,bool> del1=(x)=>{return x>0};

可以简化为

Func<int,bool> del1=x=>{x>0};

2)两个或更多输入参数由逗号分隔

Func<int,int,bool> del2=(int x,int y)=>{return x==y};

3)没有输入参数时,直接使用一个空的括号()

Action del4=()=>{Console.WriteLine("No argument");};

posted on 2013-04-14 00:55  会跳舞的鱼  阅读(366)  评论(6编辑  收藏  举报