
面试中的委托.docx
14页面试中的委托4.3委托(1)委托技术是.NET框架中的高级特性之一,也可以说是.NET重要技术之一,是在大多数的技术笔试、面试中必定出现的部分委托提供了安全的函数回调(CALLBACK)机制,成为程序员设计灵活简洁的.NET程序的重要方法之一本章节将通过介绍委托概念和分析一些常见的委托技术题面试题55什么是委托.NET面试中经常会被提问什么是C#中的委托,面试官主要意图是考察应聘者对.NET的几个重要特性的了解这样的细节问题往往让程序员不能够准确地回答,读者应该在平时学习的过程中注意积累由现频率】★★★★★【关键考点】委托(Delegate)委托的特点【考题分析】委托是一种引用类型,它是函数指针的托管版本在C#中,委托是一种可以把引用存储为函数的类型委托可以引用实例和静态方法,而函数指针只能引用静态方法委托的声明非常类似函数,和函数不同的是委托不带函数体,并且需要使用Delegate关键字委托的声明指定了一个函数签名,其中包含参数列表和一个返回类型在定义了委托后,就可以声明该委托类型的变量,然后可以将这个变量初始化为与该委托有相同签名的函数进行引用,随后可以使用委托变量调用该函数注意:委托虽然与函数指针非常类似,但却不是指针。
许多程序员把.NET中的委托理解为安全的函数指针,这样的理解是比较牵强的,委托实现的功能和函数指针非常类似的一点就是提供了程序回调机制委托的内部实现机制和函数指针在指向方法这一点上是完全相同的委托是安全的,主要因为委托和其他所有的.NET成员一样,均是一种类型,都是System.Delegate的某个派生类的一个对象现在来分析一个具体的例子,示例代码如下:usingSystem;namespace MyConsole {{ // 定义一个返回为有一个整型的输入参数Delegate_Prod(int a);fn_Prodvalues(int val1)val1 * val1; }class SimpleDelegatedouble 类型的委托, 这个委托public delegate doublestatic double{ returnstatic void Main(string[]args){Delegate_ProddelObj=newDelegate_Prod(fn_Prodvalues);//声明一个委托Console.Write("请输入数字");intv1=Int32.Parse(Console.ReadLine());//输入一个整型数值doubleres=delObj(v1);//调用委托方法fn_ProdvaluesConsole.WriteLine("返回值:"+res);//返回结果Console.ReadLine();}}}示例代码中,首先通过publicdelegatedoubleDelegate_Prod(inta)定义了一种名为Delegate_Prod的新类型,这个类型继承自System.MulticastDelegate。
它包含一个名为Invoke()的方法,该方法接收一个字符型的参数且没有任何返回这些步骤都是由C#编译器自动完成的然后,声明了一个Delegate_Prod的对象delObj,并且绑定到fn_Prodvalues这个静态方法上运行结果如下:请输入数字9返回值:81注意:本质上,委托的调用就是执行了在定义委托时所生成的Invoke()方法C#中的委托类都继承自System.Delegate类型委托类型的声明与方法签名相似,有一个返回值和任意数目任意类型的参数委托是一种可用于封装命名或匿名方法的引用类型委托类似于函数指针,但是委托是类型安全和可靠的面试题56C#中被委托的方法必须是静态的吗关于委托的方法是否必须是静态方法这个考题,考察点非常明确面试官一般希望了解应聘者是不是仅仅了解如何定义和简单的使用委托,是否真正掌握理解委托的内部原理由现频率】★★★★★【关键考点】静态方法与实例方法的区别分析委托的方法是否必须是静态方法【考题分析】在分析这个问题之前,先了解C#几个基本的概念在C#中最常见的方法就是静态方法和实例方法,它们之间的区别如表4.1所示表4.1静态方法和实例方法的区别静态方法实例方法Static关键字不需要static关键字类名调用实例对象调用可以访问静态成员可以直接访问静态成员不可以直接访问实例成员,需要实例化可以直接访问静态成员不能直接调用实例方法,需要实例化可以直接调用实例方法和静态方法调用前初始化实例化时初始化如表4.1所示,在C#中静态方法由关键字static来定义。
静态方法不需要实例化该对象,即可以通过类名来访问对象相应地,在静态方法中不能直接访问类型中任何非静态成员而实例方法,则需要通过具体的实例对象来调用,并且可以访问实例对象中的任何成员对象委托绑定实例方法的分析,依据C#实例方法的定义,当一个实例方法被调用时,需要通过实例对象来访问,因此绑定实例方法到委托时,必须同时让委托得到该实例方法的实例对象的信息这样,.NET才能在委托被回调(CallBack)的时候成功地执行该实例方法Delegate.Target属性是一个指向目标实例的引用,当绑定实例方法给委托时,该参数会被设置为该方法所在类型的一个实例对象委托绑定静态方法的分析Delegate.Target属性是一个指向目标实例的引用,当绑定一个静态方法给委托时,则该参数会被设置为null注意:如果委托调用一个或多个实例方法,则此属性返回调用列表中最后一个实例方法的目标答案】通过上面的分析读者可以清晰地判别,委托不仅能绑定静态方法,同时也可绑定实例方法当绑定实例方法时,Delegate.Target属性将会设置成指向该实例方法所属类型的一个实例对象,当绑定静态方法时,Delegate.Target属性将会被设置成null4.3委托(2)面试题57什么是多播委托每个委托都只包含一个方法调用,调用委托的次数与调用方法的次数相同。
如果要调用多个方法,就需要多次显式调用这个委托当然委托也可以包含多个方法,这种委托称为多播委托下面将详细分析这个问题由现频率】★★★★【关键考点】多播委托的基本概念System.MulticastDelegate的特性【考题分析】在本章前文中,笔者已经详细地介绍了委托的基本概念而所谓的多播委托,是指引用多个方法的委托,当调用委托时,它连续调用每个方法在调用过程中,委托必须为同类型,返回类型也必须是void,且不能带输出参数(但可以带引用参数),这样才能将委托的单个实例合并为一个多播委托除此之外,多番委托的声明和实例化方法都和其他委托没有什么不同现在来看一个实际的例子,示例代码如下:usingSystem;namespaceMyConsole{classMulticastDelegate{//定义委托,接收一个字符型参数publicdelegatevoidhellokittyHander(stringmsg);privatevoidhellokitty1(stringmsg)//定义一个简单的私有方法hellokitty1(){Console.WriteLine("hellokitty1"+msg);}privatevoidhellokitty2(stringmsg)//定义一个简单的私有方法hellokitty2(){Console.WriteLine("hellokitty2"+msg);}privatevoidhellokitty3(stringmsg)//定义一个简单的私有方法hellokitty3(){Console.WriteLine("hellokitty3"+msg);}staticvoidMain(string[]args){MulticastDelegateSimpleDelegate=newMulticastDelegate();//声明一个委托变量,并绑定第一个方法hellokittyHanderhellokitty=gate.hellokitty1);newhellokittyHander(SimpleDele-hellokitty+=newhellokittyHander(SimpleDelegate.hellokitty2);//绑定第二个方法hellokitty+=newhellokittyHander(SimpleDelegate.hellokitty3);//绑定第三个方法//删除已经调用委托方法hellokitty-=newhellokittyHander(SimpleDelegate.hellokitty2);if(hellokitty!=null)hellokitty("这是一个委托demo");Console.ReadLine();}}}简单分析这个例子,示例代码中首先定义了一个带string参数无返回的委托hellokittyHander,在Main()函数中声明了一个hellokittyHander的委托变量hellokitty,并绑定了第一个方法voidhellokitty1(stringmsg)。
然后,通过hellokitty+=newnewhellokittyHander(SimpleDelegate.hellokitty1)初始化了第二个委托,并且绑定了voidhellokitty2(stringmsg),同时把第二个委托挂在第一个委托之后紧接着,挂上第三个委托并绑定到voidhellokitty3(stringmsg)这是一种比较简单明了的写法,在开发ASP.NET或者Windows应用程序时,当一个按钮事件被添加时,VisualStudio就会为程序生成类似的代码代码运行结果如下:hellokitty1这是一个委托demohellokitty3这是一个委托demo在这里读者可能会对这个输出的代码产生困惑,为什么hellokitty2没有被输出事实上细心的读者会发现在上面的程序中有一句取消绑定的事件,代码如下://删除已经调用委托方法hellokitty-=newhellokittyHander(SimpleDelegate.hellokitty2);注意:多播委托是指一个委托的链表,而不是指另一类特殊的委托当执行链上的一个方法,后续委托方法将会依次被执行System.MulticastDelegate定义了对多播委托的支持。
答案】多播委托是指一个由委托串成的链表,当链表上的一个委托被回调时,所有链表上该委托的后续委托将会被顺序执行但要注意,多播委托必须是同类型的,返回类型必须是void,并且不能带输出参数(但可以带引用参数)面试题58列举一个C#中的委托应用列举C#中的委托应用是一个比较抽象的问题,面试官旨在考察应聘者对委托的使用经验和设计能力为了解释这一问题,本小节将带领读者实际体会一个具体的例子为了能够熟悉地运用委托,读者仍然需要在实际工作学习中不断地积累经验由现频率】★★★★【关键考。
