委托
一、什么是委托?
将一个方法作为参数传递给另一个方法(参数类型为委托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 ....)。四、泛型委托
求数组的最大值。一个数组类型为数字,另一个为字符型(求长度)。利用匿名函数委托如下。
接下来就使用高大上的泛型委托,简化因类型不同的区别。把object替换为T(泛型集合Type)
<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;
}
}}
<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等于del22、del31等于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