C# 委托

妖精的绣舞 提交于 2020-03-08 09:44:01

一:为什么会有委托?

一般开发中,常见函数传参类型是int,string,char[]等,如果将一个函数作为参数,那么这个参数的类型就是委托类型。如下例:

class Program
{
	 public static void Main(string[] args)
	 {
	      Thread th = new Thread(Method); //委托类型
	      //把一个函数作为参数传递
	  }
	  static void Method()
	  {
	  }
}

应用场景如下1:

//使用委托实现功能:将list里大于3的数字移除。
public static void Main(string[] args)
{
    List<int> list = new List<int>() { 1,2,3,4,5,6,7};
    list.RemoveAll(i => i>3);
    foreach (var item in list)
    {
        Console.WriteLine(item);
    }
}  

二:如何定义委托?

定义ChineseSayHi,EnglishSayHi两个函数,入参为string类型,返回值为void类型。所以定义的委托类型SayHi也需要入参为string类型,返回值为void类型。

class Program
{
	//委托使用关键字delegate进行定义
    public delegate void SayHi(string name);

    public static void Main(string[] args)
    {
    	//函数可以直接赋值给一个委托对象,委托的签名必须跟函数的签名一样
        SayHi sayHi1 = ChineseSayHi; //SayHi sayHi1 = new SayHi(ChineseSayHi)的简化版
        sayHi1("张三"); //你好,张三
        SayHi sayHi2 = ChineseSayHi;
        sayHi2("Daming"); //Hello,Daming

    }

    static void ChineseSayHi(string name)
    {
        Console.WriteLine("你好,{0}", name);
    }

    static void EnglishSayHi(string name)
    {
        Console.WriteLine("Hello,{0}", name);
    }
}

总结:如int a,int这个类型不需要自己定义,可以直接拿来给变量a使用。如果一个方法需要作为参数使用,那么它也需要一个类型来修饰,C#并没有提供类似int,string这样的类型来修饰函数,所以需要自己定义一个委托类型,而此委托类型需要入参与返回值跟函数一致即可。

二:委托传参使用

实现将字符串数组处理成大写或者小写。如下:

class Program
{
    //将需要处理的方法定义为委托类型
    public delegate string HandleString(string str);

    public static void Main(string[] args)
    {
        String[] str = { "asdfDS", "werASDF", "asdCSD" };

        ToHandleString(str, ToLower);
        foreach (var item in str)
        {
            Console.WriteLine(item); //asdfds werasdf asdcsd
        }

        ToHandleString(str, ToUpper);

        foreach (var item in str)
        {
            Console.WriteLine(item); //ASDFDS WERASDF ASDCSD
        }
    } 

    static void ToHandleString(string[] str, HandleString handleString)
    {
        for (int i = 0; i < str.Length; i++)
        {
            str[i] = handleString(str[i]);
        }
    }

    static string ToLower(string str) //字符串转小写
    {
        return str.ToLower();
    }

    static string ToUpper(string str) //字符串转大写
    {
        return str.ToUpper();
    }
}

上述代码也可使用 Lambda表达式简化如下:

class Program
{
    //定义ToLower,ToUpper方法的委托类型
    public delegate string HandleString(string str);

    public static void Main(string[] args)
    {
        String[] str = { "asdfDS", "werASDF", "asdCSD" };

        ToHandleString(str, i=>i.ToUpper());
        // ToHandleString(str, delegate(string s) { return s.ToUpper(); }); 同上句实现结果一样

        foreach (var item in str)
        {
            Console.WriteLine(item); //asdfds werasdf asdcsd
        }

        ToHandleString(str, i=>i.ToLower());
        // ToHandleString(str, delegate(string s) { return s.ToLower(); }); 同上句实现结果一样
        foreach (var item in str)
        {
            Console.WriteLine(item); //ASDFDS WERASDF ASDCSD
        }
    } 

    static void ToHandleString(string[] str, HandleString handleString)
    {
        for (int i = 0; i < str.Length; i++)
        {
            str[i] = handleString(str[i]);
        }
    }
}

三:泛型委托

求数组的最大值:

class Program
{
    public delegate int Compare<T>(T o1, T o2);

    public static void Main(string[] args)
    {
        int[] nums = { 1, 2, 3, 4, 5 };
        var max = GetMax<int>(nums, (o1, o2) => { return o1 - o2; }); //使用匿名函数比较大小
        Console.WriteLine(max); //5
    }
    static T GetMax<T>(T[] nums, Compare<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;
    }
}

求大于5的数字:

public static void Main(string[] args)
{
    List<int> list = new List<int>{ 1, 2, 3, 4, 5, 6, 7, 8 };
    var result = list.Where(i => { return i > 5; });
    foreach (var item in result)
    {
        Console.WriteLine(item); //6,7,8
    }
}

四:多播委托

事件本质上就是封装了一个多播委托。这里,我们先了解下什么是多播委托。
多播委托:是指在一个委托中注册多个方法,在注册方法时可以在委托中使用加号运算符或者减号运算符来实现添加或撤销方法。

class Program
{
    public delegate void Test();

    public static void Main(string[] args)
    {
        Test test = Test1;
        test += Test2; //添加Test2
        test += Test3; //添加Test3
        test -= Test1; //撤销Test1
        test(); //Test2 Test3
    }
        
    static void Test1()
    {
        Console.WriteLine("Test1");
    }
    static void Test2()
    {
        Console.WriteLine("Test2");
    }
    static void Test3()
    {
        Console.WriteLine("Test3");
    }
}

五:使用委托进行窗体传值

功能描述:
在这里插入图片描述
部分代码注释:
在这里插入图片描述
在这里插入图片描述
委托总结:委托的作用就是给一个不知道将来要执行的方法来占位,可以先用一个委托变量来代替方法调用(委托的返回值,参数列表要确定)。在实际调用之前,需要为委托赋值,否则为null。
完整源码请参考:https://github.com/chanhappy/.Net.git

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!