因为评教的维护工作,有一个星期计算机进度没有动,觉得还是时间管理出了问题,计划的总结也没有完成,现在就以这篇关于委托和事件的总结作为快速进入学习状态的调和剂吧。
定义和由来
委托是一种引用方法的类型,一旦为委托分配了方法,委托将于该方法具有完全相同的行为
因为是初学者对于委托的概念不是很理解,就查阅了很多资料,都说委托很类似于C中的指针,当然C中指针的功能有一些诟病,C# 想要拥有指针强大的功能,但是又要摒弃那些诟病,所以委托就出现了。我们可以把委托看成是一个升级的指针,因为函数指针只能简单的把地址指向另一个函数,而委托不仅仅能把地址指向另一个函数,而且还能传递参数,返回值等多个信息。
如何声明和创建委托
using System.Threading.Tasks;
namespace 委托
{
public delegate void DelegateClass();// 声明委托
class Program
{
public static void Fangfa1()
{ }
static void Main(string[] args)
{
DelegateClass dc1 = new DelegateClass(Program.Fangfa1);//方法一,方法有new关键字,参数为类.方法名
DelegateClass dc2 = new DelegateClass(Fangfa1);//方法二,常用格式,有new关键字,参数为方法
DelegateClass dc3 = Fangfa1;//方法三,不需要new关键字,直接加上方法名
Fangfa2 ac = new Fangfa2();//方法四,实例化一个对象,然后用对象名.方法名
DelegateClass de4 = new DelegateClass(ac.Fangfa二);
}
}
}
namespace 委托
{
class Fangfa2
{
public void Fangfa二()
{ }
}
}
一个小例子
namespace 委托2
{
class Program
{
delegate string MyDelegate();//声明委托
static void Main(string[] args)
{
string str = "";
MyDelegate myreadline = new MyDelegate(Console.ReadLine);//委托实例化,让其引用Console.ReadLine的方法
Console.WriteLine("请输入字符串");
str = myreadline();
Console.WriteLine("你输入的字符串是{0}", str);
Console.ReadLine();
}
}
}
可以看出,实例化出来的委托对象myreadline通过引用Console.ReadLine的方法,实现了Console.ReadLine的功能。
自己理解的委托
namespace 委托2
{
class Greet
{
public void GreetPeople(string name)//调用问好的方法,传入参数是姓名姓名
{
EnglishGreeting(name);
}
public void EnglishGreeting(string name)//问好的方法
{
Console.WriteLine("Morning," + name);
}
}
}
但是现在全球一家亲,你用英语问好我们中国人都知道,但是如果你用别的国家的语言问好,我们就不知道你再说什么了,所以这个GreetPeople方法就要扩展出“根据不同国家的人,说不同国家的话”这个功能,这就需要在GreetPeople中添加判断条件,还要新添一种语言的问好方法
class Greet
{
public enum language//枚举
{
English,Chinese
}
public void GreetPeople(string name,language lang)//调用问好的方法,传入参数是姓名姓名
{
switch (lang)
{
case language .English :
EnglishGreeting (name);
break;
case language.Chinese :
ChineseGreeting (name);
break;
}
}
public void EnglishGreeting(string name)//问好的方法
{
Console.WriteLine("Morning," + name);
}
public void ChineseGreeting(string name)
{
Console.WriteLine("早上好," + name);
}
}
从上边的代码可以看出,这段代码的扩展性很差,违背了开闭原则,每次新添语言,都要打开Greet类,添加新的条件,新的问好方法。
我们看GreetPeople这个方法的声明
public void GreetPeople(string name,language lang)
改之后的代码:
namespace 委托2
{
public delegate void GreetingDelegate(string name);//声明委托
class Greet
{
private static void EnglishGreeting(string name)//英语问好的方法
{
Console.WriteLine("Morning," + name);
}
private static void ChineseGreeting(string name)//中文问好的方法
{
Console.WriteLine("早上好," + name);
}
private static void GreetPeople(string name ,GreetingDelegate MakeGreeting)
{ //委托定义了MakeGreeting的参数类型
MakeGreeting(name);
}
static void Main(string[] args)
{
GreetPeople("Khalil",EnglishGreeting);
GreetPeople ("方大同",ChineseGreeting );
Console.ReadKey ();
}
}
}
我的理解:委托将一些逻辑判断封装到了方法体中,使得方法可以像参数一样,在调用别的方法的时候,赋值给函数一个已经封装好的方法,这就使得一些本该在调用的这个方法里做的一些逻辑判断,转移到了传参中,传进去的参数已经是经过判断的了,这样使得程序员可以灵活调用响应的方法。
事件
事件构建在委托的基础上。事件是一种信号机制,他在某些操作发生时自动地发出通知。事件定义为对象发送的消息,发信号通知操作的发生。我感觉事件类似于数据库库中的触发器。先设定好如果符合某些操作,则自动发送消息。