1.为什么使用委托
举一个操作字符串的例子,现在有三个需求:
1.将一个字符串每个元素都转换成大写
2.将一个字符串中的每个元素都转换成小写
3.将一个字符串中的每个元素都 加上双引号
传统的做法是将这三个需求分别写成3个方法,然后利用switch case 来响应客户的具体的一个需求
string[] strs = {"abcdefG","HIJKnopP"};
switch (way)
{
case "Upper":
ProStToUpper(names);
break;
case "Lower":
ProStToLower(names);
break;
default:
ProStrSYH(names);
break;
}
public static void ProStToUpper(string[] name)
{
for (int i = 0; i < name.Length; i++)
{
name[i] = name[i].ToUpper();
}
}
public static void ProStToLower(string[] name)
{
for (int i = 0; i < name.Length; i++)
{
name[i] = name[i].ToLower();
}
}
public static void ProStrSYH(string[] name)
{
for (int i = 0; i < name.Length; i++)
{
name[i] = "\"" + name[i]+"\"";
}
}
现在我们换一种思路,把方法作为参数传递给另一个方法,听着是不是很奇怪,来我们来看代码实现
public static string[] strs = { "abcdefG", "HIJKnopP" };
//声明委托指向一个函数
public delegate void DelProStTo(string[] name);
public static void Main(string[] args)
{
DelProStTo del = new DelProStTo(ProStToUpper);
del(strs);
Text("To", del);
Console.ReadKey();
}
public static void Text(string name, DelProStTo del)
{
del(strs);
}
public static void ProStToUpper(string[] name)
{
for (int i = 0; i < name.Length; i++)
{
name[i] = name[i].ToUpper();
}
}
public static void ProStToLower(string[] name)
{
for (int i = 0; i < name.Length; i++)
{
name[i] = name[i].ToLower();
}
}
public static void ProStrSYH(string[] name)
{
for (int i = 0; i < name.Length; i++)
{
name[i] = "\"" + name[i]+"\"";
}
}
还有一种更加简便的写法:直接将方法名赋值给委托类型也是可以的。
DelProStTo del = ProStToUpper;
2.委托的概念
声明一个委托类型
委托所指向的函数必须跟委托具有相同的签名
我们来看以下两个函数
左边的是求int类型的数组的最大值,右边求得是string类型的数组的字符串最多的那个字符串,他们两个函数其它地方都是一样的,就是比较的条件不一样。
那我们可以将两个函数合并成一个函数,然后不同的地方(比较的方法)写成一个委托,要谁,逮谁就完事。
是int 类型的比较还是string类型的比较,主函数调就完事
这样可以使得代码更具有条理性,以便于后期的维护和管理,你想那,要是后期有需求变更了,我只需要改动一个地方和增加一个比较条件的方法即可,就不用再重复写一样的方法,方便的很,但是这样写,依旧没有减少代码量,依旧没有解放程序员的双手,于是又有了一种更好的方式,它就是泛型委托。
3.匿名函数
public delegate void DelSay(string name);
public static void Main(string[] args)
{
//第一种写法
SayHi("阿彪", SayHiChinese);
//第二种写法
DelSay del = delegate(string name){
Console.WriteLine("你好"+name);
}
Console.ReadKey();
}
public static void SayHi(string name, DelSay del )
{
del(name);
}
public static void SayHiChinese(string name)
{
Console.WriteLine("你好"+name);
}//用第二种方法写,这里就得干掉。
public static void SayHiEnglish(string name)
{
Console.WriteLine("Hello"+name);
}
4.泛型委托
讲泛型委托之前,来说说泛型的思想:延迟声明,即定义时没有具体指定参数类型,把参数类型的声明推迟到了调用的时候才指定参数类型。
泛型是如何工作的?
控制台程序最终会编译成一个exe程序,exe被点击的时候,会经过JIT(即时编译器)的编译,最终生成二进制代码,才能被计算机执行。泛型加入到语法以后,VS自带的编译器又做了升级,升级之后编译时遇到泛型,会做特殊的处理:生成占位符。再次经过JIT编译的时候,会把上面编译生成的占位符替换成具体的数据类型。说白了,就是给你占个位置,等真正调用时,给你就是。
泛型方法
泛型委托
public delegate int DelCompare<T>(T t1,T t2);
具体比较的方法
调用
使用泛型可以避免object转到任意类型时发生的拆箱、装箱。可以大大提升性能。
5.lamda表达式
List<int> list = new List<int>() { 1, 2, 3, 4, 5 };
list.RemoveAll(x => x >= 3);//x表示这个集合中的所有数,=>后面表示条件。