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

posted @ 2020-06-24 16:16  YorkShare  阅读(287)  评论(1编辑  收藏  举报