zoukankan      html  css  js  c++  java
  • c#中的委托(二)

    1.委托链

         委托链是委托对象的集合,利用委托链调用集合中的委托所绑定的全部方法。委托对象可使用 "+" 运算符进行合并。一个合并委托调用它所合并的两个委托。只有相同类型的委托可被合并。"-" 运算符可用于从合并的委托中移除组件委托。

    2.简单示例

    using System;
    
    namespace 委托4
    {
    
       //计算类
        public class Compute
        {
           ///加法
            public static void add(double a,double b)
            {
                Console.WriteLine("两数相加的和为{0}", a + b);
            }
    
            //乘法
            public static void mul(double a, double b)
            {
                Console.WriteLine("两数相乘的积为{0}", a * b);
            }
        }
    
    
    
        class Program
        {
            // 声明一个委托
            public delegate void result(double c,double d);
            static void Main(string[] args)
            {
               
                result r1 = new result(Compute.add);
                result r2 = new result(Compute.mul);
                r1 += r2;//向委托增加一个方法
    
                //委托具体调用方法,给定实参列表,先调用Compute.add,再调用Compute.mul
                r1(5.0,6.0);
              
                Console.ReadKey();
            }
        }
    }

    运行结果:

     

    一个合并委托调用它所合并的两个委托,只有相同类型的委托可被合并。C#编译器重载了+=和-=操作符,这两个操作符分别调用Combine和Remove方法。

    3.委托的简化(以下内容转自https://www.cnblogs.com/jixiaosa/p/10687068.html)

    3.1示例

    using System;
    
    namespace 委托5
    {
        // 声明一个委托
        public delegate void result(int c, int d);
        //计算类
        public class Compute
        {
            ///加法
            public static void add(int a, int b)
            {
                Console.WriteLine("两数相加的和为{0}", a + b);
            }
    
            //乘法
            public static void mul(int a, int b)
            {
                Console.WriteLine("两数相乘的积为{0}", a * b);
            }
        }
    
        class Program
        {
            /// <summary>
            /// Test函数,输出b-a次result方法调用
            /// </summary>
            /// <param name="a">开始</param>
            /// <param name="b">结束</param>
            /// <param name="r">委托引用</param>
            private static void Test(int a, int b,result r)
            {   
               for(int i=a; i<b; i++)
                {
                    r(a, b);
                }
               
            }
    
    
            static void Main(string[] args)
            {
                //创建result委托对象,并指定方法
                result r1 = Compute.add;
                Test(1, 3,r1);
                //创建result委托对象,并指定方法
                Test(1, 3, new result(Compute.mul));
                Console.WriteLine("************************");
                //简化1,不用创建result委托对象
                Test(1, 3, Compute.add);
                //简化2,不用指定委托的方法
                Test(1, 3, (a, b)=>{ Console.WriteLine("两数相乘的积为{0}", a * b); });
    
                Console.ReadKey();
            }
        }
    }
    View Code

    3.2不用创建委托变量

    //创建result委托对象,并指定方法
    result r1 = Compute.add;
    Test(1, 3,r1);
    //创建result委托对象,并指定方法
    Test(1, 3, new result(Compute.mul));
    Console.WriteLine("************************");
    //简化1,不用创建result委托对象,直接写方法名称
    Test(1, 3, Compute.add);

    代码更简洁,可读性更强。

    3.3不用指定委托引用的方法

    使用lambda表达式定义一个匿名函数,编译器在看到lambda表达式之后会在类中自动定义一个新的私有方法。类似于之前写的回调方法Compute.add,lambda必须匹配委托!

                //创建result委托对象,并指定方法
                result r1 = Compute.add;
                Test(1, 3,r1);
                //创建result委托对象,并指定方法
                Test(1, 3, new result(Compute.mul));
                Console.WriteLine("************************");
                //简化1,不用创建result委托对象
                Test(1, 3, Compute.add);
                //简化2,不用指定委托的方法
                Test(1, 3, (a, b)=>{ Console.WriteLine("两数相乘的积为{0}", a * b); });

    lambda的语法: 参数 => 方法体。

    =>左边是要传入的参数,本例中是传入一个Int类型的变量,=>右边是具体的代码,相当于Compute.add{}中所做的操作

    一些规则:

    如果不传递参数: ()=>Console.WriteLine("Hello World!")

    传递一个参数:(int n)=>Console.WriteLine(n.ToString())    或者去掉()和int  编译器会自己推断类型:n=>Console.WriteLine(n.ToString())

    传递多个参数:(int n ,int m)=>Console.WriteLine(n.ToString())  或者编译器自己推断类型:(n , m)=>Console.WriteLine(n.ToString())

    注:如果有一个方法需要多处调用或者方法里面的代码量较多。还是单独写一个方法较为理想。

     运行结果:

     匿名委托虽然减少了一点代码,但还是要求我们自己去声明委托。是否还能再简写一点?

     4.C#内置委托(转自https://www.cnblogs.com/dotnet261010/p/10108791.html)

     4.1Action委托(无返回值)

    (1)定义      

    Action<T>是.NET Framework内置的泛型委托,可以使用Action<T>委托以参数形式传递方法,而不用显示声明自定义的委托。封装的方法必须与此委托定义的方法签名相对应。也就是说,封装的方法必须具有一个通过值传递给它的参数,并且不能有返回值。

    (2)示例(转自:https://www.cnblogs.com/winformasp/articles/12033397.html)

    Action 表示无参,无返回值的委托。

    Action<int,string> 表示有传入参数int,string无返回值的委托。

    Action<int,string,bool> 表示有传入参数int,string,bool无返回值的委托。

    Action<int,int,int,int> 表示有传入4个int型参数,无返回值的委托。

    using System;
    
    namespace action委托
    {
        class Program
        {
            static void Main(string[] args)
            {
                //定义Action委托,无参数,无返回值
                Action act01;
                //使用Lambda表达式添加方法语句块
                act01 = () => Console.WriteLine("我是Action无参数的委托");
                //调用
                act01();
    
                //定义Action委托,有1个参数,无返回值
                Action<int> act02;
                act02 = (int a) => Console.WriteLine("我是Action有1个参数的委托{0}", a);
                act02(666);
    
                //定义Action委托,有2个参数,无返回值
                Action<int, string> act03;
                act03 = (int a, string str) =>
                {
                    Console.WriteLine("我是Action有2个参数的委托,第一个参数是{0},第二个是{1}", a, str);
                };
                act03(666, "sixsixsix");
                Console.ReadKey();
            }
        }
    }

     运行结果:

    4.2Func委托(有返回值)

    (1) Func委托代表有返回类型的委托

    (2)示例(转自:https://www.cnblogs.com/winformasp/articles/12033397.html)

    Func至少0个输入参数,至多16个输入参数,根据返回值泛型返回。必须有返回值,不可void。

    Func<int> 表示没有输入参数,返回值为int类型的委托。

    Func<object,string,int> 表示传入参数为object, string ,返回值为int类型的委托。

    Func<object,string,int> 表示传入参数为object, string, 返回值为int类型的委托。

    Func<T1,T2,,T3,int> 表示传入参数为T1,T2,,T3(泛型),返回值为int类型的委托。

    using System;
    
    namespace action委托
    {
        class Program
        {
            static void Main(string[] args)
            {
                //定义Func委托,没有参数,返回值是int
                Func<int> func01;
                func01 = () =>
                {
                    Console.Write("一个无参数的Func委托,返回值是:");
                    return 666;
                };
                Console.WriteLine(func01());
    
                //定义Func委托,有两个string参数,返回值是int,注意返回值是在<>的最后一个
                Func<string, string, int> func02;
                func02 = (string str01, string str02) =>
                {
                    Console.Write("{0}一个有两个string类型参数的Func委托{1},返回值是int类型:", str01, str02);
                    return 666;
                };
                var Temp = func02("我是", "类型");
                Console.WriteLine(Temp);
    
                Console.ReadKey();
            }
        }
    }        

    运行结果:

     4.3 Action与Func的异同

    (1)Action<T>只有参数列表,没有返回值;Func<Result>有返回类型。

    (2)Func<Result>与Action<T>都支持Lambda表达式。

    (2)Func<Result>与Action<T>都支持0~16个参数。

    参考文章:

    https://docs.microsoft.com/zh-cn/dotnet/csharp/delegate-class

    https://blog.csdn.net/lizhenxiqnmlgb/article/details/82141968

    https://www.cnblogs.com/kiba/p/9330936.html

    https://www.runoob.com/csharp/csharp-delegate.html

    https://www.cnblogs.com/jixiaosa/p/10687068.html

     https://www.cnblogs.com/dotnet261010/p/10108791.html

    转载文章链接已标明,如有侵权请告知。文章仅作为知识记忆所用,如有错误,敬请指正。
  • 相关阅读:
    leetcode------Rotate Array
    leetcode------Validate Binary Search Tree
    leetcode------Unique Binary Search Trees II
    [错误]集合已修改;可能无法执行枚举操作
    [转载]如何申请淘宝app_key、app_secret、SessionKey?
    [转载]JS中如何定义全局变量
    [转载]C# Double toString保留小数点方法
    jquery easyui datagrid 获取选中多行
    MongoDB { code: 18, ok: 0.0, errmsg: "auth fails" } 原因
    C# WinForm开发系列
  • 原文地址:https://www.cnblogs.com/YorkZhangYang/p/13177976.html
Copyright © 2011-2022 走看看