`
warlock333
  • 浏览: 5100 次
最近访客 更多访客>>
社区版块
存档分类
最新评论

浅析C#之——Observer, Delegate和event(2)

    博客分类:
  • C#
阅读更多
接下来说一下Delegate
先介绍一下Delegate类:
Delegate——委托,是C#中对于函数指针进行封装后的对象,因为C#和JAVA一样都不允许直接使用指针这种高效但危险的东西,所以就用Delegate对象将其封装了起来以增加其使用的安全性;此外,比起直接使用字段,使用对象会更为方便,因为有了对象的封装后,就可以在对象内部预设需要的方法,为外部的调用增添许多便利。
创建委托时,delegate修饰符使其后类型继承MulticastDelegate,该基类提供委托以赋值,添加委托,移除委托和调用委托方法等操作,具体更多功能可查阅MSDN。

先写一个关于使用Delegate的例子:delegate.cs
using System;

// 创建一个delegate
delegate int MyHandler(int d1, int d2); 

class Test
{		
	public static int Add(int x, int y)
	{
		Console.WriteLine("Add has been invoked..");
		return x+y;
	}
	
	public int Minus(int x, int y)
	{
		Console.WriteLine("Minus has been invoked..");
		return x-y;
	}
	
	public static void Main()
	{
		Console.WriteLine("mh1:=====================================");
		MyHandler mh1 = new MyHandler(Test.Add);	//绑定静态方法;	
		Console.WriteLine("Outcome1: "+ mh1(100, 200));//==>mh1.Invoke(100, 200); ==> {jump Test.Add;}
		Console.WriteLine();
		
		Console.WriteLine("mh2:=====================================");
		Test t = new Test();
		MyHandler mh2 = new MyHandler(t.Minus);//绑定动态方法,这里其实传了两个参数:t和&Minus;
		Console.WriteLine("Outcome2: "+ mh2(100, 50));
		Console.WriteLine();
		
		Console.WriteLine("mh3:=====================================");
		MyHandler mh3 = mh1 + mh2;//   ;构建委托链;有序的;
		Console.WriteLine("Outcome3: "+ mh3(200, 100));//依次执行mh1,mh2;返回值是最后一个委托方法的返回值,在此为mh2的返回值;
		Console.WriteLine();
		
		Console.WriteLine("mh4:=====================================");
		MyHandler mh4 = mh1 + mh2 + mh3;
		Delegate[] mhs = mh4.GetInvocationList();  //使用Delegate的GetInvocationList()方法可以数组的形式获得委托链中的每一个委托,从而实现对于委托链的随机访问;
		Console.WriteLine(mhs);
		for(int i = 0; i<mhs.Length; i++) //遍历委托链;
		{
			MyHandler tempHandler =(MyHandler)mhs[i];
			Console.WriteLine("outcome4: " + i + " " + tempHandler(200, 100));
		}
		Console.WriteLine();
		
		Console.WriteLine("mh5:=====================================");
		MyHandler mh5 = delegate(int x, int y){  //绑定匿名方法;
				Console.WriteLine("匿名方法:");
				return x*y;
		};		
		Console.WriteLine("Outcome5: " + mh5(100,200));			
	}	
}

输出结果:



以上是委托创建申明方法和delegate所支持的一些操作用法。

接下来想讨论一下delegate修饰符和Delegate类的内部实现,其实刚才的代码中的一些注释已经给出了答案:
我们可以通过使用ILDasm.exe查看实际生成的程序集:



由此可知,当编译器看到
delegate int MyHandler(int d1, int d2);
这行代码时,会将其转换为如下代码:
class MyHandler : MulticastDelegate
{
	//构造器;
	public MyHandler(Object object, IntPtr method);
	
	//这个方法和源代码指定的原型一样;
	public virtual void Invoke(int d1, int d2);
	
	//以下方法实现了对回调方法的异步回调,具体还没有研究过。。。
	public virtual IAsyncResult BeginInvoke(...);
	public irtual void EndInvoke(...);
} 

//MulticastDelegate内最主要的是包含了三个静态字段:
class MulticastDelegate
{
	private Object _target; //这个字段用来指出要传给实例方法的隐式参数this的值;
													//当委托对象包装的是一个静态方法时,这个字段为null;
													//当委托对象包装一个实例方法时,这个字段引用的是回调函数要操作的对象;
	private IntPtr _method;	//一个内部的整数值,CLR用它标示要回调的方法;可以理解为一个函数指针;
	private Object _invocationList;	//用来指向委托链中的下一个委托对象;
	//...
}

当使用委托调用某方法时,如:
Console.WriteLine("mh2:=====================================");
		Test t = new Test();
		MyHandler mh2 = new MyHandler(t.Minus);//绑定动态方法,这里其实传了两个参数:t和&Minus;
		Console.WriteLine("Outcome2: "+ mh2(100, 50));
		Console.WriteLine();

它所生成的真正的程序集为:



由此可知,程序会在mh2被创建的时候将对象t赋给_target,将Minus的地址赋给_methodPtr以完成委托对象与方法的绑定;随后当执行到mh2(100, 50)时,因为编译器知道mh2是一个委托,所以它会事先将其自动转化为
mh2.Invoke(100,50)

从而调用mh2.Invoke(100,50)方法并根据先前保存下来的_target和_methodPtr跳转进入t.Minus()方法,执行t.Minus(100,200)。
以上,便是委托的事实真相!

接下来说一下我对于C#定义委托这一对象的理解:
Java中没有委托这个概念,但似乎可以用继承Handler接口来实现委托的功能,具体是怎么做的没有去研究。
总之,C#应该是认为函数指针在程序设计还中是一个很重要的概念,需要单独为其封装一个类并设定一些使用的机制。其实,或许大多数基于方法的晚绑定都可以用定义接口后将对象传入某方法随后调用接口中预设好的某个特定方法来实现(如之前用接口方法实现的Observer设计模式),只是这样的话就让人感觉很繁琐,不够直接。使用委托可以直接定位到对象中的某个方法,也能使代码更精简且利用阅读(可以对比一下之后用delegate和event实现的Observer设计模式)。

接下来用delegate改写先前的Observer.cs:Observer_delegate.cs
using System;
//using System.Collections;

interface ReceiveMessage
{
	void storeMessage(String message);
}

//创建委托类型;
delegate void ReceiverList(String message);

class MessageCenter
{		
	private String messageString; // MessageCenter用来缓存消息的String字段;
	//private ArrayList receiverList = new ArrayList();
	private ReceiverList receiverList; //has a delegate;	
	
	//添加消息接受者;
	public void addReceiver(ReceiveMessage receiver)
	{
		//receiverList.Add(receiver);
		receiverList += new ReceiverList(receiver.storeMessage);
	}
	
	//移除消息接受者;
	public void removeReceiver(ReceiveMessage receiver)
	{
		//receiverList.Remove(receiver);
		receiverList -= new ReceiverList(receiver.storeMessage);
	}
	
	// 新建消息;
	public void newMessage(String message)
	{
		Console.WriteLine("New message: " + message + "... [MessageCenter]" );
		this.messageString = message;
	}
	
	// 通知MessageStore有新消息,将其备份入MessageStore;
	//public void notice(MessageStore messageStore)
	/*
	public void notice(ReceiveMessage messageStore) //将对象参数类型换成接口类型;	
	{
		//messageStore.MessageString = this.messageString;
		//Console.WriteLine("Message: '" + messageString + "' have been stored in MessageStore...");
		messageStore.storeMessage(this.messageString);
	}
	*/
	public void notice()	//// 通知所有已注册的receiver有新消息,并调用其storeMessage方法;
	{
		/*foreach(Object receiver in receiverList)
		{
			(receiver as ReceiveMessage).storeMessage(this.messageString);
		}*/
		this.receiverList(this.messageString);
	}	
}

class MessageStore : ReceiveMessage
{
	private String messageString;	// MessageStore用户存储消息的String字段;
																// 其实应该是一个String容器用来存储多条消息,不过在此为了简单只放一条消息;
	public String MessageString	
	{
		get{return messageString;}
		set{this.messageString = value;}
	}
	
	/*
	public void storeMessage(String message)
  {
    this.messageString = message; 
    Console.WriteLine("Message: '" + this.messageString + "' have been stored in MessageStore..."); 
  }
  */
  
  public void storeMessage(String message)  //实现接口方法storeMessage(String message);
  {
  	this.messageString = message; 
    Console.WriteLine("Message: '" + this.messageString + "' have been stored in MessageStore..."); 
  }
	
	// 列出MessageStore中已存储的消息;
	public void listMessages()
	{
		Console.WriteLine("Stored message1: '" + this.messageString + "'...[MessageStore]");
	}
}

class MessageChecker : ReceiveMessage
{
	private String checkResult;
	
	public void storeMessage(String message)  //实现接口方法storeMessage(String message);
	{
		this.checkResult = "OK!";
		Console.WriteLine("The message: '" + message + "' has been checked...");
	}
	
	public void showCheckResult()
	{
		Console.WriteLine("The checkResule is: " + this.checkResult + " [MEssageChecker]");
	}
}

class Test
{
	public static void Main()
	{
		MessageCenter messageCenter = new MessageCenter();
		MessageStore messageStore = new MessageStore();
		MessageChecker messageChecker = new MessageChecker();
		
		messageCenter.addReceiver(messageStore);
		messageCenter.addReceiver(messageChecker);
		
		messageCenter.newMessage("Hello world!");	 //新建消息Hello world;
		//messageCenter.notice(messageStore);		//通知messageStore有消息需要存储;
		messageCenter.notice();
		messageStore.listMessages();	//列出messageStore中已经存储的消息;
		messageChecker.showCheckResult(); //显示messageChecker的checkResule;
	}
}

输出结果:



可以看到,就这样简单的用delegate改写一下也能使调用变得更方便一些,也使代码看起来更为简洁,但其实我们还可以做的更多。

================================================================================
  • 大小: 29.9 KB
  • 大小: 18.3 KB
  • 大小: 9.6 KB
  • 大小: 5 KB
分享到:
评论

相关推荐

    Observer模式

    Observer模式,也被称为“发布-订阅”模式,是软件设计模式中的行为模式之一。它定义了对象之间的一对多依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都会得到通知并自动更新。Observer模式是实现...

    C#范例——研究生信息系统,提供详细的代码,控件,适合C#初学者借鉴!

    【C#范例——研究生信息系统】是一个专门为C#初学者设计的学习资源,旨在帮助他们理解和掌握C#编程语言在实际项目中的应用。这个系统可能是针对研究生教育管理的一个完整解决方案,涵盖了学生信息管理、课程管理、...

    深入浅出设计模式(中文版电子版)

    3.1.4C#实例2——学校登录系统 29 3.1.5Java实例——手机简单工厂 32 3.1.6优势和缺陷 34 3.1.7应用情景 34 3.2FactoryMethodPattern(工厂方法模式) 35 3.2.1定义 35 3.2.2现实例子——兵工厂 36 3.2.3C#...

    C#中的委托、事件和Observer设计模式使用方法示例

    在C#编程语言中,委托、事件和Observer设计模式是构建高效、可扩展的应用程序的重要概念。这篇文档将深入探讨这些主题,以帮助你更好地理解它们的用途和实现方式。 首先,我们来看委托(Delegate)。委托在C#中相当...

    iOS基础——通知代理之NSNotificationCenter、Delegate

    在iOS开发中,通知代理是实现对象间通信的重要机制,主要分为两个方面:NSNotificationCenter和Delegate。这两种方式都允许一个对象监听并响应其他对象的事件,但它们各自有其特性和适用场景。 首先,我们来详细...

    详解C#委托,事件,Observer设计模式

    在C#中,事件和委托是实现Observer模式的有效工具。 通过事件,发布者可以在特定条件下触发通知,而订阅者则可以通过添加事件处理程序来响应这些通知。这种方式不仅降低了对象之间的耦合度,还提高了系统的灵活性和...

    C# 委托和事件在.NET Framework详解

    在C#中,委托可以用于实现Observer设计模式,从而使得代码更加灵活和可扩展。 委托和事件是C#中的重要概念,广泛应用于各个领域。通过了解委托和事件的概念、应用场景和设计模式,可以提高开发效率和代码质量。

    C#中的委托delegate用法的示例详解

    【C#中的委托delegate用法的示例详解】 在C#编程语言中,委托是类型安全的函数指针,允许我们将方法作为参数传递给其他方法,或者存储在类的字段中,以便稍后调用。这种特性使得委托成为C#中实现事件处理和回调机制...

    C#设计模式(17)——观察者模式(Observer Pattern).pdf

    从生活中的例子可以看出,只要对订阅号进行关注的客户端,如果订阅号有什么更新,就会直接推送给订阅了的用户。从中,我们就可以得出观察者模式的定义。  观察者模式定义了一种一对多的依赖关系,让多个观察者对象...

    LINUX C# OBSERVER MEMENTO COMPOSITE COMMAND CHAINOFRESPONSIBILITY.tar.bz2

    LINUX C# OBSERVER MEMENTO COMPOSITE COMMAND CHAINOFRESPONSIBILITY.

    c# 中的委托 详细讲解了如何使用c#中的委托机制

    下面我们将深入讲解委托的定义、使用委托的原因、事件的由来、委托和事件对 Observer 设计模式的意义、.Net Framework 中的委托和事件。 委托的定义 委托是一个类型,可以将方法作为参数传递给它,然后在后续使用时...

    设计模式代码——c#

    C#设计模式(23种设计模式) 1. 单件模式(Singleton Pattern) 2. 抽象工厂(Abstract Factory) 3. 建造者模式(Builder) 4. 工厂方法模式(Factory Method) 5. 原型模式(Prototype) 结构型: 6. 适配器...

    Observer-based H∞ Event-triggered Control for Piecewise Affine Systems

    线性矩阵不等式(LMI)是数学中处理线性矩阵之间关系的一种方法,因其在处理约束条件和优化问题时具有方便易用的特点,常被用于控制系统的稳定性分析和控制器设计。 蒋永豪与吴炜的这篇论文中,结合了观测器理论、...

    Observer设计模式实例

    Observer设计模式,也被称为“发布-订阅”(Publish-Subscribe)模式或“依赖倒置”模式,是软件设计中的一种行为模式。...在Java、C#、Python等面向对象语言中,都有内置的Observer支持,使得实现这一模式更加便捷。

    C#面向对象设计模式纵横谈(19):(行为型模式) Observer 观察者模式 (Level 300)

    在C#中实现观察者模式,通常涉及两个关键角色:主题(Subject)和观察者(Observer)。主题是被观察的对象,它维护了一个观察者列表,并提供方法供观察者注册和注销;观察者则表示对主题状态变化感兴趣的实体,它们...

    重温Observer模式--热水器·改

    在这个“重温Observer模式--热水器·改”的讨论中,作者将再次阐述如何不依赖C#的委托和事件来实现Observer模式,而是采用GOF(GoF,Gang of Four)的经典方式。 在Observer模式中,有两个核心角色:Subject(主题...

    委托实现C#观察者模式简单例子

    在C#编程中,观察者模式(Observer Pattern)是一种行为设计模式,它允许你定义一个订阅机制,可以在对象状态改变时通知多个“观察”该对象的其他对象。在这个例子中,我们将通过使用委托来实现这一模式。委托在C#中...

    委托、事件与Observer设计模式

    委托、事件和Observer设计模式是面向对象编程中的关键概念,特别是在C#中有着广泛的应用。本文将深入探讨这三个概念,并通过实例帮助初学者理解和掌握它们。 首先,让我们从委托(Delegate)开始。委托在C#中可以被...

Global site tag (gtag.js) - Google Analytics