面试中的委托_第1页
面试中的委托_第2页
面试中的委托_第3页
已阅读5页,还剩9页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、面试中的委托4.3 委托( 1) 委托技术是 .NET 框架中的高级特性之一,也可以说是 .NET 重要技术之一,是在大多数的技术笔试、面试中必定出现的 部分。委托提供了安全的函数回调( CALL BACK )机制, 成为程序员设计灵活简洁的 .NET 程序的重要方法之一。 本章 节将通过介绍委托概念和分析一些常见的委托技术题。 面试题 55 什么是委托 .NET 面试中经常会被提问什么是 C#中的委托,面试官主要 意图是考察应聘者对 .NET 的几个重要特性的了解。 这样的细 节问题往往让程序员不能够准确地回答,读者应该在平时学 习的过程中注意积累。【出现频率】 【关键考点】 委托( Del

2、egate) 委托的特点 【考题分析】 委托是一种引用类型,它是函数指针的托管版本。在C#中,委托是一种可以把引用存储为函数的类型。委托可以引用实 例和静态方法,而函数指针只能引用静态方法。委托的声明 非常类似函数,和函数不同的是委托不带函数体,并且需要使用 Delegate 关键字。委托的声明指定了一个函数签名,其 中包含参数列表和一个返回类型。在定义了委托后,就可以 声明该委托类型的变量,然后可以将这个变量初始化为与该 委托有相同签名的函数进行引用,随后可以使用委托变量调 用该函数。注意:委托虽然与函数指针非常类似,但却不是指针。许多 程序员把 .NET 中的委托理解为安全的函数指针, 这

3、样的理解 是比较牵强的,委托实现的功能和函数指针非常类似的一点 就是提供了程序回调机制。委托的内部实现机制和函数指针在指向方法这一点上是完 全相同的。委托是安全的, 主要因为委托和其他所有的 .NET 成员一样, 均是一种类型, 都是 System.Delegate 的某个派生 类的一个对象。现在来分析一个具体的例子,示例代码如下: using System;namespace MyConsole class SimpleDelegate/定义一个返回为double 类型的委托, 这个委托有一个整型的输入参数public delegate doubleDelegate_Prod(int a);

4、static doublereturnval1 * val1;fn_Prodvalues(int val1)static void Main(stringargs) Delegate_Prod delObj = newDelegate_Prod(fn_Prodvalues);/声明一个委托Console.Write(" 请输入数字 ");int v1 = Int32.Parse(Console.ReadLine();/输入一个整型数值 double res = delObj(v1); /调用委托方法 fn_ProdvaluesConsole.WriteLine("

5、 返回值: " + res);/ 返回结果Console.ReadLine(); 示例代码中,首先通过 public delegate double Delegate_Prod(int a)定义了一种名为 Delegate_Prod 的新类 型,这个类型继承自 System.MulticastDelegate 。它包含一个 名为 Invoke() 的方法,该方法接收一个字符型的参数且没有 任何返回。 这些步骤都是由 C#编译器自动完成的。 然后, 声 明了一个 Delegate_Prod 的对象 delObj ,并且绑定到 fn_Prodvalues 这个静态方法上。运行结果如下:请

6、输入数字 9 返回值: 81 注意:本质上,委托的调用就是执行了在定义委托时所生成 的 Invoke() 方法。C#中的委托类都继承自 System.Delegate 类型。委托类型的声 明与方法签名相似,有一个返回值和任意数目任意类型的参 数。委托是一种可用于封装命名或匿名方法的引用类型。委 托类似于函数指针,但是委托是类型安全和可靠的。面试题 56 C#中被委托的方法必须是静态的吗关于委托的方法是否必须是静态方法这个考题,考察点非常 明确。面试官一般希望了解应聘者是不是仅仅了解如何定义 和简单的使用委托,是否真正掌握理解委托的内部原理。 【出现频率】【关键考点】 静态方法与实例方法的区别

7、分析委托的方法是否必须是静态方法【考题分析】 在分析这个问题之前,先了解 C# 几个基本的概念。在 C#中 最常见的方法就是静态方法和实例方法,它们之间的区别如 表 4.1 所示。表 4.1 静态方法和实例方法的区别静 态 方 法实例方法Static 关键字不需要 static 关键字类名调用实例对象调用可以访问静态成员可以直接访问静态成员不可以直接访问实例成员,需要实例化可以直接访问静态成员不能直接调用实例方法,需要实例化可以直接调用实例方法和静态方法调用前初始化实例化时初始化 如表 4.1 所示,在 C# 中静态方法由关键字 static 来定义。静 态方法不需要实例化该对象,即可以通过类

8、名来访问对象。 相应地,在静态方法中不能直接访问类型中任何非静态成 员。而实例方法,则需要通过具体的实例对象来调用,并且 可以访问实例对象中的任何成员对象。 委托绑定实例方法的分析, 依据 C#实例方法的定义, 当一个 实例方法被调用时,需要通过实例对象来访问,因此绑定实 例方法到委托时,必须同时让委托得到该实例方法的实例对 象的信息。这样, .NET 才能在委托被回调( CallBack )的时 候成功地执行该实例方法。 Delegate.Target 属性是一个指向 目标实例的引用,当绑定实例方法给委托时,该参数会被设 置为该方法所在类型的一个实例对象。 委托绑定静态方法的分析。 Dele

9、gate.Target 属性是一个指向 目标实例的引用,当绑定一个静态方法给委托时,则该参数 会被设置为 null 。 注意:如果委托调用一个或多个实例方法,则此属性返回调 用列表中最后一个实例方法的目标。【答案】 通过上面的分析读者可以清晰地判别,委托不仅能绑定静态 方法,同时也可绑定实例方法。当绑定实例方法时, Delegate.Target 属性将会设置成指向该实例方法所属类型的 一个实例对象,当绑定静态方法时, Delegate.Target 属性将会被设置成 null4.3 委托( 2)面试题 57 什么是多播委托 每个委托都只包含一个方法调用,调用委托的次数与调用方 法的次数相同。

10、如果要调用多个方法,就需要多次显式调用 这个委托。当然委托也可以包含多个方法,这种委托称为多 播委托。下面将详细分析这个问题。【出现频率】【关键考点】 多播委托的基本概念System.MulticastDelegate 的特性 【考题分析】 在本章前文中,笔者已经详细地介绍了委托的基本概念。而 所谓的多播委托, 是指引用多个方法的委托, 当调用委托时, 它连续调用每个方法。在调用过程中,委托必须为同类型, 返回类型也必须是 void ,且不能带输出参数(但可以带引用 参数),这样才能将委托的单个实例合并为一个多播委托。 除此之外,多番委托的声明和实例化方法都和其他委托没有 什么不同。现在来看一

11、个实际的例子,示例代码如下: using System; namespace MyConsole class MulticastDelegate /定义委托, 接收一个字符型参数public delegate voidhellokittyHander(string msg);private voidhellokitty1(string msg)/定义一个简单的私有方法hellokitty1()Console.WriteLine("hello kitty1" +msg);msg)private void hellokitty2(string/定义一个的私有方法hellokit

12、ty2()简单msg);msg)私有方法hellokitty3()Console.WriteLine("hello kitty2" +private void hellokitty3(string/定义一个简单的Console.WriteLine("hello kitty3" +msg);static void Main(string args)MulticastDelegate SimpleDelegate = newMulticastDelegate();/ 声明一个委托变量, 并绑定第一个方法hellokittyHander hellokitty

13、=newgate.hellokitty1);hellokittyHander(SimpleDele-hellokitty += new hellokittyHander(SimpleDelegate.hellokitty2); /绑定第二个方法 hellokitty += new hellokittyHander(SimpleDelegate.hellokitty3); /绑定第三个方法/删除已经调用委托方法hellokitty -= new hellokittyHander (SimpleDelegate.hellokitty2); if (hellokitty != null) hello

14、kitty(" 这是一个委托 demo"); Console.ReadLine(); 简单分析这个例子,示例代码中首先定义了一个带 string 参 数无返回的委托 hellokittyHander ,在 Main() 函数中声明了一 个 hellokittyHander 的委托变量 hellokitty ,并绑定了第一个方 法 void hellokitty1(string msg) 。然后,通过 hellokitty += new new hellokittyHander(SimpleDelegate.hellokitty1) 初始化了第 二个委托,并且绑定了 void

15、 hellokitty2(string msg) ,同时把 第二个委托挂在第一个委托之后。紧接着,挂上第三个委托 并绑定到 void hellokitty3(string msg) 。这是一种比较简单明 了的写法,在开发 ASP.NET 或者 Windows 应用程序时,当 一个按钮事件被添加时, Visual Studio 就会为程序生成类似 的代码。代码运行结果如下: hello kitty1 这是一个委托 demo hello kitty3 这是一个委托 demo 在这里读者可能会对这个输出的代码产生困惑, 为什么 hello kitty2 没有被输出。事实上细心的读者会发现在上面的程序

16、 中有一句取消绑定的事件,代码如下: /删除已经调用委托方法 hellokitty -= new hellokittyHander (SimpleDelegate.hellokitty2); 注意:多播委托是指一个委托的链表,而不是指另一类特殊 的委托。当执行链上的一个方法,后续委托方法将会依次被 执行。 System.MulticastDelegate 定义了对多播委托的支持。 【答案】 多播委托是指一个由委托串成的链表,当链表上的一个委托 被回调时,所有链表上该委托的后续委托将会被顺序执行。 但要注意, 多播委托必须是同类型的, 返回类型必须是 void, 并且不能带输出参数(但可以带引用

17、参数) 。面试题 58 列举一个 C#中的委托应用列举 C#中的委托应用是一个比较抽象的问题, 面试官旨在考 察应聘者对委托的使用经验和设计能力。为了解释这一问 题,本小节将带领读者实际体会一个具体的例子。为了能够 熟悉地运用委托,读者仍然需要在实际工作学习中不断地积 累经验。【出现频率】【关键考点】委托的设计 委托的应用【考题分析】 排序系统在大多数系统中都有所应用,在本小节中,笔者将 举一个学生成绩排序的例子来说明委托的实际应用。下列代 码展示了这个学生成绩排序系统的简单实现方式。示例中定义了学生类型的基本成员、构造方法,在私有构造 方法中, 为学生排序委托定义了默认的逻辑, 示例代码如下

18、:/学生类class Studentprivate string name;/ 姓名字段private decimal score;/ 成绩字段public Student(string name,decimal score) / 构造函数、参数 姓名和成绩 = name;this.score = score;/比较方法/<param name="lhs"> 左侧学生对象 </param> /<param name="rhs"> 右侧学生对象 &

19、lt;/param>/<returns> 右侧学生对象的成绩高则返回 true</returns>public static bool RhsIsGreater(object lhs, object rhs)Student studentL = (Student)lhs;Student studentR = (Student)rhs;return (studentR.score > studentL.score) ? true : false;/<returns> 预定义格式的输出

20、</returns>/重写 ToString 方法,可以使得输出更加清晰,输出预定义 格式public override string ToString()return string.Format(name + " : " + score);4.3 委托( 3) 定义成绩排序的委托方法,并将这个方法添加到委托对象之 中。以下示例代码使用冒泡法排序法对数组进行排序。 /<summary> / 排序类, 方法 Sort 为静态方法, 使用冒 泡法 /</summary> class ScoreS

21、ort /<summary> / 冒泡法排序/</summary> /<param name="sortArray"> 要进行排序的数组 </param> /<param name="Method"> 排序的方法 </param> static public void Sort(object sortArray, CompareOp Method) / 外围第一次循环for (int i

22、= 0; i <sortArray.Length; i+) / 第二次 循环for (int j = i + 1; j < sortArray.Length;j+) / 比较大小并交换if (Method(sortArrayj, sortArrayi) object temp = sortArrayi; sortArrayi = sortArrayj;sortArrayj =temp; 最后可以编写测试代码,来测试学生排序的功能,示例代码 如下: class StudentSort /定义一个委托delegatebool CompareOp(object lhs, object

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论