木老师教笨笨课堂——系列讲座(从函数指针到委托) 四、C#的委托

四、C#的委托
“.Net以委托的形式实现了函数指针的概念。”——《C#高级编程(第四版)》
现在看这句话,可能笨笨同学就有感觉了。
看书可能就是这样,想当初天山童姥的缥缈峰灵鹫宫里一幅武功秘籍的壁画,她只允许侍女每年进去看一次。虚竹和尚成为灵鹫宫主人,心善允许侍女和他一同进去练功,虚竹练完顿觉神清气爽,而侍女们则有走火入魔之感。Why?功力尚浅。一本书初看,淡如开水,原因可能功力尚浅,当然还有一种原因,尽管我们不想承认,就是这本书实在是......太烂了。如果果真遇到一本好书,我们在看不懂的时候,不妨把它垫桌角,砸人等等干什么都行,就是不要再死读下去。过得半月,三月,半年或者一年,再读很有可能打通任督二脉,气贯丹田。
笨笨:“老师,讲课了。”
咳........咳.........(讲课,讲课,我是老师还是你是老师?)
好,首先我们看一看,如何在C#中声明委托
在C#中声明委托,就好像在C里声明函数指针一样,比如定义一个委托TwoLongsOp,该委托代表的函数有两个long型参数,返回类型为double,则写成如下形式:
delegate double TwoLongsOp(long first,long second);
紧接着我们就是在C#中使用委托
在C#中使用委托就好比 我们把函数指针指向相应的函数,然后调用该函数指针。讲这个我们将分为如下几种讲解,一 委托PK函数指针 内容:指向类的方法 二 委托PK函数指针 内容:作为函数参数 三 委托PK函数指针 内容:指向静态函数四 函数指针数组PK多播委托。
 
一 函数指针PK委托 内容:指向类的方法
(1)函数指针:
在第三节里,我们已经讲过,函数指针的声明和调用如下,具体参见第三节:
void (CA::*f1)();
f1 = CA::Fun;
CA a;
(a.*f1)();
(2)委托
delegate void FunDelegate();
CA a;
FunDelegate funMethod = new FunDelegate(a.Fun);
funMethod();
 
二 委托PK函数指针 内容:作为函数参数
(1)函数指针:
void CallFun(void (*f)())
{
       f();
}
 
void (*f)();
f = CA::StaticFun; // StaticFun 是CA的静态函数
CallFun(f);
(2) 委托:
delegate void FunDelegate();
FunDelegate funMethod = new FunDelegate(CA.StaticFun);
CallFun(funMethod);                                        //实际上这并不符合C#语法,因为在C#里没有全局函数,这里是为了上下文比较。
 
三 委托PK函数指针 内容:指向静态函数
(1)函数指针:
void (*f)();
f = CA::StaticFun; // StaticFun 是CA的静态函数
f();
(2) 委托:
delegate void FunDelegate();
FunDelegate funMethod = new FunDelegate(CA.StaticFun);
funMethod();
 
四 函数指针数组PK多播委托
(1)函数指针数组:
typedef void (*PFV)();
PFV funarray[2];
funarray[0] = CA::StaticFun;
funarray[1] = CA::StaticFun;
 
funarray[0]();
funarray[1]();
 
(2)多播委托
delegate void FunDelegate();
FunDelegate funMethod1 = new FunDelegate(CA.StaticFun);
FunDelegate funMethod2 = new FunDelegate(CA.StaticFun);
FunDelegate funMethods = funMethod1 + funMethod2
 
其实通过上述的比较,无疑委托比函数指针实现的更为优雅,无论是数组,静态函数,类成员函数,作为函数参数和多播委托。委托都是用的同一种方式,容易掌握。而函数指针则没有这么简单地掌握。
而且委托是一种类型安全的操作。所谓“类型安全”和函数指针相比较可以体现在如下方面:
委托示例:
public delegate string GetAString();
GetAString firstStringMethod = new GetAString(null);
提示错误:“应输入方法名称”
创建一个委托的时候,不可能将一个空值作为构造函数的参数传给委托;
 
函数指针示例:
void (*f)();
f = NULL;             // f被赋成空值 或者不赋值 程序编译都会通过
f();
这段代码编译完全没有问题,但是程序运行的时候则会出问题。程序员有时候很容易将函数指针未赋值或者赋成空值。
 
 
嘘 这个问题总算讲完了。当我第一次看到委托的时候,其实我很震惊,因为没有想到能够用如此优雅的方式来实现。原来我以为C++中的纯虚函数机制,组件模型中的连接点机制就已经达到极致,但是委托则更为简明。真的是由于震撼才写出此文。仅以此文对微软和程序界的精英和前辈们表示敬意。
posted @ 2008-12-02 14:50  helloj2ee  阅读(367)  评论(0编辑  收藏  举报