NET课件--第4部分PPT文档格式.ppt
- 文档编号:13881036
- 上传时间:2022-10-14
- 格式:PPT
- 页数:60
- 大小:534.50KB
NET课件--第4部分PPT文档格式.ppt
《NET课件--第4部分PPT文档格式.ppt》由会员分享,可在线阅读,更多相关《NET课件--第4部分PPT文档格式.ppt(60页珍藏版)》请在冰豆网上搜索。
/给变量赋值委托(delegate)也可以看成是一种数据类型,可以用于定义变量。
但它是一种特殊的数据类型,它所定义的变量能接收的数值只能是一个函数,更确切地说,委托类型的变量可以接收一个函数的地址,很类似于C/C+语言的函数指针。
简单地说:
委托变量可看成是一种类型安全的函数指针,它只能接收符合其要求的函数引用。
17.1.1理解委托的概念,ublicclassMathOptpublicintAdd(intargument1,intargument2)returnargument1+argument2;
publicdelegateintMathOptDelegate(intvalue1,intvalue2);
classProgramstaticvoidMain(stringargs)MathOptDelegateoppDel;
MathOptobj=newMathOpt();
oppDel=obj.Add;
Console.WriteLine(oppDel(1,2);
/输出3/Console.ReadKey();
示例1:
从上述示例中可得到一个直观的印象:
委托可以看成是一个函数的“容器”,将某一具体的函数“装入”后,就可以把它当成函数一样使用。
其实,委托是一个派生自Delegate的类,但从使用角度理解为函数“容器”也是可以的。
那么,是不是所有的函数都可以赋值给委托类型MathOptDelegate的变量oppDel呢?
注意MathOptDelegate的定义语句:
它规定了委托类型的变量只能接收这样的函数:
拥有两个int类型的参数,并且返回值类型也是int。
只要是满足上述要求的函数,不管名字如何,也不管是静态的还是实例的,都可以传给委托类型的变量oppDel,并通过oppDel来“间接地”调用它们。
定义委托类型时对函数的要求被称为函数的“签名(Signature)”。
函数的签名规定了函数的参数数目和类型,以及函数的返回值,体现了函数的本质特征。
每一个委托都确定了一个函数的签名。
拥有不同签名的函数不能赋值给同一类型的委托变量。
13.1.2委托的组合与分解,委托不仅可以代表一个函数,还可以组合“一堆”的函数,然后批量执行它们。
下面示例2,展示了委托变量之间的组合与分解。
delegatevoidMyDelegate(strings);
classMyClasspublicstaticvoidHello(strings)Console.WriteLine(您好,0!
s);
publicstaticvoidGoodbye(strings)Console.WriteLine(再见,0!
classProgramstaticvoidMain(stringargs)MyDelegatea,b,c,d;
/创建引用Hello方法的委托对象aa=MyClass.Hello;
Console.WriteLine(调用委托变量a:
);
a(a);
/创建引用Goodbye方法的委托对象bb=MyClass.Goodbye;
Console.WriteLine(调用委托变量b:
b(b);
请仔细看以下代码:
/a和b两个委托合成c,c=a+b;
Console.WriteLine(调用委托变量c:
c(c=a+b);
/c将按顺序调用两个方法/从组合委托c中移除a,只留下b,用d代表移除结果,d=c-a;
Console.WriteLine(调用委托变量d:
d(d=c-a);
/后者仅调用Goodbye方法:
Console.ReadKey();
上述代码中委托变量c组合了两个委托变量a和b,因而,它拥有两个函数,当执行“c(“c=a+b”);
”时,将导致MyClass类的两个静态函数都被执行。
像c这样的委托变量又称为“多路委托变量”。
可以用加法运算符来组合单个委托变量为多路委托变量。
也可以使用减法运算符从一个多路委托变量中移除某个委托变量。
上述示例2运行结果为:
17.1.3委托揭秘,编译器和CLR怎样来实现委托?
使用ildasm查看示例1Main()方法的代码:
staticvoidMain(stringargs)MathOptDelegateoppDel;
/输出3注意:
通过委托变量间接调用对象obj的实例方法Add(),实际上调用的是MathOptDelegate类的Invoke()方法。
这个Invoke()方法从何而来?
委托定义语句:
当编译器遇到这段代码时,它会产生如下面所示的一个完整的类定义:
publicclassMathOptDelegate:
System.MulticastDelegatepublicMathOptDelegate(Objecttarget,Int32methodPtr);
publicvoidvirtualInvoke(Int32value1,Int32value2);
publicvirtualIAsyncResultBeginInvoke(Int32value1,Int32value2,AsyncCallbackcallback,Objectobject);
publicvirtualvoidEndInvoke(IAsyncResultresult);
类的构造器,它接收两个参数target和methodPtr。
target:
引用要调用方法的对象;
methodPtr:
是一个方法指针,代表要调用的对象方法。
方法和源代码中指定的原型一样。
对外界对象实例方法的调用通过Invoke()方法实现。
用于实现异步调用。
编译器定义的类中有4个方法:
一个构造器、Invoke、BeginInvoke,以及EndInvoke。
MathOptDelegate类的方法全部都是虚方法,其对应的方法IL代码为空。
以Invoke()方法为例,其生成的IL代码如下(通过ILDasm查看):
.methodpublichidebysignewslotvirtualinstanceint32Invoke(int32value1,int32value2)runtimemanaged/endofmethodMathOptDelegate:
InvokeC#编译器为委托类型生成的所有方法体都为空!
这个标记告诉CLR,此方法的IL指令将在运行时动态生成。
17.1.4委托调用链,自定义委托其实是从MulticastDelegate类中派生出来的。
Delegate类代表委托基类,而MulticastDelegate类代表“多路广播委托”,言下之意是从Delegate类派生出的委托只能“装有”一个函数,而从MulticastDelegate类派生出来的委托则可以“装有”多个函数,这多个函数首尾相接为一个“委托调用链表”,包容于多路委托变量中(见下图)。
事实上C#编译器将我们定义的委托类型都处理为从MulticastDelegate派生。
示例3介绍“委托调用链”的含义,首先定义一个委托类型MyDelegate与一个类ApublicdelegateintMyDelegate(intvalue);
publicclassApublicintf1(inti)Console.WriteLine(f1.i=0,i);
returni;
publicintf2(inti)i*=2;
Console.WriteLine(f2.i=0,i);
类A中两个方法都符合MyDelegate委托所确定的
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- NET 课件 部分