什么是委托
通俗解释:委托就是一个能存放符合某种格式(方法签名)的方法的指针
自己理解:委托就是定义一个变量来存放方法,这个委托可以存放多个方法,在调用的时候,会按照添加的次序来执行添加的方法
对委托的理解
其实委托类似于C语言中的指针,他是一种数据类型的名字,例如int、double等,只不过,指针类型存放的是方法。委托本身就是一个类,可以写在类的里面或者类的外边,本身是一个语法糖,在编译的时候会编译成一个类。
委托的作用
因为委托是一个存放方法的数据类型,所以委托的作用如下
- 将方法作为参数
- 将方法作为返回值
- 将方法作为外部属性
使用委托
因为委托本身就是一个类,在使用的时候需一下几个步骤
- 声明委托
- 创建委托对象
- 调用委托
*委托示例
1.排序
现有一个Dog类,这个Dog类属性有 Name、Age 如下:
public class Dog { private string name; public string Name { get { return name; } set { name = value; } } private int age; public int Age { get { return age; } set { age = value; } } }
为这个Dog类创建多个对象,并存放在List的泛型中,如下:List<Dog> list = new List<Dog>(); list.Add(new Dog() { Name = "小黑", Age = 12 }); list.Add(new Dog() { Name = "小绿", Age = 2 }); list.Add(new Dog() { Name = "小白", Age = 22 }); list.Add(new Dog() { Name = "小青", Age = 34 });
需求:现在需要为这个泛型集合中的小狗狗们按照年龄进行排序,目前有两种解决方案,1.使用接口;2.使用委托;3.使用lamda表达式在List集合中,有一个排序的方法Sort(),具有4个重载,分别如下:
在这里,1,4,不进行阐述,主要讲解2,3
- public void Sort();
- public void Sort(Comparison<T> comparison);
- public void Sort(IComparer<T> comparer);
- public void Sort(int index, int count, IComparer<T> comparer);
1.使用接口进行排序。
public void Sort(IComparer<T> comparer);
这个方法就是使用接口实现对对象进行排序
讲解:
IComparer是一个接口,其接口会实现一个Compare方法,来指定排序的条件,接口定义如下:
// 摘要: // 定义类型为比较两个对象而实现的方法。 // // 类型参数: // T: // 要比较的对象的类型。 public interface IComparer<in T> { // 摘要: // 比较两个对象并返回一个值,指示一个对象是小于、等于还是大于另一个对象。 // // 参数: // x: // 要比较的第一个对象。 // // y: // 要比较的第二个对象。 // // 返回结果: // 一个带符号整数,它指示 x 与 y 的相对值,如下表所示。值含义小于零x 小于 y。零x 等于 y。大于零x 大于 y。 int Compare(T x, T y); }
那么,在使用接口的时候,我们要定义一个类CompareDog,来继承这个接口,并且设定排序的条件是按照对象中的年龄属性进行排序的,代码如下:public class CompareDog:IComparer<Dog> { public int Compare(Dog x, Dog y) { return x.Age - y.Age; } }
这样的话,我们就可以使用Sort(IComparer<T> comparer)这个方法来对集合进行排序了,这里的参数就是我们上边定义的CompareDog类,它实现了IComparer接口。list.Sort(new CompareDog());//这样既实现了对集合的排序
2.使用委托排序
public void Sort(Comparison<T> comparison);这个方法就是使用委托对集合进行排序讲解:Comparison其实就是一个委托类型,定义如下:// 摘要: // 表示比较同一类型的两个对象的方法。 // // 参数: // x: // 要比较的第一个对象。 // // y: // 要比较的第二个对象。 // // 类型参数: // T: // 要比较的对象的类型。 // // 返回结果: // 一个有符号整数,它指示 x 与 y 的相对值,如下表所示。值含义小于 0x 小于 y。0x 等于 y。大于 0x 大于 y。 public delegate int Comparison<in T>(T x, T y);
既然是委托类型的参数,那么我们就要写一个符合该委托的方法,并指定排序的条件,代码如下:int Comparison(Dog x, Dog y) { return x.Age - y.Age; }
这样,我们在排序的时候,只需要将上边的这个方法传入作为参数即可:list.Sort(Comparison);3.使用lamda表达式排序
其实,lamda表达式的本质就是一个委托,只不过微软把它变成了语法糖,方便程序员的使用,这里不多阐述,代码如下即可实现:list.Sort((x,y)=>x.Age-y.Age);
2.求最大值
要求:有一个int型的数组,求其中的最大值我们先按照常规的思想来做,然后在使用委托实现。
int[] arrInt = new int[5] { 1,3,8,4,2};
常规思想:定义一个方法,传入这个数组作为参数,然后循环遍历该数组,取出最大值,方法如下:
int MaxInt(int[] arr) { int maxInt = arr[0]; for (int i = 1; i < arr.Length; i++) { if (maxInt < arr[i]) { maxInt = arr[i]; } } return maxInt; }
调用:int[] arrInt = new int[5] { 1,3,8,4,2}; int max = MaxInt(arrInt);
注:以上自定义的方法可以实现求int型数据的最大值,那么如果求double型的最大值?string类型的字符串长度?对象中按照指定的属性求最大值? 这样的话就得针对每一种情况都要写一个方法,从逻辑上是可以实现的,但是使用委托会是一种更好的方法。
委托实现
定义一个泛型方法,传入数组作为参数,同时传入Comparison<T>类型作为比较的委托,这个委托在上边已经讲解过,代码如下:
T MaxValue<T>(T[] arr,Comparison<T> func) { T maxInt = arr[0]; for (int i = 1; i < arr.Length; i++) { //使用委托来比较 if (func(maxInt, arr[i]) < 0) { maxInt = arr[i]; } } return maxInt; }
调用:这里的委托方法参数使用lamda表达式表示//求最大数 int[] arrInt = new int[5] { 1,3,8,4,2}; int max = MaxValue<int>(arrInt, (x, y) => x - y); //求字符串长度最大的字符串 string[] arrStr = new string[] { "aa","fcc","tgtgc"}; string maxLenght = MaxValue<string>(arrStr, (x, y) => x.Length - y.Length); //按照年龄,求对象集合中年龄最大的对象 Dog[] dogs = new Dog[] { new Dog() { Name = "小黑", Age = 12 }, new Dog() { Name = "小lv", Age = 2 }, new Dog() { Name = "小bai", Age = 62 }, new Dog() { Name = "小qing", Age = 22 } }; Dog maxDog = MaxValue<Dog>(dogs, (x, y) => x.Age - y.Age);
不喜勿喷,欢迎评论!