zoukankan      html  css  js  c++  java
  • 委托学习体会

    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");};

  • 相关阅读:
    Python动态展示遗传算法求解TSP旅行商问题
    MOEAD算法中均匀权向量的实现---Python
    HDU 5294 多校第一场1007题 最短路+最小割
    POJ 3261 Milk Patterns sa+二分
    HDU 4292 FOOD 2012 ACM/ICPC Asia Regional Chengdu Online
    CodeForces 201A Clear Symmetry
    POJ 1679 The Unique MST 确定MST是否唯一
    POJ 3268 Silver Cow Party 最短路 基础题
    POJ 2139 SIx Degrees of Cowvin Bacon 最短路 水題
    POJ2229 Sumsets 基礎DP
  • 原文地址:https://www.cnblogs.com/75115926/p/3019712.html
Copyright © 2011-2022 走看看