委托、lamda表达式..委托概念-匿名函数-泛型委托-Lamda表达式-多播委托

本文详细解释了C#中委托的概念及其在函数重用和多播调用中的应用,同时介绍了Lambda表达式的使用方法,通过具体示例展示了如何在实际编程中灵活运用这些高级特性。

委托

一、什么是委托?

  将一个方法作为参数传递给另一个方法(参数类型为委托delegate)。
  声明一个委托类型。
  委托所指向的函数必须跟委托具有相同的的签名(参数个数、参数类型、返回值一样)。

二、基本的委托

  先看下面的代码,一种中文的问候方法还有种英文的问候方法,明显它们两个签名相同但函数名不同所以不能重载重载,当输入name时需要判断需要要调用那个函数。
</pre><pre name="code" class="csharp">namespace 基本的委托
{
    //声明一个委托指向一个函数
    public delegate void DelSayHi(string name);
    class Program
    {
        static void Main(string[] args)
        {
           
        }

        public static void SayHiChinese(string name)
        {
            Console.WriteLine("吃了么?" + name);
        }
        public static void SayHiEnglish(string name)
        {
            Console.WriteLine("Nice to meet you" + name);
        }
    }
}

  接下来来看看委托的方法。
namespace 基本的委托
{
    //声明一个委托指向一个函数
    public delegate void DelSayHi(string name);
    class Program
    {
        static void Main(string[] args)
        {
            //DelSayHi del = SayHiEnglish;//new DelSayHi(SayHiEnglish);定义一个对象
            //del("张三");
            //Console.ReadKey(); //方法一

            Test("张三", SayHiChinese);
            Test("李四", SayHiEnglish);
            Console.ReadKey();//方法二
        }

        public static void Test(string name,DelSayHi del)//将委托对象(方法)作为一个参数
        { 
            //调用
            del(name);
        }

        public static void SayHiChinese(string name)
        {
            Console.WriteLine("吃了么?" + name);
        }
        public static void SayHiEnglish(string name)
        {
            Console.WriteLine("Nice to meet you" + name);
        }
    }
}

  声明一个委托类型的函数(签名与要调用的函数相同)
  DelSayHi del = SayHiEnglish; 或DelSayHi del =new DelSayHi(SayHiEnglish);   这两种方法相同目的是实例化DelSayHi创建一个委托对象指向一个,将委托的方法赋给del。运行后结果为Nice to meet you 张三。

三、匿名函数

 3.1 匿名函数:有方法名没函数名的函数。
  可以将上一个列子中方法二的主函数简化,改为
static void Main(string[] args)
        {
            DelSayHi del = delegate(string name)
            {
                Console.WriteLine("你好" + name);
            };
            del("张三");
            Console.ReadKey();//方法二
        }
  这时就可以把下面主函数定义的Text()、SayHiChainses()和SayHiEnglish()给删了。注意:匿名函数的签名也要和委托一样。当委托有返回值时,匿名函数也要有返回值。

  3.2接下来来看看Lamda表达式(简写版的匿名函数)
  static void Main(string[] args)
        {
            //lamda表达式    => :goes to
            DelSayHi del = (string name) => { Console.WriteLine("你好" + name); };
            del("张三");
            Console.ReadKey();
        }
  (string name):参数(当参数个数为0时,直接写“()”)。=> :goes to 。 { Console.WriteLine("你好" + name); }  :方法体(有返回值就加return  ....)。

四、泛型委托

  求数组的最大值。一个数组类型为数字,另一个为字符型(求长度)。利用匿名函数委托如下。
<pre name="code" class="csharp">
public delegate int DelCompare(object o1, object o2);
    class Program
    {
        static void Main(string[] args)
        {
            //用匿名
            object[] o = {"abc","fdsfdsds","fdsfdsfdsfdsfdsfds","fdsfds"};
            //object result = GetMax(o, Compare2);
            //object result = GetMax(o, delegate(object o1, object o2) {
            //    string s1 = (string)o1;
            //    string s2 = (string)o2;
            //    return s1.Length - s2.Length;
            //});

            //用lamda
            object result = GetMax(o, (object o1, object o2) =>
            {
                string s1 = (string)o1;
                string s2 = (string)o2;
                return s1.Length - s2.Length;
            });

            object[] oo = { 1,2,3,4,5,6,7,8,9};
            object result1 = GetMax(oo, (object o1,object o2) => {
                int s1 = (int)o1;
                int s2 = (int)o2;
                return s1 - s2;
            });
            Console.WriteLine(result);
            Console.WriteLine(result1);
            Console.ReadKey();
        }

        public static object GetMax(object[] nums, DelCompare del)
        {
            object max = nums[0];
            for (int i = 0; i < nums.Length; i++)
            {
                //要传一个比较的方法
                if (del(max, nums[i]) < 0)
                {
                    max = nums[i];
                }
            }
            return max;
        }
}}

  接下来就使用高大上的泛型委托,简化因类型不同的区别。把object替换为T(泛型集合Type)
   <span style="font-family: Arial, Helvetica, sans-serif; font-size: 12px;"> public delegate int DelCompare<T>(T t1, T t2);</span>
// public delegate int DelCompare(object o1, object o2);
    class Program
    {
        static void Main(string[] args)
        {
            int[] nums = { 1, 2, 3, 4, 5 };
            int max = GetMax<int>(nums, Compare1);
            Console.WriteLine(max);

            string[] names = { "abcdefg", "fdsfds", "fdsfdsfdsfdsfdsfdsfdsfsd" };
            string max1 = GetMax<string>(names, (string s1, string s2) =>
            {
                return s1.Length - s2.Length;
            });
            Console.WriteLine(max1);
            Console.ReadKey();
        }
        public static T GetMax<T>(T[] nums, DelCompare<T> del)
        {
            T max = nums[0];
            for (int i = 0; i < nums.Length; i++)
            {
                //要传一个比较的方法
                if (del(max, nums[i]) < 0)
                {
                    max = nums[i];
                }
            }
            return max;
        }


        public static int Compare1(int n1, int n2)
        {
            return n1 - n2;
        }
    }
}

                        
如图:当调用用T定义的函数GetMax<T>时,只要把T改为string后面的T也变成了string型了。所以这个可以解决因参数类型不同但函数方法相同的调用问题。
这样大大的简化了代码。

五、Lamda表达式

  首先来看看Lamda表达式和委托的关系:
 从委托类中定义出几个对象。
    public delegate void DelOne();
    public delegate void DelTwo(string name);
    public delegate string DelThree(string name);
    class Program
    {
        static void Main(string[] args)
        {
            DelOne del11 =delegate() { };// 没参数,没返回值
            DelOne del12 = () => { };

            DelTwo del21=delegate(string name) { };//有参数,没返回值
            DelTwo del22 = (string name) => { };

            DelThree del31 = delegate(string name) { return name; };//有参数,有返回值
            DelThree del32 = (string name) => { return name; };
         }
     }
 从上面的代码中可以看出来del11等于del12、del21等于del22del31等于del32。即Lamda表达式时匿名委托的另一种表达形式。
实例:
从数据1,2,3,4,5,6,7,8,9中移除后五行。
List<int> list = new List<int>() { 1, 2, 3, 4, 5, 6, 7, 8, 9 };
            list.RemoveAll(n => n > 4);
            foreach (var item in list)
            {
                Console.WriteLine(item);
            }
            Console.ReadKey();

六、多播委托

namespace 多播委托
{
    public delegate void DelTest();//指向4个签名相同的函数
    class Program
    {

        static void Main(string[] args)
        {
            DelTest del = T1;// 委托指向T1
            del += T2;// 委托指向T2
            del += T3;
            del += T4;
            del -= T3;
            del -= T1;
            //委托不只指向一个委托还可以指向多个函数
            del();
            Console.ReadKey();
        }

        public static void T1()
        {
            Console.WriteLine("我是T1");
        }
        public static void T2()
        {
            Console.WriteLine("我是T2");
        }

        public static void T3()
        {
            Console.WriteLine("我是T3");
        }
        public static void T4()
        {
            Console.WriteLine("我是T4");
        }
    }
}


  运行结果为:
  我是T2
  我是T4





  



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值