`

复习一下 .Net: delegate(委托)、event(事件) 的基础知识,从头到尾实现事件!

 
阅读更多

/*
.Net 的 delegate 与 event 的实现是不可分的!属于基础知识!

有这样一道 .Net/C# 试题:

请以事件的概念实现: 控制台屏幕录入任意字符串,并回显 "你键入了:" + 你刚才键入的字符串,如果键入 "q",退出程序,运行结束!

.Net 的 delegate 与 event 的实现是不可分的!属于基础知识!

写惯了 Windows 下的事件响应程序,真正从头到尾实现事件不常见!
我有两篇老文章:

《C# 写的 HttpRequsetResponse 类,异步、事件... 还热乎着呢!》
http://www.csdn.net/Develop/read_article.asp?id=19254
http://blog.csdn.net/playyuer/archive/2003/07/03/2856.aspx

《TreeView 的派生类: TreeViewEx 实现 NodeShowToolTip、NodeDoubleClick 事件》
http://www.csdn.net/Develop/Read_Article.asp?Id=19246
http://blog.csdn.net/playyuer/archive/2003/06/26/2857.aspx

也只是在 WinForm 下部分的实现了事件!


我的最简单的参考答案,都是用 static 方法实现的:
*/
/*
class Class1
{
public delegate void FireEventHandler(string s);
public static event FireEventHandler FireStatic;
static bool b = false;
static void Main(string[] args)
{
FireStatic += new FireEventHandler(Fire1);
System.Console.WriteLine("请键入任意字符(串),/"q/" 退出!");
string s;
while (true)
{
s = System.Console.ReadLine();
FireStatic(s);
if (b == true)
break;
}
}
static void Fire1(string s)
{
if (s != "q")
{
System.Console.WriteLine("你键入了: " + s);
}
else
{
System.Console.WriteLine("不送了!");
b = true;
}
}
}
*/
/*

经常编写 WinForm 程序的人应该熟悉,我想应该还是有人不知道具体怎样实现的事件!
这些人实际并不一定真知道:
this.button1.Click += new System.EventHandler(this.button1_Click)
的 EventHandler 到底是怎么实现的?不过这确实不妨碍编写 Click 事件的响应代码!

今天我也复习了一下,用 C# Console 程序跟大家分享一下:
请一定要注意程序注释,运行时注意屏幕提示:

*/
// 请存为任意 *.cs 文件后,csc 成 exe 文件!
class Class1
{
//声明一个委托 delegate FireEventHandler,delegate 没有 静态或实例 成员的说法
public delegate void FireEventHandler(string s);

//声明 FireEventHandler 委托类型的事件
//亦即将 FireEventHandler 理解为数据类型,易理解
public event FireEventHandler FireInstance;
public static event FireEventHandler FireStatic;

static void Main(string[] args)
{
System.Console.WriteLine("Hello World");

//用 delegate: FireEventHandler() 委托,建立委托关系
//Static 方法 FireStatic() 代理(被委托)了 Static 方法 Fire1()
FireStatic += new FireEventHandler(Fire1);
//Static 方法 FireStatic() 代理(被委托)了 Instance 方法 .Fire2()
FireStatic = FireStatic + new FireEventHandler(new Class1().Fire2);

Class1 c = new Class1();

//Instance 方法 .FireInstance() 代理(被委托)了 Instance 方法 .Fire2()
c.FireInstance += new FireEventHandler(c.Fire2);

//Instance 方法 .FireInstance() 代理(被委托)了 Static 方法 Fire1()
c.FireInstance = new FireEventHandler(Fire1) + c.FireInstance;
//以上仅是声明了委托关系,尚未执行 委托代理方法 !

System.Console.WriteLine("下面列印委托关系:");
System.Console.WriteLine("Static 方法 FireStatic() 作为代理接受以下委托:");

ListDelegateRelation(FireStatic);

System.Console.WriteLine();

System.Console.WriteLine("Instance 方法 .FireInstance() 作为代理接受以下委托:");
ListDelegateRelation(c.FireInstance);

System.Console.WriteLine("请键入任意字符(串),/"q/" 退出!");
string s;
while (true)
{
s = System.Console.ReadLine();
System.Console.WriteLine("--------------------------");
System.Console.WriteLine("以下是键入 /"{0}/" 后,触发事件的响应:");
//我们在此编程,即:在接受屏幕行录入后,令程序执行委托代理方法!
//从而触发了事件!
// FireStatic 静态事件被触发了
FireStatic("FireStatic 静态事件被触发了:/nStatic 方法 FireStatic() 受委托代理执行了 {0}/n你键入了: [" + s + "]/n");

// .FireInstance 实例事件被触发了
c.FireInstance(".FireInstance 实例事件被触发了: /nInstance 方法 .FireInstance() 受委托代理执行了 {0}/n你键入了: [" + s + "]/n");
System.Console.WriteLine("=======================================");
System.Console.WriteLine("请键入任意字符(串),/"q/" 退出!");
if (s == "q")
break;
}
///*
//解除委托关系可用 "-="
//下面解除委托,列印剩余委托关系
ListDelegateRelation(FireStatic);

FireStatic -= new FireEventHandler(Fire1);
ListDelegateRelation(FireStatic);

FireStatic = FireStatic - new FireEventHandler(new Class1().Fire2);
ListDelegateRelation(FireStatic);

c.FireInstance = new FireEventHandler(Fire1) - c.FireInstance;
ListDelegateRelation(c.FireInstance);

c.FireInstance = c.FireInstance - new FireEventHandler(Fire1);
ListDelegateRelation(c.FireInstance);

//*/
}

//静态方法
static void Fire1(string s)
{
//响应事件的程序
System.Console.WriteLine(s.Replace("{0}","static 方法 Fire1()"));
}

//实例方法
void Fire2(string s)
{
//响应事件的程序
System.Console.WriteLine(s.Replace("{0}","Instance 方法 .Fire2()"));
}

static void ListDelegateRelation(FireEventHandler x)
{
if (x != null)
{
//foreach (System.Delegate d in x.GetInvocationList())
foreach (FireEventHandler d in x.GetInvocationList())
{
System.Console.WriteLine(x.ToString() + " 类型的事件代理了 " + (d.Method.IsStatic ? x.Target + " 类的 Static 方法 ":d.Target + " 的 Instance 方法 .") + d.Method.Name);
}
}
else
{
System.Console.WriteLine("没有任何委托关系");
}
}
}

/*
下面是一个更复杂点的 Console 程序,根据 输入数字的奇偶性触发不同的事件!
*/
/*
using System.Text.RegularExpressions;
class Class1
{
private static Class1 x;
static void Main(string[] args)
{
System.Console.WriteLine("Hello World");
x = new Class1();

//设置委托 delegate 关系
//把 += 右边的 委托 给左边 的 (-= 是取消委托关系)
//以后就可以用对"左边"的方法签名的调用,实际就是相当于调用了"右边"的方法的执行
//将 Class1 的实例方法(x.Fire1) 委托给 Class1 的实例事件(x.FireInstance)
x.FireInstance += new Class1.FireEventHandler(x.Fire1);

//将 Class1 的静态方法(Class1.Fire2) 委托给 Class1 的实例事件(x.FireInstance)
x.FireInstance += new Class1.FireEventHandler(Class1.Fire2);

//将 Class1 的静态方法(Class1.Fire2) 委托给 Class1 的静态事件(Class1.FireStatic)
Class1.FireStatic += new Class1.FireEventHandler(Class1.Fire3);

//将 Class1 的实例方法(x.Fire1) 委托给 Class1 的静态事件(Class1.FireStatic)
Class1.FireStatic += new Class1.FireEventHandler(x.Fire4);

int i;
string s;
while (true)
{
if ((s = System.Console.ReadLine()) == "q")
{
break;
}
if (Regex.IsMatch(s,@"^/d+$"))
{
i = System.Convert.ToInt32(s);
if (i % 2 == 0)
{
//输入时偶数触发该事件
x.OnFireInstance();//调用实例方法触发事件
}
else
{
//输入时基数触发该事件
Class1.OnFireStatic(); //调用静态方法触发事件
}
}
}
}
public string Fire1() //实例方法
{
System.Console.WriteLine("输入是偶数");
return null;
}
public static string Fire2() //静态方法
{
System.Console.WriteLine("输入是偶数");
return null;
}
public static string Fire3() //静态方法
{
System.Console.WriteLine("输入是奇数");
return null;
}
public string Fire4() //实例方法
{
System.Console.WriteLine("输入是奇数");
return null;
}

//大多数委托是不需要返回值!

public delegate string FireEventHandler();

//实例事件
public event FireEventHandler FireInstance;

//静态事件
public static event FireEventHandler FireStatic;

//实例方法
public void OnFireInstance()
{
//实例方法触发实例事件
//根据委托关系的声明:
//委托执行时: 将实际调用执行 Fire1 和 Fire2
this.FireInstance(); //实例方法触发实例事件 委托执行
System.Console.WriteLine("以下是错误答案: 仅是测试/"实例方法/"触发/"静态事件/"");
//实例方法触发静态事件
//根据委托关系的声明:
//委托执行时: 将实际调用执行 Fire3 和 Fire4
FireStatic(); //实例方法触发静态事件 委托执行
}

//静态方法
public static void OnFireStatic()
{
//静态方法触发静态事件
//根据委托关系的声明:
//委托执行时: 将实际调用执行 Fire3 和 Fire4
FireStatic();

System.Console.WriteLine("以下是错误答案: 仅是测试/"静态方法/"触发/"实例事件/"");
//实例成员 x 就是为这里调用实例事件方法!
//静态方法触发实例事件
//根据委托关系的声明:
//委托执行时: 将实际调用执行 Fire1 和 Fire2
x.FireInstance(); //静态方法触发实例事件 委托执行
}
}
*/

回答下面网友问题
class AppTest
{
static void Main(string[] args)
{
WithEventsClass.FireStatic += new WithEventsClass.FireEventHandler(Fire1);
System.Console.WriteLine("请键入任意字符(串),/"q/" 退出!");
WithEventsClass.Run();
}
static void Fire1(string s)
{
if (s != "q")
{
System.Console.WriteLine("你键入了: " + s);
}
else
{
System.Console.WriteLine("不送了!");
WithEventsClass.b = true;
WithEventsClass.FireStatic -= new WithEventsClass.FireEventHandler(Fire1);;
}
}
}

class WithEventsClass
{
public delegate void FireEventHandler(string s);
public static event FireEventHandler FireStatic;
public static bool b = false;
public static void Run()
{
string s;
while (!b)
{
s = System.Console.ReadLine();
if (FireStatic != null)
{
FireStatic(s);
}
}
}
}
//=======================================
//instance1
class AppTest
{
public WithEventsClass _wec;
static void Main(string[] args)
{
AppTest a = new AppTest();
WithEventsClass wec = new WithEventsClass();
wec.FireInstance += new WithEventsClass.FireEventHandler(a.wec_FireInstance);
a._wec = wec;
System.Console.WriteLine("请键入任意字符(串),/"q/" 退出!");
wec.Run();

}
private void wec_FireInstance(string s)
{
if (s != "q")
{
System.Console.WriteLine("你键入了: " + s);
}
else
{
System.Console.WriteLine("不送了!");
_wec.b = true;
_wec.FireInstance -= new WithEventsClass.FireEventHandler(this.wec_FireInstance);
}
}
}

class WithEventsClass
{
public delegate void FireEventHandler(string s);
public event FireEventHandler FireInstance;
public bool b = false;
public void Run()
{
string s;
while (!this.b)
{
s = System.Console.ReadLine();
if (this.FireInstance != null)
{
this.FireInstance(s);
}
}
}
}
//=================================================
//instance2
class AppTest
{
static void Main(string[] args)
{
AppTest a = new AppTest();
WithEventsClass wec = new WithEventsClass();
wec.FireInstance += new WithEventsClass.FireEventHandler(a.wec_FireInstance);
System.Console.WriteLine("请键入任意字符(串),/"q/" 退出!");
wec.Run();
}
private void wec_FireInstance(WithEventsClass Sender)
{
if (Sender.s != "q")
{
System.Console.WriteLine("你键入了: " + Sender.s);
}
else
{
System.Console.WriteLine("不送了!");
Sender.b = true;
Sender.FireInstance -= new WithEventsClass.FireEventHandler(this.wec_FireInstance);
}
}
}

class WithEventsClass
{
public delegate void FireEventHandler(WithEventsClass Sender);
public event FireEventHandler FireInstance;
public bool b = false;
public string s;
public void Run()
{
while (!this.b)
{
this.s = System.Console.ReadLine();
if (this.FireInstance != null)
{
this.FireInstance(this);
}
}
}
}

分享到:
评论

相关推荐

    VB.Net-C#多线程Thread-代理委托delegate编程

    最近收集的VB.Net-C#多线程Thread-代理委托delegate编程。文章列表: c#.net多线程同步.txt C#WebBrowser页面与WinForm交互技巧一.txt C#多线程编程-多细全.txt C#多线程编程简单实例.txt C#多线程窗体控件安全访问....

    .Net C#委托 delegate

    本ppt结合场景和实例对C#委托(delegate)的基础进行了讲解:包括了委托的定义,基本语法,同步异步调用,匿名委托的使用,泛型委托,lamda表达式,剖析了委托协变、委托逆变。对委托在.net 3.5框架中的身影进行了分析...

    C#由浅至深深度解析Delegate委托与Event事件

    委托 和 事件在 .Net Framework中的应用非常广泛,然而,较好地理解委托和事件对很多接触C#时间不长的人来说并不容易。它们就像是一道槛儿,过了这个槛的人,觉得真是太容易了,而没有过去的人每次见到委托和事件就...

    .net delegate and event

    学习.net委托与事件的语法及使用方法,例子简单易懂,是不错的入门手册。

    【答:】Insus.NET:七道最经典的asp.net页面传值题

    [主要用delegate&event实现。代码很简单,本来想写注释了,可碍于嘴拙,便摆了个空架子,朋友们可以自己酌情添加] 第一题:一个Page:PageA.aspx的网页上放有一个TextBox ID为TextBox1和一个Button ID为Button1; ...

    C#中的事件和委托(Delegate,Event)

    C#中的事件和委托(Delegate,Event)

    FastDelegate.Net:.Net 缓慢的 Delegate.DynamicInvoke 的替代品

    .Net 缓慢的 Delegate.DynamicInvoke 的替代品。 (需要 .Net 3.5 或更新版本) Delegate.DynamicInvoke 使用非常慢的后期绑定。 FastDelegate 生成、编译和缓存几乎与常规方法调用一样快的代码。 它适用于任何...

    .NET笔记之:Delegate内部原理的分析

     这篇文章我主要是想告诉大家委托的内部到底是什么样的结构,我们先通过一个简单的demo来复习一下委托: 代码如下:using System; using System.Collections.Generic; using System.Linq; using System.Text; ...

    解析.Net 4.0 中委托delegate的使用详解

    但是.Net毕竟是更高级的语言,委托Delegate也更高级了,委托是一种数据接口,它包含调用目标和调用方法的指针;而在.Net中定义的委托都继承自MulticastDelegate即多播委托,所谓的多播委托是指可以包含多个调用方法...

    .Net的异步机制(委托Delegate)

    使用.Net 的委托机制来为我们的程序提供异步操作行为. 1步, 为我们的AsyncTest(Hello方法) 声明一个委托 public delegate string AsyncEventHandler(string name); 2步,使用委托提供的BeginInvoke, EndInvoke 方法...

    Delegate.Event.ThreadDelegate.Event.Thread

    Delegate.Event.ThreadDelegate.EvDelegate.Event.Threadent.Thread

    asp.net知识库

    ASP.NET: State Server Gems 完整的动态加载/卸载程序集的解决方案 从NUnit中理解.NET自定义属性的应用(转载) 如何在.NET中实现脚本引擎 (CodeDom篇) .NET的插件机制的简单实现 我对J2EE和.NET的一点理解 难分难舍...

    事件委托 event delegate

    主要通过进度条进行解释 利用委托将界面和业务层分离的方法

    ios app:Delegate例子

    ios app :使用delegate事例

    delegate委托

    从序言中,大家应该对委托和事件的重要性有点了解了吧,虽然说我们现在还是能模糊,但是从我的大白话系列中,我会把这些概念说的通俗易懂的。首先,我们还是先说说委托吧,从字面上理解,只要是中国人应该都知道这个...

    .NET事件模型教程

    对.NET的事件模型的讲解,通俗易懂

    asp.net 事件与委托分析

    delegate是C#中的一种类型,它实际上是一个能够持有对某个方法的引用的类。与其它的类不同,delegate类能够拥有一个签名(signature),并且它只能持有与它的签名相匹配的方法的引用。

    NET Delegate Event Model vs COM Connection PointsNET事件模型

    NET Delegate Event Model vs COM Connection PointsNET事件模型和COM连接点

    .net C# 泛型事件委托

    泛型事件委托,涉及了Generic , EventAgrs , Delegate

Global site tag (gtag.js) - Google Analytics