关于C#事件和委托的一点体会
2014-02-24 15:02
513 查看
下面这段代码为:
/******************************************************************************
Module: MailManager.cs
Notices: Copyright (c) 2002 Jeffrey Richter
******************************************************************************/
using System;
///////////////////////////////////////////////////////////////////////////////
class MailManager
{
public class
ProcessMailMsgEventArgs : EventArgs
{
// 1. Type defining information passed to receivers of the
event
public ProcessMailMsgEventArgs(
String from, String to, String subject, String body)
{
this.from = from;
this.to = to;
this.subject = subject;
this.body = body;
}
public readonly String from, to, subject, body;
}
// 2.
Delegate type defining the prototype of the callback method
// that
receivers must implement
public
delegate void ProcessMailMsgEventHandler(
Object sender, ProcessMailMsgEventArgs args);
// 3. The
event itself
public event
ProcessMailMsgEventHandler ProcessMailMsg;
// 4.
Protected, virtual method responsible for notifying
registered
// objects of
the event
protected
virtual void OnProcessMailMsg(ProcessMailMsgEventArgs e)
{
// Has any objects registered interest with our event?
if (ProcessMailMsg != null)
{
// Yes, notify all the objects
ProcessMailMsg(this, e);
//激发事件,将消息传递给订阅此事件的所有对象
}
}
// 5.
Method that translates the input into the desired event
// This
method is called when a new e-mail message arrives
public void
SimulateArrivingMsg(String from, String to,
String subject, String body)
{
// Construct an object to hold the information we wish
// to pass to the receivers of our notification
ProcessMailMsgEventArgs e =
new ProcessMailMsgEventArgs(from, to, subject, body);
// Call our virtual method notifying our object that the
event
// occurred. If no type overrides this method, our object
will
// notify all the objects that registered interest in the
event
OnProcessMailMsg(e);
}
}
///////////////////////////////////////////////////////////////////////////////
class Fax
{
// Pass the
MailManager object to the constructor
public
Fax()
{
}
// This
is the method that the MailManager will call
// when a
new e-mail message arrives
public
virtual void FaxMsg(
Object sender, MailManager.ProcessMailMsgEventArgs e)
{
// 'sender' identifies the MailManager in case
// we want to communicate back to it.
// 'e' identifies the additional event information
// that the MailManager wants to give us.
// Normally, the code here would fax the e-mail message.
// This test implementation displays the info on the console
Console.WriteLine("Faxing mail message:");
Console.WriteLine(
" To:
{0}\n From:
{1}\n Subject:
{2}\n Body: {3}\n",
e.from, e.to, e.subject, e.body);
}
public
void Register(MailManager mm)
{
// Construct an instance of the ProcessMailMsgEventHandler
// delegate that refers to our FaxMsg callback method.
MailManager.ProcessMailMsgEventHandler callback =
new MailManager.ProcessMailMsgEventHandler(FaxMsg);
mm.ProcessMailMsg+= callback;
}
public void
Unregister(MailManager mm)
{
// Construct an instance of the ProcessMailMsgEventHandler
// delegate that refers to our FaxMsg callback method.
MailManager.ProcessMailMsgEventHandler callback =
new MailManager.ProcessMailMsgEventHandler(FaxMsg);
// Unregister ourself with MailManager's ProcessMailMsg event
mm.ProcessMailMsg -= callback;
}
}
class Fax1 : Fax
{
public
override void FaxMsg(
Object sender, MailManager.ProcessMailMsgEventArgs e)
{
// 'sender' identifies the MailManager in case
// we want to communicate back to it.
// 'e' identifies the additional event information
// that the MailManager wants to give us.
// Normally, the code here would fax the e-mail message.
// This test implementation displays the info on the console
Console.WriteLine("Faxing1 mail message:");
Console.WriteLine(
" To:
{0}\n From:
{1}\n Subject:
{2}\n Body: {3}\n",
e.from, e.to, e.subject, e.body);
}
}
///////////////////////////////////////////////////////////////////////////////
class Pager
{
// Pass the
MailManager object to the constructor
public
Pager(MailManager mm)
{
// Construct an instance of the ProcessMailMsgEventHandler
// delegate that refers to our SendMsgToPager callback
method.
// Register our callback with MailManager's ProcessMailMsg
event
mm.ProcessMailMsg +=
new MailManager.ProcessMailMsgEventHandler(SendMsgToPager);
}
// This
is the method that the MailManager will call
// when a
new e-mail message arrives
private void SendMsgToPager(
Object sender, MailManager.ProcessMailMsgEventArgs e)
{
// 'sender' identifies the MailManager in case
// we want to communicate back to it.
// 'e' identifies the additional event information
// that the MailManager wants to give us.
// Normally, the code here would send the e-mail message to a
pager.
// This test implementation displays the info on the console
Console.WriteLine("Sending mail message to pager:");
Console.WriteLine(
" To:
{0}\n From:
{1}\n Subject:
{2}\n Body: {3}\n",
e.from, e.to, e.subject, e.body);
}
}
///////////////////////////////////////////////////////////////////////////////
class App
{
static void
Main()
{
// Construct a MailManager object
MailManager mm = new MailManager();
// Construct a Fax object passing it the MailManager object
Fax fax = new Fax();
Fax fax1 = new Fax1();
fax.Register(mm);
fax1.Register(mm);
// Construct a Pager object passing it the MailManager object
Pager pager = new Pager(mm);
// Simulate an incoming mail message
mm.SimulateArrivingMsg("Jeffrey Richter",
"Santa",
"Christmas",
"Thanks for the great presents last year");
// Force the Fax object to unregister itself with the
MailManager
fax.Unregister(mm);
// Simulate an incoming mail messa
4000
ge
mm.SimulateArrivingMsg("Jeffrey Richter", "Mom & Dad",
"My birthday",
"Thanks for the great presents last year");
}
}
执行结果如下:
Faxing mail
message:
To:
Jeffrey Richter
From: Santa
Subject: Christmas
Body: Thanks for the great
presents last year
Faxing1 mail
message:
To: Jeffrey Richter
From: Santa
Subject: Christmas
Body: Thanks for the great
presents last year
Sending mail message to pager:
To: Jeffrey Richter
From: Santa
Subject: Christmas
Body: Thanks for the great
presents last year
Faxing1 mail message:
To: Jeffrey Richter
From: Mom & Dad
Subject: My birthday
Body: Thanks for the great
presents last year
Sending mail message to pager:
To: Jeffrey Richter
From: Mom & Dad
Subject: My birthday
Body: Thanks for the great
presents last year
注意上面红颜色部分,出现这样输出结果的原因是名为FaxMsg的委托方法是虚方法,而将委托方法改为虚函数,则不会有任何影响。
在C/C++中,非静态成员函数是不同作为回调函数的,因为非静态成员函数成员函数与具体的对象有关系,所以我最初很不能理解为什么FaxMsg可以用作回调函数,最近似乎有所领悟,那就是在把委托实例加入事件的委托链时,除了将方法的地址传入外,同时也将this指针传入了,这部分工作应该是编译器完成的。如果是虚方法,则动态绑定方法的地址。如果是静态方法,则忽略this指针。
这样,上面的代码就好理解了,我估计应该是这样的,不知道对不对,也许《Applied
Microsoft.NET Framework
Programming》中会讲到,不过我还没有看到那么远。到时候再验证吧。
/******************************************************************************
Module: MailManager.cs
Notices: Copyright (c) 2002 Jeffrey Richter
******************************************************************************/
using System;
///////////////////////////////////////////////////////////////////////////////
class MailManager
{
public class
ProcessMailMsgEventArgs : EventArgs
{
// 1. Type defining information passed to receivers of the
event
public ProcessMailMsgEventArgs(
String from, String to, String subject, String body)
{
this.from = from;
this.to = to;
this.subject = subject;
this.body = body;
}
public readonly String from, to, subject, body;
}
// 2.
Delegate type defining the prototype of the callback method
// that
receivers must implement
public
delegate void ProcessMailMsgEventHandler(
Object sender, ProcessMailMsgEventArgs args);
// 3. The
event itself
public event
ProcessMailMsgEventHandler ProcessMailMsg;
// 4.
Protected, virtual method responsible for notifying
registered
// objects of
the event
protected
virtual void OnProcessMailMsg(ProcessMailMsgEventArgs e)
{
// Has any objects registered interest with our event?
if (ProcessMailMsg != null)
{
// Yes, notify all the objects
ProcessMailMsg(this, e);
//激发事件,将消息传递给订阅此事件的所有对象
}
}
// 5.
Method that translates the input into the desired event
// This
method is called when a new e-mail message arrives
public void
SimulateArrivingMsg(String from, String to,
String subject, String body)
{
// Construct an object to hold the information we wish
// to pass to the receivers of our notification
ProcessMailMsgEventArgs e =
new ProcessMailMsgEventArgs(from, to, subject, body);
// Call our virtual method notifying our object that the
event
// occurred. If no type overrides this method, our object
will
// notify all the objects that registered interest in the
event
OnProcessMailMsg(e);
}
}
///////////////////////////////////////////////////////////////////////////////
class Fax
{
// Pass the
MailManager object to the constructor
public
Fax()
{
}
// This
is the method that the MailManager will call
// when a
new e-mail message arrives
public
virtual void FaxMsg(
Object sender, MailManager.ProcessMailMsgEventArgs e)
{
// 'sender' identifies the MailManager in case
// we want to communicate back to it.
// 'e' identifies the additional event information
// that the MailManager wants to give us.
// Normally, the code here would fax the e-mail message.
// This test implementation displays the info on the console
Console.WriteLine("Faxing mail message:");
Console.WriteLine(
" To:
{0}\n From:
{1}\n Subject:
{2}\n Body: {3}\n",
e.from, e.to, e.subject, e.body);
}
public
void Register(MailManager mm)
{
// Construct an instance of the ProcessMailMsgEventHandler
// delegate that refers to our FaxMsg callback method.
MailManager.ProcessMailMsgEventHandler callback =
new MailManager.ProcessMailMsgEventHandler(FaxMsg);
mm.ProcessMailMsg+= callback;
}
public void
Unregister(MailManager mm)
{
// Construct an instance of the ProcessMailMsgEventHandler
// delegate that refers to our FaxMsg callback method.
MailManager.ProcessMailMsgEventHandler callback =
new MailManager.ProcessMailMsgEventHandler(FaxMsg);
// Unregister ourself with MailManager's ProcessMailMsg event
mm.ProcessMailMsg -= callback;
}
}
class Fax1 : Fax
{
public
override void FaxMsg(
Object sender, MailManager.ProcessMailMsgEventArgs e)
{
// 'sender' identifies the MailManager in case
// we want to communicate back to it.
// 'e' identifies the additional event information
// that the MailManager wants to give us.
// Normally, the code here would fax the e-mail message.
// This test implementation displays the info on the console
Console.WriteLine("Faxing1 mail message:");
Console.WriteLine(
" To:
{0}\n From:
{1}\n Subject:
{2}\n Body: {3}\n",
e.from, e.to, e.subject, e.body);
}
}
///////////////////////////////////////////////////////////////////////////////
class Pager
{
// Pass the
MailManager object to the constructor
public
Pager(MailManager mm)
{
// Construct an instance of the ProcessMailMsgEventHandler
// delegate that refers to our SendMsgToPager callback
method.
// Register our callback with MailManager's ProcessMailMsg
event
mm.ProcessMailMsg +=
new MailManager.ProcessMailMsgEventHandler(SendMsgToPager);
}
// This
is the method that the MailManager will call
// when a
new e-mail message arrives
private void SendMsgToPager(
Object sender, MailManager.ProcessMailMsgEventArgs e)
{
// 'sender' identifies the MailManager in case
// we want to communicate back to it.
// 'e' identifies the additional event information
// that the MailManager wants to give us.
// Normally, the code here would send the e-mail message to a
pager.
// This test implementation displays the info on the console
Console.WriteLine("Sending mail message to pager:");
Console.WriteLine(
" To:
{0}\n From:
{1}\n Subject:
{2}\n Body: {3}\n",
e.from, e.to, e.subject, e.body);
}
}
///////////////////////////////////////////////////////////////////////////////
class App
{
static void
Main()
{
// Construct a MailManager object
MailManager mm = new MailManager();
// Construct a Fax object passing it the MailManager object
Fax fax = new Fax();
Fax fax1 = new Fax1();
fax.Register(mm);
fax1.Register(mm);
// Construct a Pager object passing it the MailManager object
Pager pager = new Pager(mm);
// Simulate an incoming mail message
mm.SimulateArrivingMsg("Jeffrey Richter",
"Santa",
"Christmas",
"Thanks for the great presents last year");
// Force the Fax object to unregister itself with the
MailManager
fax.Unregister(mm);
// Simulate an incoming mail messa
4000
ge
mm.SimulateArrivingMsg("Jeffrey Richter", "Mom & Dad",
"My birthday",
"Thanks for the great presents last year");
}
}
执行结果如下:
Faxing mail
message:
To:
Jeffrey Richter
From: Santa
Subject: Christmas
Body: Thanks for the great
presents last year
Faxing1 mail
message:
To: Jeffrey Richter
From: Santa
Subject: Christmas
Body: Thanks for the great
presents last year
Sending mail message to pager:
To: Jeffrey Richter
From: Santa
Subject: Christmas
Body: Thanks for the great
presents last year
Faxing1 mail message:
To: Jeffrey Richter
From: Mom & Dad
Subject: My birthday
Body: Thanks for the great
presents last year
Sending mail message to pager:
To: Jeffrey Richter
From: Mom & Dad
Subject: My birthday
Body: Thanks for the great
presents last year
注意上面红颜色部分,出现这样输出结果的原因是名为FaxMsg的委托方法是虚方法,而将委托方法改为虚函数,则不会有任何影响。
在C/C++中,非静态成员函数是不同作为回调函数的,因为非静态成员函数成员函数与具体的对象有关系,所以我最初很不能理解为什么FaxMsg可以用作回调函数,最近似乎有所领悟,那就是在把委托实例加入事件的委托链时,除了将方法的地址传入外,同时也将this指针传入了,这部分工作应该是编译器完成的。如果是虚方法,则动态绑定方法的地址。如果是静态方法,则忽略this指针。
这样,上面的代码就好理解了,我估计应该是这样的,不知道对不对,也许《Applied
Microsoft.NET Framework
Programming》中会讲到,不过我还没有看到那么远。到时候再验证吧。
相关文章推荐
- 我今天的工作日志——关于事件委托的一点心得体会
- 关于C#的委托和事件的一点思考
- 关于C#.Net中事件(event)、委托(delegate)和方法的一点理解
- 关于C#的delegate(委托)和event(事件)的使用
- C# 关于委托和事件的妙文
- c#中关于delegate、委托、事件之间的联系、关系
- 关于C#的委托与事件的一个小DEMO
- C# 关于委托和事件的妙文:通过一个例子详细介绍委托和事件的作用;Observer模式简介
- js之onload事件关于我的一点体会
- c#关于委托和事件
- C#关于委托与事件的例子
- [转摘] 关于C#中委托和事件机制的一个最佳实例
- c#关于委托和事件(三)
- c#关于委托和事件
- c#关于委托和事件(一)(介绍的很详细)
- 对C#下函数,委托,事件的一点理解!
- (每日心得)关于C#中委托和事件的一些认识(二)
- 对C#下函数,委托,事件的一点理解!
- 关于c#中委托与事件的一些理解
- c#关于委托和事件