C# 委托和事件高级进阶
本篇文章主要采用理论和代码实例相结合方式来论述委托和事件,涉及到一些边界技术,如软件架构的OCP原则(开-闭原则),
软件架构解耦,设计模式(Sender-Order)和事件驱动模型,有一定难度和深度,不适合初级者。
第一部份 委托
关于委托内容,主要围绕下图来论述。
一 委托是什么(what)
(一)委托产生的背景之一
1.我们先来假设这样一个情景需求:
设计一个系统,使其满足如下条件:
(1)当前,只有中国人和英国人使用该系统;
(2)向系统输入用户名和相应的语言,将产生相应语言的问候语;
(3)后期,可能会有其他国家语言加入该系统(系统变化的部分) ;
2.技术方案实现
关于技术方案实现,我们可以采用下图中的三种方式之一。
为了更好地叙述委托,我们分别实现三种技术方案,并找出它们的关系。
2.1 一般实现
Code(控制台程序)
1 using System;
2
3 namespace DelegateDemo
4 {
5 class Program
6 {
7 static void Main(string[] args)
8 {
9 Console.WriteLine(GetGreetingContens("小王", "Chinese"));
10 Console.WriteLine(GetGreetingContens("Alan_beijing", "English"));
11 Console.WriteLine(GetGreetingContens("Linda", "Russian"));
12 Console.Read();
13 }
14
15 //根据用户名和语言,获取问候语
16 public static string GetGreetingContens(string UserName, string Language)
17 {
18 //New 一个GreetToUsers对象
19 GreetToUsers greetToUsers = new GreetToUsers();
20 //当然,你也可以使用switch开发语句来代替如下的if......else......
21 if (Language == "Chinese")
22 {
23 return greetToUsers.ChinesePeople(UserName);
24 }
25 else if (Language == "English")
26 {
27 return greetToUsers.EnglishPeople(UserName);
28 }
29 else
30 {
31 return "抱歉,当前系统只支持汉语与英语(Sorry, the current system only supports Chinese and English.)";
32 }
33 }
34 }
35
36
37
38 //定义基本问候类和方法
39 public class GreetToUsers
40 {
41 //Chinese People
42 public string ChinesePeople(string UserName)
43 {
44 string GreetContents = "您好!" + UserName;
45 return GreetContents;
46 }
47
48 //English People
49 public string EnglishPeople(string UserName)
50 {
51 string GreetContents = "Hello," + UserName + "!";
52 return GreetContents;
53 }
54 }
55
56 }
Result
分析
2.2用接口实现
如上,我们分析了方案一中的问题,为了更好地解决方案一存在的问题,我们采用面向接口编程的形式来实现。
2.2.1 什么是面向接口编程?
面向接口编程,主要是解决软件架构设计中“动静问题”,即封装不变(静),剥离变化(抽出变化)。
Code:
1 using System;
2
3 namespace DelegateDemo
4 {
5 class Program
6 {
7 static void Main(string[] args)
8 {
9 GreetToChineseUsers greetToChinesUsers = new GreetToChineseUsers();
10 GreetToEnglishUsers greetToEnglishUsers = new GreetToEnglishUsers();
11 GreetToOtherUsers greetToOtherUsers = new GreetToOtherUsers();
12 //Chinse Users
13 IGreetToUsers iGreetToChineseUsers = greetToChinesUsers;
14 Console.WriteLine(iGreetToChineseUsers.CountryPeople("小王", "Chinese"));
15 //English Users
16 IGreetToUsers iGreetToEnglishUsers = greetToEnglishUsers;
17 Console.WriteLine(iGreetToEnglishUsers.CountryPeople("Alan_beijing", "English"));
18 //Other Users
19 IGreetToUsers iGreetToOtherUsers = greetToOtherUsers;
20 Console.WriteLine(iGreetToOtherUsers.CountryPeople("Linda", "Russian"));
21
22 Console.Read();
23 }
24
25
26 }
27
28 //系统输出问候语(变化的部分,语言为变化因子)
29 public interface IGreetToUsers
30 {
31 string CountryPeople(string UserName,string Language);
32 }
33
34
35 //汉语用户类
36 public class GreetToChineseUsers:IGreetToUsers
37 {
38 //Chinese People
39 public string CountryPeople(string UserName, string Language)
40 {
41 string GreetContents = "您好!" + UserName;
42 return GreetContents;
43 }
44 }
45
46 //英语用户类
47 public class GreetToEnglishUsers : IGreetToUsers
48 {
49 //English People
50 public string CountryPeople(string UserName, string Language)
51 {
52 string GreetContents = "Hello," + UserName + "!";
53 return GreetContents;
54 }
55 }
56
57 //其他用户类
58 public class GreetToOtherUsers : IGreetToUsers
59 {
60 //English People
61 public string CountryPeople(string UserName, string Language)
62 {
63 return "Sorrry,当前系统只支持汉语与英语";
64 }
65 }
66
67 }
result
分析:
(1)如上,我们将变化因子"语言"剥离出来,形成接口,以后只要每增加一个语言,只需实现接口即可,满足了OCP原则,基本解决了方案一中存在的问题;
(2)如上代码只是为了演示面向接口编程这个功能,并不完善,感兴趣的读者,可自行完善(如将语言定义为枚举类型等);
方案二中的代码,细心的读者会发现,Main方法中new了三个对象,假若以后系统有300门语言,那岂不New 300个类,这样的话,也不利于代码维护呀,怎么解决这个问题呢?(提示一下,采用设计模式抽象工厂即可解决该问题)
2.3 用委托实现
在这里,没接触过委托的读者,先跳过这部分,往下读,看完(三)怎样使用委托(How to use)后,再来看本部分。
Code
1 using System;
2
3 namespace DelegateDemo
4 {
5 class Program
6 {
7 static void Main(string[] args)
8 {
9 //根据语言判断,传递哪个方法的参数
10 Console.WriteLine("------------请输入用户名------------");
11 string UserName = Console.ReadLine();
12 Console.WriteLine("------------请输入语言------------");
13 string Language = Console.ReadLine();
14 Console.WriteLine("------------输出结果------------");
15 GreetToUsers greetToUsers = new GreetToUsers();
16 if (Language == "Chinese")
17 {
18 Console.WriteLine(GetGreetingContents(UserName, greetToUsers.ChinesePeople));
19 }
20 else if (Language == "English")
21 {
22 Console.WriteLine(GetGreetingContents(UserName, greetToUsers.EnglishPeople));
23 }
24 else
25 {
26 Console.WriteLine(GetGreetingContents(UserName, greetToUsers.OtherPeople));
27 }
28 Console.Read();
29 }
30
31
32
33 public static string GetGreetingContents(string UserName,DelegateGetGreeting delegateGetGreeting)
34 {
35 return delegateGetGreeting(UserName);
36 }
37 }
38
39 //定义委托
40 public delegate string DelegateGetGreeting(string UserName);
41
42
43 //定义基本问候类和方法
44 public class GreetToUsers
45 {
46 //Chinese People
47 public string ChinesePeople(string UserName)
48 {
49 string GreetContents = "您好!" + UserName;
50 return GreetContents;
51 }
52
53 //English People
54 public string EnglishPeople(string UserName)
55 {
56 string GreetContents = "Hello," + UserName + "!";
57 return GreetContents;
58 }
59 //非英非汉
60 public string OtherPeople(string UserName)
61 {
62 return "Sorrry,当前系统只支持汉语与英语";
63 }
64 }
65
66 }
Result
2.3 分析上述三种实现方案的关系
通过上诉三种方式的比较,我们容易得出委托的如下结论:
(1)抽象方法,屏蔽方法细节,调用只需传递方法名字即可;
(2)能够实现程序的解耦,松耦合(在方案一中,GetGreetingContens方法体内new了GreetToUsers对象,强耦合)
(3)委托一般扮演中间者的角色,这功能在委托事件中体现非常明显(第二部分 事件 将详细论述)
如我们在租房子时,可以直接找房东(技术实现的一般方法,强耦合,让租房者和房东直接联系),也可找中介(技术实现的委托,松耦合,租房者通过中介来与房东联系)
2.4 委托背景概述
委托的重要产生背景,就是事件驱动模型(关于什么是事件和事件驱动,在本文第二部份 事件 论述)。
(二) 委托定义
用delegate关键字定义委托(注意,委托是没有方法体的,类似接口里面的方法),在定义委托前,必须明确两个问题:
1.委托将要绑定的方法;
2.委托的形参类型,形参个数和委托的返回值必须与将要绑定的方法的形参类型,形参个数和返回值一致;
(三)相关概念
委托涉及的相关概念有函数指针,类型安全性、事件、Lambda表达式等
1.函数指针:在C++中,指针的一个类别,主要指向函数(变量指针,主要指向变量地址),可以把C#中的委托理解为函数指针;
2.类型安全性:在C++中,我们都知道指针是类型不安全的(返回值,返回类型和什么时候返回,这些都是未知的),而委托是类型安全的;
3.事件:可以把事件理解为委托的一种特例(在本文第二部份 事件 论述)
4.Lambda表达式:委托与Lambd表达式相结合,实现高效编程,与Jquery的“较少代码做更多的事”类似,委托与Lambda,Linq相结合,使较短代码就能实现比较复杂的功能(在本篇文章中不讲解Lambda与Lambda树,将在后续文章中讲解)
(四)委托组成
大致分为两部分:声明委托和注册方法(也叫绑定方法)
1.声明委托
用delegate声明;
2.绑定方法
绑定具体方法,传递方法名称;
(五) 委托种类
委托种类,一般分为多播委托和单播委托
1.单播委托:绑定单个方法
2.绑定多个方法
(六) 委托操作
1.绑定方法
2.解绑方法
二 委托能解决什么问题(Can do)
1.避免核心方法中存在大量的if....else....语句(或swich开关语句);
2.满足程序设计的OCP原则;
3.使程序具有扩展性;
4.绑定事件;
5.结合Lambda表达式,简化代码,高效编程;
6.实现程序的松耦合(解耦),这个在事件(event)中体现比较明显;
三 怎么使用委托(How to use)(本篇文章不谈匿名委托,匿名委托具体内容,将在Lambda章节讲解)
(一)委托的基本构成
通常地,使用委托的步骤与使用类的步骤是一样的。大致分为两步:定义委托和绑定方法(传递方法)
1.定义委托
用delegate关键字定义委托(注意,委托是没有方法体的,类似接口里面的方法),在定义委托前,必须明确两个问题:
(1).委托将要绑定的方法;
(2).委托的形参类型,形参个数和委托的返回值必须与将要绑定的方法的形参类型,形参个数和返回值一致;
public delegate 委托返回类型 委托名(形参)
例子:如上我们委托将要表示系统输出的问候语
a.委托将要绑定的方法
public string ChinesePeople(string UserName)
{
string GreetContents = "您好!" + UserName;
return GreetContents;
} //English People
public string EnglishPeople(string UserName)
{
string GreetContents = "Hello," + UserName + "!";
return GreetContents;
}
//非英非汉
public string OtherPeople(string UserName)
{
return "Sorrry,当前系统只支持汉语与英语";
}
b.由如上方法可看出,方法的返回类型为string,方法有一个string类型的形参,在定义委托时,与其保持一致即可
//定义委托
public delegate string DelegateGetGreeting(string UserName);
2.绑定方法
使用委托时,将方法名字作为参数传递给委托即可
1 GreetToUsers greetToUsers = new GreetToUsers();
2 GetGreetingContents(UserName, greetToUsers.ChinesePeople)
(二)委托绑定方法
1.绑定单个方法
绑定单个方法,将单个方法名字传给委托即可
1 static void Main(string[] args)
2 {
3 //根据语言判断,传递哪个方法的参数
4 Console.WriteLine("------------请输入用户名------------");
5 string UserName = Console.ReadLine();
6 Console.WriteLine("------------请输入语言------------");
7 string Language = Console.ReadLine();
8 Console.WriteLine("------------输出结果------------");
9 GreetToUsers greetToUsers = new GreetToUsers();
10 DelegateGetGreeting DGG;
11 if (Language == "Chinese")
12 {
13 //绑定单个方法
14 DGG = greetToUsers.ChinesePeople;
15 Console.WriteLine(GetGreetingContents(UserName, DGG));
16 }
17 else if (Language == "English")
18 {
19 DGG = greetToUsers.EnglishPeople;
20 Console.WriteLine(GetGreetingContents(UserName, DGG));
21 }
22 else
23 {
24 DGG = greetToUsers.OtherPeople;
25 Console.WriteLine(GetGreetingContents(UserName, DGG));
26 }
27
28 Console.Read();
29 }
另一种不太规范写法:不用GetGreetingContents(string UserName,DelegateGetGreeting delegateGetGreeting)方法
1 static void Main(string[] args)
2 {
3 //根据语言判断,传递哪个方法的参数
4 Console.WriteLine("------------请输入用户名------------");
5 string UserName = Console.ReadLine();
6 Console.WriteLine("------------请输入语言------------");
7 string Language = Console.ReadLine();
8 Console.WriteLine("------------输出结果------------");
9 GreetToUsers greetToUsers = new GreetToUsers();
10 DelegateGetGreeting DGG;
11 if (Language == "Chinese")
12 {
13 //绑定单个方法
14 DGG = greetToUsers.ChinesePeople;
15 Console.WriteLine(DGG(UserName));
16 }
17 else if (Language == "English")
18 {
19 DGG = greetToUsers.EnglishPeople;
20 Console.WriteLine(DGG(UserName));
21 }
22 else
23 {
24 DGG = greetToUsers.OtherPeople;
25 Console.WriteLine(DGG(UserName));
26 }
27
28 Console.Read();
29 }
之所以不规范,主要是在项目中,不利于代码的模块化。
2.绑定多个方法(多播委托)
注意:绑定多个方法时,委托范围类型必须为void类型,否则只返回最后一个绑定的值。
绑定多个方法,采用 += 绑定
1 using System;
2
3 namespace DelegateDemo
4 {
5 class Program
6 {
7 static void Main(string[] args)
8 {
9
10 GreetToUsers greetToUsers = new GreetToUsers();
11 DelegateGetGreeting DGG;
12
13 //绑定多个方法
14 DGG = greetToUsers.ChinesePeople;
15 DGG += greetToUsers.EnglishPeople;
16 DGG("小王");
17
18 Console.Read();
19 }
20
21
22 }
23
24 //定义委托
25 public delegate void DelegateGetGreeting(string UserName);
26
27
28 //定义基本问候类和方法
29 public class GreetToUsers
30 {
31 //Chinese People
32 public void ChinesePeople(string UserName)
33 {
34 string GreetContents = "您好!" + UserName;
35 Console.WriteLine(GreetContents);
36 }
37
38 //English People
39 public void EnglishPeople(string UserName)
40 {
41 string GreetContents = "Hello," + UserName + "!";
42 Console.WriteLine(GreetContents);
43 }
44 //非英非汉
45 public void OtherPeople(string UserName)
46 {
47 Console.WriteLine("Sorrry,当前系统只支持汉语与英语");
48 }
49 }
50
51 }
52
53
54
3.解绑方法
解载绑定的方法,采用 -= 解绑
1 using System;
2
3 namespace DelegateDemo
4 {
5 class Program
6 {
7 static void Main(string[] args)
8 {
9
10 GreetToUsers greetToUsers = new GreetToUsers();
11 DelegateGetGreeting DGG;
12
13 //绑定多个方法
14 DGG = greetToUsers.ChinesePeople;
15 DGG += greetToUsers.EnglishPeople;
16
17 //解绑ChinesePeople方法
18 DGG-= greetToUsers.ChinesePeople;
19 DGG("小王");
20
21 Console.Read();
22 }
23
24
25 }
26
27 //定义委托
28 public delegate void DelegateGetGreeting(string UserName);
29
30
31 //定义基本问候类和方法
32 public class GreetToUsers
33 {
34 //Chinese People
35 public void ChinesePeople(string UserName)
36 {
37 string GreetContents = "您好!" + UserName;
38 Console.WriteLine(GreetContents);
39 }
40
41 //English People
42 public void EnglishPeople(string UserName)
43 {
44 string GreetContents = "Hello," + UserName + "!";
45 Console.WriteLine(GreetContents);
46 }
47 //非英非汉
48 public void OtherPeople(string UserName)
49 {
50 Console.WriteLine("Sorrry,当前系统只支持汉语与英语");
51 }
52 }
53
54 }
(三)委托机制
将如下代码通过反汇编工具.NET Reflector反汇编
1 using System;
2
3 namespace DelegateDemo
4 {
5 class Program
6 {
7 static void Main(string[] args)
8 {
9
10 GreetToUsers GTU = new GreetToUsers();
11
12 DelegateGreet DG = new DelegateGreet();
13
14 //DG.delegateGetGreeting = GTU.ChinesePeople;//注册方法
15 DG.delegateGetGreeting += GTU.ChinesePeople;
16 DG.delegateGetGreeting += GTU.EnglishPeople;
17 DG.GreetUser("小王");
18
19 Console.Read();
20 }
21 }
22
23 public class DelegateGreet
24 {
25 //声明委托
26 public delegate void DelegateGetGreeting(string UserName);
27
28 //委托变量为public,破坏了类的封装性
29 public DelegateGetGreeting delegateGetGreeting;
30
31 //虽然Event论定义为public,但其还是私有变量,只能通过+=,或-=访问
32 //public event DelegateGetGreeting EventGreet;
33
34 public void GreetUser(string UserName)
35 {
36 //EventGreet?.Invoke(UserName);
37 delegateGetGreeting(UserName);
38 }
39 }
40
41 //定义基本问候类和方法
42 public class GreetToUsers
43 {
44 //Chinese People
45 public void ChinesePeople(string UserName)
46 {
47 string GreetContents = "您好!" + UserName;
48 Console.WriteLine(GreetContents);
49 }
50
51 //English People
52 public void EnglishPeople(string UserName)
53 {
54 string GreetContents = "Hello," + UserName + "!";
55 Console.WriteLine(GreetContents);
56 }
57 //非英非汉
58 public void OtherPeople(string UserName)
59 {
60 Console.WriteLine("Sorrry,当前系统只支持汉语与英语");
61 }
62 }
63 }
64
65
反汇编
分析:
1.三个核心方法:BeginInvoke,EndInvoke和Invoke
(1)使用Invoke完成一个委托方法的封送,就类似于使用SendMessage方法来给界面线程发送消息,是一个同步方法。也就是说在Invoke封送的方法被执行完毕前,Invoke方法不会返回,从而调用者线程将被阻塞。
(2使用BeginInvoke方法封送一个委托方法,类似于使用PostMessage进行通信,这是一个异步方法。也就是该方法封送完毕后马上返回,不会等待委托方法的执行结束,调用者线程将不会被阻塞。但是调用者也
可以使用EndInvoke方法或者其它类似WaitHandle机制等待异步操作的完成。
总结:但是在内部实现上,Invoke和BeginInvoke都是用了PostMessage方法,从而避免了SendMessage带来的问题。而Invoke方法的同步阻塞是靠WaitHandle机制来完成的。
提示:
最近浏览一篇文章,也讲得不错:http://blog.csdn.net/goodshot/article/details/6157529
要想深入了解,请参照《CLR Via C#》,
第二部分 事件
关于事件(event),将会从如下四个角度来分析.
1.什么是事件
2.事件能解决什么问题
3.怎么使用事件
4.事件机制
一 什么是事件
谈到委托,必提事件,事件本质是对委托的封装,对外提供add_EventName(对应+=)和remove_EventName(对应-=)访问,从而实现类的封装性。
1.种类
强类型事件和弱类型事件
2.一些用处
(1)WebForm控件的Click事件。做过WebForm开发的朋友,可能对事件是非常熟悉的,如拖一个Button,双击,就自动在后台生成Button的Click事件,如下图所示。
原理:在Windows运用程序中,Button类提供了Click事件,其本质就是委托,当我们触发Click事件时,调用的处理程序方法需要参数,其参数就是由委托类型来定义的。
(2)设计模式发布/订阅。事件是基于委托的,为委托提供了一种发布/订阅机制。
二 事件能解决哪些问题
1.将公有的委托变量定义为私有变量,从而满足类的封装性原则;
2.具有委托具有的作用;
三 如何使用事件
1.声明委托
public delegate void DelegateGetGreeting(string UserName);
2.声明事件
与委托声明一样,只不过多了一个关键字event
public event DelegateGetGreeting EventGreet;
3.时间注册方法
事件注册方法与委托注册方法是一样的。
1 DelegateGreet DG= new DelegateGreet();
2 //DG.delegateGetGreeting = GTU.ChinesePeople;//注册方法
3 DG.EventGreet+= GTU.ChinesePeople;
4 DG.EventGreet += GTU.EnglishPeople;
4.调用事件
调用定义事件的方法
DG.GreetUser("小王");
完整代码如下:
1 using System;
2
3 namespace DelegateDemo
4 {
5 class Program
6 {
7 static void Main(string[] args)
8 {
9
10 GreetToUsers GTU = new GreetToUsers();
11
12 DelegateGreet DG= new DelegateGreet();
13
14 //DG.delegateGetGreeting = GTU.ChinesePeople;//注册方法
15 DG.EventGreet+= GTU.ChinesePeople;
16 DG.EventGreet += GTU.EnglishPeople;
17 DG.GreetUser("小王");
18
19 Console.Read();
20
21 }
22
23
24 }
25 public class DelegateGreet
26 {
27 //声明委托
28 public delegate void DelegateGetGreeting(string UserName);
29
30 //委托变量为public,破坏了类的封装性
31 //public DelegateGetGreeting delegateGetGreeting;
32
33 //虽然Event论定义为public,但其还是私有变量,只能通过+=,或-=访问
34 public event DelegateGetGreeting EventGreet;
35
36 public void GreetUser(string UserName)
37 {
38 EventGreet?.Invoke(UserName);
39 //delegateGetGreeting(UserName);
40 }
41
42
43 }
44
45
46 //定义基本问候类和方法
47 public class GreetToUsers
48 {
49 //Chinese People
50 public void ChinesePeople(string UserName)
51 {
52 string GreetContents = "您好!" + UserName;
53 Console.WriteLine(GreetContents);
54 }
55
56 //English People
57 public void EnglishPeople(string UserName)
58 {
59 string GreetContents = "Hello," + UserName + "!";
60 Console.WriteLine(GreetContents);
61 }
62 //非英非汉
63 public void OtherPeople(string UserName)
64 {
65 Console.WriteLine("Sorrry,当前系统只支持汉语与英语");
66 }
67 }
68
69 }
70
71
72
四 事件机制
事件的本质就是委托,向外提供两个访问方法add_EventName(对应+=)和remove-EventName(对应-=),我们通过.NET Reflector反汇编工具来查看,到底是不是这样的。
参考文献
【01】C#高级编程(第七版) (Christian Nagel,Bill Evjen和Jay Glynn 编著,李铭 译,黄静 审校)
版权区
- 感谢您的阅读,若有不足之处,欢迎指教,共同学习、共同进步。
- 博主网址:http://www.cnblogs.com/wangjiming/。
- 极少部分文章利用读书、参考、引用、抄袭、复制和粘贴等多种方式整合而成的,大部分为原创。
- 如您喜欢,麻烦推荐一下;如您有新想法,欢迎提出,邮箱:2098469527@qq.com。
- 可以转载该博客,但必须著名博客来源。
C# 委托和事件高级进阶的更多相关文章
- [ASP.NET MVC 大牛之路]02 - C#高级知识点概要(1) - 委托和事件
在ASP.NET MVC 小牛之路系列中,前面用了一篇文章提了一下C#的一些知识点.照此,ASP.NET MVC 大牛之路系列也先给大家普及一下C#.NET中的高级知识点.每个知识点不太会过于详细,但 ...
- [ASP.NET 大牛之路]02 - C#高级知识点概要(1) - 委托和事件
在ASP.NET MVC 小牛之路系列中,前面用了一篇文章提了一下C#的一些知识点.照此,ASP.NET MVC 大牛之路系列也先给大家普及一下C#.NET中的高级知识点.每个知识点不太会过于详细,但 ...
- c#进阶之浅析委托和事件
何为委托 加了delegate关键字,没有方法体{}的方法模版(方法列表);委托是一种类型 public void Write() { //TODO } //加上关键字delegate,去掉方法体{} ...
- (.NET高级课程笔记)委托、事件总结
1.委托的声明.实例化和调用 同样的,也可以把事务写成上面的形式 2.泛型委托---Func.Action 3.委托的意义:解耦 4.委托的意义:异步多线程 5.委托的意义:多播委托 6.观察者模 ...
- C#高级编程 (第六版) 学习 第七章:委托和事件
第七章 委托和事件 回调(callback)函数是Windows编程的一个重要方面,实际上是方法调用的指针,也称为函数指针. .Net以委托的形式实现了函数指针的概念,.Net的委托是类型安全的. 委 ...
- .NET面试题系列[7] - 委托与事件
委托和事件 委托在C#中具有无比重要的地位. C#中的委托可以说俯拾即是,从LINQ中的lambda表达式到(包括但不限于)winform,wpf中的各种事件都有着委托的身影.C#中如果没有了事件,那 ...
- [转载]C#深入分析委托与事件
原文出处: 作者:风尘浪子 原文链接:http://www.cnblogs.com/leslies2/archive/2012/03/22/2389318.html 同类链接:http://www.c ...
- C#知识体系(二)用案例来理解委托与事件
上一篇博客讲到了LinQ和lambda的常用方法 还有很多我们未知但c#设计团队已经为我们封装好的类和方法.随着我们不断的熟悉C#语言,渐渐的就会接触到其他的知识点,委托.事件.反射.线程.同步,异步 ...
- C#综合揭秘——深入分析委托与事件
http://www.cnblogs.com/leslies2/archive/2012/03/22/2389318.html 引言 本篇文章将为你介绍一下 Delegate 的使用方式,逐渐揭开 C ...
随机推荐
- Vivado 调用自定义IP核
关于Vivado如何创建自定义IP核有大量的参考文章,这里就不多加阐述了,本文目的主要是解决如何在新建工程中引用其它工程已经自定义封装好的IP核,从而实现自定义IP核的灵活复用. 举个例子,我们的目标 ...
- 20155211 2016-2017-2 《Java程序设计》第四周学习总结
20155211 2016-2017-2 <Java程序设计>第四周学习总结 教材学习内容总结 这周的内容感觉较上周相比难度增加 教材学习中的问题和解决过程 刚开始学习第六章的时候的时候敲 ...
- CF543E Listening to Music
题面 空间只有$64\text{MB}$!!! 题解 (据说正解是毒瘤分块套分块) 按照权值从大到小排序,对所有能够覆盖到它的区间的左端点打个标记 按照值域建一棵主席树就可以了 区间查询最大值,用$m ...
- python爬虫-爬取盗墓笔记
本来今天要继续更新 scrapy爬取美女图片 系列文章,可是发现使用免费的代理ip都非常不稳定,有时候连接上,有时候连接不上,所以我想找到稳定的代理ip,下次再更新 scrapy爬取美女图片之应对反 ...
- Swift入门基础知识
var //代表变量,变量的值可以改变 let//代表常量类型不可改变 //声明常量heh类型Swift会自动根据你的值来自动判断该变量的类型也可以指定类型(个人感觉还是指定类型的比较好,可能会减少系 ...
- linux、WINDOWS命令行下查找和统计行数
linux : 例子: netstat -an | grep TIME_WAIT | wc -l | 管道符 grep 查找命令 wc 统计命令 windows: 例子: netstat -an | ...
- stl源码分析之vector
上篇简单介绍了gcc4.8提供的几种allocator的实现方法和作用,这是所有stl组件的基础,容器必须通过allocator申请分配内存和释放内存,至于底层是直接分配释放内存还是使用内存池等方法就 ...
- tomcat 设定自定义图片路径
1.问题 平常图片路径都是在项目目录下存放,都是ip地址+端口号+项目名+图片路径,因为项目需要要把图片从tomcat中分离出来,并且设置可以通过自定义地址访问自定义图片路径. 2.解决 在 tomc ...
- Git生成SSH密钥
git config --global user.name "yangjianliang"配置用户名 git config --global user.email "52 ...
- gtest命令行测试案例
使用gtest编写的测试案例通常本身就是一个可执行文件,因此运行起来非常方便.同时,gtest也为我们提供了一系列的运行参数(环境变量.命令行参数或代码里指定),使得我们可以对案例的执行进行一些有效的 ...