委托的使用

本文详细介绍了C#中委托的概念和使用,包括如何定义委托、使用匿名函数和Lambda表达式。通过实例展示了如何将方法作为参数传递,以及如何通过委托执行多方法。同时提到了Action和Func委托的使用,并给出了委托在跨窗体传值中的应用。
摘要由CSDN通过智能技术生成

可以当作指针,指向某个(某些)方法。

作用:将方法作为参数传递给另一个方法。本可以直接调用方法,但是使用委托将要执行的方法交给另一个方法来执行。

1.基本使用

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace 委托
{
    //定义委托类型,参数、返回值与被委托的方法相同
    delegate void Del(string name);
    class Program
    {
        static void Main(string[] args)
        {
            Program p = new Program();
            //将方法作为参数传入,不同参数执行不同的方法
            p.Test("张三",SayHiChinese);
        }

        public void Test(string name, Del delSayHi)
        {
            //为委托传入参数,执行委托
            delSayHi(name);
        }

        public static void SayHiChinese(string name)
        {
            Console.WriteLine(name+"用中文说:嗨");
            Console.ReadLine();
        }

        public static void SayHiEnglish(string name)
        {
            Console.WriteLine(name + "用英文说:Hi");
            Console.ReadLine();
        }
    }
}

注意:在执行委托时传入参数。

也可以不使用Test(string name, Del delSayHi)方法,直接为委托添加要执行的方法:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace 委托
{
    //定义委托类型,参数、返回值与被委托的方法相同
    delegate void Del(string name);
    class Program
    {
        static void Main(string[] args)
        {
            //为委托添加方法的两种方法
            //Del delSayHi = new Del(SayHiEnglish);
            Del delSayHi = SayHiEnglish;
            //多播委托
            delSayHi += SayHiChinese;
            //为委托传入参数,执行委托即执行所有添加的方法
            delSayHi("张三");
        }

        public void Test(string name, Del delSayHi)
        {
            //为委托传入参数,执行委托
            delSayHi(name);
        }

        public static void SayHiChinese(string name)
        {
            Console.WriteLine(name+"用中文说:嗨");
            Console.ReadLine();
        }

        public static void SayHiEnglish(string name)
        {
            Console.WriteLine(name + "用英文说:Hi");
            Console.ReadLine();
        }
    }
}

题外话:线程也是将方法作为参数传递给构造函数。

2.使用匿名函数:只是用一次

不需要定义SayHiChinese(string name)和SayHiEnglish(string name)方法,在调用时实参部分直接写一个带SayHiChinese(string name)或SayHiEnglish(string name)方法体的实参委托。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace 委托
{
    //定义委托类型,参数、返回值与被委托的方法相同
    delegate void Del(string name);
    class Program
    {
        static void Main(string[] args)
        {
            Program p = new Program();
            //匿名函数
            p.Test("张三", delegate (string name) { Console.WriteLine(name + "用中文说:嗨"); Console.ReadLine(); });
        }

        public void Test(string name, Del delSayHi)
        {
            //为委托传入参数,执行委托
            delSayHi(name);
        }

    }
}

甚至不需要定义Test(string name, Del delSayHi)方法,直接定义委托,为委托添加方法体,最后执行委托:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace 委托
{
    //定义委托类型,参数、返回值与被委托的方法相同
    delegate void Del(string name);
    class Program
    {
        static void Main(string[] args)
        {
            //匿名函数
            
            //不使用Test()方法,定义委托,为委托添加方法体
            Del delSayHi = delegate (string name)
            {
                Console.WriteLine(name + "用中文说:嗨");
                Console.ReadLine();
            };
            //传入参数,执行委托
            delSayHi("张三");
        }
    }
}

等价于:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace 委托
{
    //定义委托类型,参数、返回值与被委托的方法相同
    delegate void Del(string name);
    class Program
    {
        static void Main(string[] args)
        {
            Del delSayHi = (string name) => { Console.WriteLine(name + "用中文说:嗨"); Console.ReadLine(); };
            //传入参数,执行委托
            delSayHi("张三");
        }
    }
}

3.泛型委托

//未完待续

4.Lambda表达式

Lambda表达式是匿名函数,常用作委托,方便简洁。

Lambda表达式可以访问到外部变量。

无参数无返回值:

Del del = delegate(){};
//等价于
Del del = () =>{};

有参数无返回值:

Del del = delegate(string name){};
//等价于
Del del = (string name) =>{};

有参数有返回值:

Del del = delegate(string name){return name};
//等价于
Del del = (string name) =>{return name};

移除集合中大于4 的元素:

List<int> list = new List<int>(){1,2,3,4,5,6,7,8,9};
list.RemoveAll(n => n > 4);
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Demo
{
    class Lambda1
    {
        delegate string Del(string s);
        static void Main(string[] args)
        {
            //fun1();
            //fun2();
            //执行委托(相当于匿名方法)
            fun3("BeiJing 2013", s =>
            {
                if (s.Contains("2013"))
                {
                    s = s.Replace("2013", "2014");
                }
                return s;
            });
            Console.ReadLine();
        }

        private static void fun1()
        {
            //lambda运算符“=>” 的左边是参数列表,右边是lambda变量的方法的实现代码。
            //没有参数(),一个参数没有()直接写参数,多个参数使用(int x, string s...)
            //一行代码可省略{}
            Del myDel = n =>
            {
                string s = n + " " + "World";
                return s;
            };
            string str = myDel("Hello");
            Console.WriteLine(str);
        }

        private static void fun2()
        {
            List<string> citys = new List<string>()
            {
               "BeiJing",
               "ShangHai",
               "Tianjin",
               "GuangDong"
            };
            //查找集合中第一个长度大于7的元素
            Console.WriteLine(citys.First(c => c.Length > 7));
        }

        private static void fun3(string str, Func<string, string> func)
        {
            Console.WriteLine(func(str));
        }

    }
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Demo
{
    class Lambda2
    {
        private delegate int twoparams(int p1, int p2);
        static void Main(string[] args)
        {
            Show();
            Console.ReadLine();
        }

        static void Perform(twoparams tdel)
        {
            for (int i = 0; i < 5; i++)
            {
                for (int j = 0; j < 5; j++)
                {
                    int result = tdel(i, j);
                    Console.Write("f({0},{1})={2}", i, j, result);
                    if (j != 5)
                        Console.Write(" ,");
                }
                Console.WriteLine();
            }

        }

     
        static void Show()
        {
            twoparams test;
            test = Tdel;
            Console.WriteLine("a+b");
            Perform((p1, p2) => p1 + p2);
            Console.WriteLine("a*b");
            Perform(
                delegate (int p1, int p2) { return p1 * p2; }
                );
            Console.WriteLine("2*a*b");
            Perform(Tdel);
            Console.WriteLine("2*a*b-22222");//22222纯属为了方便区分,在IL中查看
            Perform(test);
        }

        private static int Tdel(int p1, int p2)
        {
            return p1 * p2 * 2;
        }
    }
}

这里用了4种方式来调用:
        1.Perform(((p1, p2) => p1 + p2));使用lambda表达式;
        2.Perform((delegate (int p1, int p2){ return p1* p2;}));使用匿名函数;
        3.Perform(Tdel); 给方法传递一个匹配委托的方法,似乎一个方法不是一个委托, 但因为其满足委托的签名,是可行的,编译器同样可以将其编译成一个委托实例。
        4.Perform(test); 这是这个实例中唯一一个满足方法参数的,twoparams test; 创建一个委托实例, 并给它提供一个方法test = Tdel;


5.系统内置委托类型

Action委托:可以有参数,没有返回值。只能执行无返回值的方法。

没有参数的Action委托:

//委托添加方法
Action a1 = Add;
a1 += Sub;

//执行委托的两种方法
a1();
a1.Invoke();

public void Add()
{
    int a = 10;
    int b= 20;
    Console.WriteLine("a+b=",a+b);
}

public void Sub()
{
    int a = 10;
    int b= 20;
    Console.WriteLine("a-b=",a-b);
    Console.ReadLine();
}

有参数的Action委托:
        

//委托添加方法
Action<int,int,int> a1 = Add;

//执行委托的两种方法
a1(1,2,3);
a1.Invoke(1,2,3);

public void Add(int a,int b,int c)
{
    Console.WriteLine("{1},{2},{3}",a,b,c);
}

Func<>委托:可以有参数,有返回值。<>中只有一个类型时,表示方法返回值类型;<>中只有多个类型时,表示返回值类型,最后一个表示方法返回值类型,前几个表示参数类型。

//Func委托,两个int类型的参数,一个string类型的返回值
Func<int, int, string> fun = Add;

//执行委托的两种方法
//string result = fun(1,2);
string result = fun.Invoke(1,2);

Console.WriteLine(result);
Console.ReadLine();


public static string Add(int a,int b)
{
     return (a + b).ToString();
}

6.使用委托跨窗体传值

场景:Form1中有一个Labe和button1,点击button1创建Form2。

Form2中有一个TextBox和button2,点击button2将TextBox的内容传递给Lebal。

实现方法:Form1中写一个ShowMeg方法,点击button1时,将该方法传递给Form2。

Form1中代码:

public void ShowMeg(string str)
{
    label.Text = str;
}

public void button1_Click(object o,EventArgs e)
{
    Form2 from2 = new Form2(ShowMeg);
    from2.Show();
}

Form1中有显示方法,没有值;Form2中有值,没有显示方法。

Form2中代码:

public delegate void DelTest(string str)

public class Form2:Form1
{
    //定义委托类型的引用
    public DelTest _del;
    public Form2(DelTest del)
    {
        this._del=del; //调用构造函数时给委托添加方法,即_del=ShowMeg
        initializeComponent();
    }
}

public void button2_Click(object o,EventArgs e)
{
    //执行委托,即给ShowMeg()方法传参数并执行该方法
    _del(textBox1.Text);
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值