您的位置:首页 > 编程语言 > C#

CLR via C# 读书笔记 委托

2012-07-12 10:59 357 查看
初识委托

委托是一种定义方法签名的类型。实例化委托时,可以将其实例与任何具有兼容签名的方法相关联。通过委托实例调用方法。委托用于将方法作为参数传递给其他方法。事件处理就是通过委托调用的方法

声明一个委托

//声明一个委托类型
//方法获取2个Int32类型的参数 ,返回值为void
public delegate void PerformCalculation(int num1, int num2);


使用委托

直接上代码:

View Code

//声明委托
internal delegate void PerformCalculation(int num1, int num2);

static void Main(string[] args)
{
//创建委托对象 new运算符实例化委托
PerformCalculation myDelegate = new PerformCalculation(Add);
//调用委托
myDelegate(100, 100);
Program p = new Program();
CallBack(1000, 10, p.Division);
//快捷语法实例化委托
PerformCalculation myDelegate1 = Minus;
myDelegate1(200, 10);

ChainDelegateDemo1(p);
ChainDelegateDemo2(p);
Console.ReadKey();
}
public static void ChainDelegateDemo1(Program p)
{
Console.WriteLine("****** chain delegate demo ******");
PerformCalculation pc1=new PerformCalculation (Add);
PerformCalculation pc2 = new PerformCalculation(Minus);
PerformCalculation pc3 = new PerformCalculation(p.Division);
PerformCalculation pc4 = new PerformCalculation(Multiply);
PerformCalculation pcChain = null;
pcChain = (PerformCalculation)Delegate.Combine(pcChain, pc1);
pcChain = (PerformCalculation)Delegate.Combine(pcChain, pc2);
pcChain = (PerformCalculation)Delegate.Combine(pcChain, pc3);
pcChain = (PerformCalculation)Delegate.Combine(pcChain, pc4);
pcChain(100, 50);
}

public static void ChainDelegateDemo2(Program p)
{
Console.WriteLine("****** chain delegate demo2 ******");
PerformCalculation pc1 = new PerformCalculation(Add);
PerformCalculation pc2 = new PerformCalculation(Minus);
PerformCalculation pc3 = new PerformCalculation(p.Division);
PerformCalculation pc4 = new PerformCalculation(Multiply);
PerformCalculation pcChain = null;
pcChain += pc1;
pcChain += pc2;
pcChain += pc3;
pcChain += pc4;
pcChain(200, 100);
}

public static void CallBack(int num1, int num2, PerformCalculation cal)
{
if (cal!=null)
{
cal(num1, num2);
}
}
public static void Add(int num1, int num2)
{
Console.WriteLine(num1 + num2);
}
public static void Multiply(int num1, int num2)
{
Console.WriteLine(num1 * num2);
}
public static void Minus(int num1, int num2)
{
Console.WriteLine(num1 - num2);
}
public void Division(int num1, int num2)
{
Console.WriteLine(num1 / num2);
}


Program 类定义了静态方法CallBack。CallBack方法获取2个Int32类型的整数,一个PerformCalculation委托对象的引用。CallBack内部地用 cal变量指定的回调方法。Program 类中Add、Multiply、Minus为静态方法,Division为实例方法。

总结:

委托声明使用关键字delegate,与方法相似又返回值和签名,但是没有方法体

实例化委托对象时可以使用new运算符,也可以是用快捷语法

委托揭秘

编译器生成的代码:





1、声明的委托PerformCalculation被编译成同名的类,包含一个构造器,3个方法(BeginInvoke、EndInvoke、Invoke),完整的PerformCalculation类

internal class PerformCalculation : System.MulticastDelegate
{
public PerformCalculation(object obj, IntPtr method);

public virtual void Invoke(Int32 num1, Int32 num2);

public virtual IAsyncResult BeginInvoke(Int32 num1,Int32 num2,AsyncCallback callback,Object obj);

public virtual void EndInvoke(IAsyncResult result);

}


2、所有的委托都派生自System.MulticastDelegate类,System.MulticastDelegate派生自System.Delegate类。

System.MulticastDelegate类的3个重要的非公共字段  

字段类型

说明
_targetSystem.Object当委托对象包装一个静态方法时,这个字段为null。当委托对象包装一个实例方法时,这个字段引用的回调方法要操作的对象。

换言之,这个字段指出要传给实例方法的隐式参数this的值

_methodPtr  System.IntPtr一个内部的整数值,CLR用它标识要回调的方法
_invocationListSystem.Object该字段通常为null。构造一个委托链时,它可以引用一个委托数组
Delegate类中定义了两个只读的公共实例属性,分别是Target和Method,Target属性返回保存在私有字段_target中的值。如果委托对象包装的是一个静态方法,Target将返回null。Method属性返回对一个System.Reflection.MethodInfo对象的引用,该对象标识了回调方法。实际例子:

//创建委托对象 new运算符实例化委托
PerformCalculation myDelegate = new PerformCalculation(Add);
//调用委托
myDelegate(100, 100);

Console.WriteLine("Target:{0} Method:{1}",myDelegate .Target,myDelegate.Method);
Program p = new Program();

myDelegate=p.Division;
myDelegate(100, 100);
Console.WriteLine("Target:{0} Method:{1}",myDelegate .Target,myDelegate.Method);


调用结果:



委托链

委托链是由委托对象构成的一个集合。利用委托链,可以调用集合中的委托所包装的全部方法。
委托链示例见demo,ChainDelegateDemo1、ChainDelegateDemo2 方法。

构造委托链会使用System.Delegate 的Combine静态方法,移除委托使用System.Delegate 的Remove静态方法。C#编译器自动为委托类型的实例重载了+= 和-=操作符。操作符分别调用System.Delegate.Combine和System.Delegate.Remove

当构造委托链时,_invocationList字段会被初始化为引用一个委托对象的数组,这一点也非常重要

园中的优秀文章

C# 中的委托和事件

读<<CLR via C#>>总结(10) 详谈委托

跟小静学CLR via C#(12)-委托Delegate
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: