面试常见题

1.委托是什么?★☆
2.为什么需要委托?★☆
3.委托能用来做什么?★☆
4.如何自定义委托★☆
5…NET默认的委托类型有哪几种?★☆
6.怎样使用委托?★★★
7.多播委托是什么?★★★
8什么是泛型委托?★★★
9.什么是匿名方法?★★
10.委托是否可以回调实例方法★★★
11.Lambda表达式是什么?★
12.Lambda表达式怎么传参?★★★
13.Lambda多行代码怎么写?★★
14.什么是闭包?★★
事件的面试题我放在下一篇里面。看完这些题目,心中是否有疑惑呢?那就接着看呗,我来帮您解答心中的疑惑o()o
参考答案:
1.委托是什么?★☆
本题主要考察委托的概念:委托是寻址的.NET版本。在C++中,函数指针只不过是一个指向内存位置的指针,它不是类型安全的。我们无法判断这个指针实际指向什么,像参数和返回类型等项久更无从知晓了。而.NET委托完全不同,委托是类型安全的类,它定义了返回类型和参数的类型。委托类不仅包含对方法的引用,也可以包含对多个方法的引用。
2.为什么需要委托?★☆
本题主要考察直接调用一个方法和通过委托来间接调用委托的区别。在很多场景下直接调用方法是比较简单方便的,但是在某些场景下,使用委托来调用方法能达到减少代码量,实现某种功能的用途,比如说事件。
3.委托能用来做什么?★☆
本题主要考察委托在我们写code时的用途。一个笼统的准则:当要把方法传给其他方法时,需要使用委托。比如下面几个场景: 
 a.启动线程和任务  
   调用System.Threading.Thread的一个实例上使用方法Start(),必须为计算机提供开始启动的方法的事件,即Thread类的构造函数必须带有一个参数,该参数定义线程调用的方法。   
    Thread t = new Thread(new ThreadStart(Go));//public static GO(){}   
     有兴趣的同学可以看下我之前写的多线程的博客:
     干货分享:详解线程的开始和创建  
     b.设计模式中的简单工厂模式。    向一个方法中传递一个子类的方法。  
     c.事件。    一般通知代码发生了什么事件。GUI编程主要处理事件。在引发事件时,运行库需要知道应执行哪个方法。    这就需要处理事件的方法作为一个参数传递给委托。
  4.如何自定义委托★☆
  声明一个委托类型,它的实例引用一个方法,该方法获取一个int参数,返回void。

public delegate void Feedback(int num);

理解委托的一个要点是它们的安全性非常高。在定义委托时,必须给出它所表示的方法的签名和返回类型等全部细节。理解委托的一种比较好的方式是把委托当作这样一件事情:它给方法的签名和返回类型指定名称。

其语法类似于方法的定义,需要在定义方法的前面加上delegate关键字。定义委托基本上就是定义一个新的类,所以可以在任何地方定义类的相同地方定义委托,也就是说,可以在另一个类的内部定义,也可以在任何类的外部定义,还可以在名称控件中把委托定义为定义为顶层对象。访问修饰符可以是public/private/protected等

5…NET默认的委托类型有哪几种?★★
1.Action  泛型Action委托表示引用一个void返回类型的方法。这个委托类存在16种重载方法。  例如Action<in T1,In T2>调用没有参数的方法
2.Func  Func调用带返回类型的方法。有16种重载方法。  例如Func委托类型可以调用带返回类型且无参数的方法,  Func<in T,out TResult>委托类型调用带有4个参数和一个返回类型的方法。
3.等等
6.怎样使用委托★★

 1    // 声明一个委托类型,它的实例引用一个方法,该方法获取一个int参数,返回string2     public delegate String myMethodDelegate(int myInt);3     // 定义一些方法给委托变量引用4     public class mySampleClass5     {6         // 定义一个实例方法7         public String myStringMethod(int myInt)8         {9             if (myInt > 0)
10                 return ("positive");
11             if (myInt < 0)
12                 return ("negative");
13             return ("zero");
14         }
15         // 定义一个静态方法
16         public static String mySignMethod(int myInt)
17         {
18             if (myInt > 0)
19                 return ("+");
20             if (myInt < 0)
21                 return ("-");
22             return ("");
23         }
24     }
25     public static void Main()
26     {
27         // 给每个方法都创建一个委托实例
28         // 对于实例方法,mySC必须提供
29         //   对于静态方法,只需要指定类的名字
30         mySampleClass mySC = new mySampleClass();
31         myMethodDelegate myD1 = new myMethodDelegate(mySC.myStringMethod);
32         myMethodDelegate myD2 = new myMethodDelegate(mySampleClass.mySignMethod);
33         // 调用委托
34         Console.WriteLine("{0} is {1}; use the sign \"{2}\".", 5, myD1(5), myD2(5));
35         Console.WriteLine("{0} is {1}; use the sign \"{2}\".", -3, myD1(-3), myD2(-3));
36         Console.WriteLine("{0} is {1}; use the sign \"{2}\".", 0, myD1(0), myD2(0));
37     }

输出5 is positive; use the sign “+”.
-3 is negative; use the sign “-”.
0 is zero; use the sign “”.
7.多播委托是什么?★★★
包含多个方法的委托叫做多播委托。如果调用多播委托,就可以顺序连续调用多个方法。  为此,委托的签名就必须返回void;否则,就只能得到委托调用的最后一个方法的结果。例子:

1         /// <summary>2         /// 定义委托类型3         /// </summary>4         /// <param name="num"></param>5         /// <returns>void</returns>6         public delegate void Feedback(int num);7          8         /// <summary>9         /// 实例方法
10         /// </summary>
11         /// <param name="b"></param>
12         /// <returns>void</returns>
13         public void InstanceMethod(int a)
14         {
15             Console.WriteLine(a.ToString());
16         }
17         /// <summary>
18         /// 静态方法
19         /// </summary>
20         /// <param name="a"></param>
21         /// <returns>返回void</returns>
22         public static void StaticMethod( int b)
23         {
24             Console.WriteLine((b * b).ToString());
25         }
26
27         //定义一个Program实例
28         Program p = new Program();
29         //委托feedback1指定回调方法:p.InstanceMethod
30         Feedback feedback1 = new Feedback(p.InstanceMethod);
31         //委托feedback2指定回调方法:StaticMethod
32         Feedback feedback2 = new Feedback(StaticMethod);
33         //输出2
34         feedback1(2);
35         //输出4
36         feedback2(2);
37
38         //----多播委托-------
39         Feedback fbChain = null;
40         //将feedback1添加到fbChain委托中
41         fbChain += feedback1;
42         //将feedback2添加到fbChain委托中
43         fbChain += feedback2;
44         //输出:
45         //2
46         //4
47         fbChain(2);

8.什么是泛型委托?★★★
比如第5题提到的,Action就是泛型委托。
注意事项:
  1.建议尽量使用这些委托类型,而不是在代码中定义更多的委托类型。这样可以减少系统中的类型数目,同时简化编码 
  2.如果需要使用ref或out关键字,以传引用的方式传递一个参数,就可能不得不定义自己的委托:

    delegate void Test(ref int i)

3.如果委托要通过C#的params关键字获取可变数量的额参数,要为委托的任何桉树指定默认值,    或者要对委托的泛型类型参数进行约束,也必须定义自己的委托类型

delegate void EventHandler<TEventArgs>(Object sender, TEventArgs e)where TEventArgs : EventArgs;

4.使用获取泛型实参和返回值的委托时,可利用逆变与协变。逆变:父类转换为子类;协变:子类转换为父类
9.什么事匿名方法★★
匿名方法是用作委托的参数的一段代码。

1         //匿名方法,例12         Func<int, int> anon = delegate(int i)3         {4             i = i+1;5             return i;6         };7         //输出28         Console.WriteLine(anon(1));9
10         //匿名方法,例2
11         Action<int> anon2 = delegate(int i)
12         {
13             i = i + 1;
14         };
15         //输出2
16         Console.WriteLine(anon(1));

10.委托是否可以回调实例方法★★★
可以。委托可以回调实例方法和静态方法。如果是实例方法,委托需要知道方法操作的是哪个对象实例。
11.Lambda表达式是什么?★
从C#3.0开始,就可以使用一种新语法把实现代码赋予委托:Lambda表达式。只要有委托参数类型的地方,就可以使用Lambda表达式。
12.Lambda表达式怎么传参?★★★
Lambda表达式有几种定义参数的方式。

1.只有一个参数,只写出参数名就足够了。

如下面的例子:定义了一个泛型委托,输入参数是一个string类型,返回一个string类型,
lambda表达式:s=>s.Replace(‘a,b’)
委托引用的方法名:oneParam
传入参数:abc
打印结果:bbc

1 Func<string, string> oneParam = s => s.Replace('a', 'b');
2 Console.WriteLine(oneParam("abc"));
3 Console.ReadKey();
2.如果委托使用多个参数,就把参数名放在小括号中。

如下面的例子:
定义了一个泛型委托,输入参数是两个int类型(可以给小括号中的变量名添加参数类型),返回一个int类型,
lambda表达式:(i, j) => i*j
委托引用的方法名:twoParam
传入参数:2和4
打印结果:8

1 Func<int, int, int> twoParam = (i, j) => i*j;
2 Console.WriteLine(twoParam(2,4));

13.Lambda多行代码怎么写?★★
添加大括号,如果需要返回值,则必须添加return语句

1 Func<int, int, int> test = (i, j) =>
2 {
3     i = i + 1;
4     i = i * j;
5     return i;
6 };
7 Console.WriteLine(test(2, 4));

打印结果:12
14.什么是闭包?★★
通过Lambda表达式可以访问Lambda表达式块外部的变量,这称为闭包。
当引用外部变量时,需要注意,外部变量变化时,lambda表达式的结果也可能会随着外部变量变化而变化。
如下面的例子:

1 int y = 5;
2 Func<int, int> lambda = x => x + y;
3 Console.WriteLine(lambda(1));
4 y = 10;
5 Console.WriteLine(lambda(1));

第一次打印出6,第二次打印出11

关于委托的知识点还有很多没有总结出来,比如说委托和反射,委托的底层实现等等。面试经常会问到也就是上面总结的。后续还会总结更多关于.NET的知识点。

★★写在最后
委托(delegate)是一种存储函数引用的类型。这听起来相当深奥,但其机制是非常简单的。委托的声明非常类似于函数,但不带函数体,且要使用delegate 关键字。委托的声明制定了一个返回类型和一个参数列表。
定义了委托后,就可以声明该委托类型的变量。接着把这个变量初始化为与委托具有相同返回类型和参数列表的函数引用。之后,就可以使用委托变量调用这个函数,就像该变量是一个函数一样。
有了引用函数的变量后,就可以执行无法用其他方式完成的操作。例如,可以把委托变量作为参数传递给一个函数,这样,该函数就可以使用委托调用它引用的任何函数,而且在运行之前不必知道调用的是哪个函数。下面的示例使用委托访问两个函数中的一个。
(1)在C:\BegVCSharp\Chapter06目录中创建一个新的控制台应用程序Ch06Ex05.
(2)把下列代码添加到Program.cs中:

class  Program
{delegate double ProcessDelegate(double param1, double param2);static double Multiply(double param1,  double param2) =>param1 *param2;static double Divide(double param1, double param2) =>param1/param2; static void Main(string[] args){ ProcessDeletegate process;WriteLine("Enter 2 numbers separated with a comma:");string input  = Readline();int commaPos = input.IndexOf(',');double param1 = ToDouble(input.Substring(0,commaPos));double param2 = ToDouble(input.Substring(commaPos + 1,input.Length - commaPos - 1));WriteLine("Enter M to multiply or D to divide:");input=ReadLine();if(input=="M")process = new ProcessDelegate(Multiply);elseprocess = new ProcessDelegate(Divide);WriteLine($"Result: {process(param1,param2)}");ReadKey();
}
}

(3)执行代码,在看到提示时输入值,便看到结果。
示例说明
这段代码定义了一个委托ProcessDelegate,其返回类型和参数与函数Multiply()和Divide()相匹配。注意Multiply()和Divide()方法使用了C#6引入的=>(Lambda箭头)。
委托的定义如下所示:

 delegate double ProcessDelegate(double param1, double param2);

deletgate关键字指定该定义是用于委托的,而不是用于函数的(该定义所在的位置与函数定义的相同)。接着,该定义指定double返回类型和两个double参数。实际使用的名称可以是任意的,所以可以给委托类型和参数指定任意名称。这里的委托名是ProcessDelegate,double参数名是param1和param2.
Main()中的代码首先使用新的委托类型声明一个变量:

  static void Main(string[] args){ ProcessDeletegate process;

接着用一些比较标准的C#代码请求由逗号分隔的两个数字,并将这些数字放在两个double变量中

  WriteLine("Enter 2 numbers separated with a comma:");string input  = Readline();int commaPos = input.IndexOf(',');double param1 = ToDouble(input.Substring(0,commaPos));double param2 = ToDouble(input.Substring(commaPos + 1,input.Length - commaPos - 1));

接着询问用户,这两个数字是要相乘还是相除:
根据用户的选择,初始化process委托变量:
要把一个函数引用赋给委托变量,需要使用略显古怪的语法。这个过程比较类似于给数组赋值,必须使用new关键字创建一个新委托。在这个关键字的后面,指定委托类型,提供一个引用所需函数的参数,这里也就是Multiply()或Divide()函数。注意这个参数与委托类型或目标函数的参数不匹配,这是委托赋值的一种独特语法,参数是要使用的函数名且不带括号。
实际上,这里可以使用略微简单的语法:

if(input == "M")
process=Multiply;
else
process=Divide;

编译器会发现,process变量的委托类型匹配两个函数的签名,于是自动初始化一个委托。可以自行确定使用那种语法,但一些人喜欢使用较长的版本,因为更容易一眼看出会发生什么。
最后,使用该委托调用所选的函数。无论委托引用的是什么函数,该语法都是有效的:

WriteLine($"Result: {process(param1,param2)}");ReadKey();

这里把委托变量看成一个函数名。但与函数不同,我们还可以对这个变量执行更多的操作,例如,通过参数将其传递给一个函数,如下例所示:

static void ExecuteFunction(ProcessDelegate process) =>process(2.2,3.3);

就像选择一个要使用的“插件”一样,通过函数委托传递给函数,就可以控制函数的执行。例如,一个函数要对字符串数组按照字母进行排序。对列表排序有几个不同的方法,他们的性能取决于要排序的列表特性。使用委托可以把一个排序算法函数委托传递给排序函数,指定要使用的函数。
Comparison: 这个委托类型用于排序方法,其返回类型和参数如下:
int method(T objectA,T objectB)
Predicate:这个委托类型用于搜索方法,其返回类型和参数如下:
bool method(T targrtObject)
可以定义任意多个这样的方法,使用他们实现List的搜索和排序方法。

C#委托之如何理解委托面试常见题:相关推荐

  1. python第三方库有哪些常用的、请列举15个-python基础面试常见题

    Python是目前市面上,我个人认为是最简洁.最优雅.最有前途.最全能的编程语言,没有之一. 2.通过什么途径学习的Python? 通过自学,包括网上查看一些视频,购买一些相关专业的书籍. 3.Pyt ...

  2. python基础笔试面试题_python基础面试常见题

    Python是目前市面上,我个人认为是最简洁.最优雅.最有前途.最全能的编程语言,没有之一. 2.通过什么途径学习的Python? 通过自学,包括网上查看一些视频,购买一些相关专业的书籍. 3.Pyt ...

  3. TCP面试常见题:time_wait状态产生的原因,危害,如何避免

    http://blog.csdn.net/u013616945/article/details/77510925 MSL(Maximum Segment Lifetime)最大报文生存时间       ...

  4. c++面试常见题·Part 3 TCP/IP多线程编程设计模式Linux基操等

    1.TCP/IP 四层模型: (图来源于网络) IP层(网络层)主要协议: ARP(地址解析协议):负责将一个已知的ip地址解析成MAC地址,以便在交换机上进行通信. ICMP(Internet控制消 ...

  5. 大型软件公司.Net面试常见题(含答案)

    1.a=10,b=15,在不用第三方变量的前提下,吧a.b互换 2.已知数组int[] max={6,5,2,9,7,4,0};用快速排序算法按降序对其进行排列,并返回数组 3.请简述面向对象的多态的 ...

  6. 数据库基础(面试常见题)笔试面试题

    一.数据库基础 1. 数据抽象:物理抽象.概念抽象.视图级抽象,内模式.模式.外模式 2. SQL语言包括数据定义.数据操纵(Data Manipulation),数据控制(Data Control) ...

  7. c++面试常见题·Part 2 数据结构和STL

    常用数据结构 数组 :分配空间固定,地址连续,随机取一个数时间复杂度为O(1) 链表(单链表,双链表) 适合快速增删 栈(后进先出) 队列(FIFO先进先出) 树:二叉树遍历(递归方式和非递归方式 ) ...

  8. c++面试常见题·Part 1 基础

    new&delete.malloc&free 都能动态申请内存和释放内存 malloc&free是标准库函数,new&delete是运算符,对于非内部数据类型的对象而言 ...

  9. 计算机网络面试常见题

    文章目录 浏览器输入网址之后发生了什么? 网络体系结构? HTTP和HTTPS的区别? Session和Cookie的区别? HTTP和WebSocket的联系和区别,什么情况下用WebSocket? ...

最新文章

  1. spring cloud互联网分布式微服务云平台规划分析--服务统一配置中心
  2. [1维粒子模拟 version3.6]成功调试read input parameters
  3. 关于 QAbstractItemModel 学习的一点分享
  4. 第十四节: EF的三种模式(四) 之 原生正宗的 CodeFirst模式的默认约定
  5. 陆志勤:记交大数学系二三事
  6. Android 开发总结大全
  7. 多功能pdf编辑器PDF Office Max for mac
  8. 用java语言求老汉卖西瓜程序_Java编程练习题
  9. 【单片机项目实训】51单片机电子秤(语音播报版)
  10. 《现代控制系统》第五章——反馈控制系统性能分析 5.4 二阶系统里面极点以及零点带来的影响
  11. 世界第4疯狂的科学家,在103岁生日那天去世了
  12. 国产工业机器人目前发展到了什么水平?
  13. [bhpyg] QQ互联接口 ,第三方帐号登录
  14. 1143-最长公共子序列的长度和最长公共子序列
  15. 从智能合约的演进看 Move 的架构设计
  16. Google Chrome 浏览器常用快捷键
  17. sql--15回顾学习记录
  18. 计算机应用2010综合测试五,计算机应用基础Word2010综合测试操作步骤参考自测题步骤...
  19. linux pppoe配置文件,linux pppoe服务器配置
  20. STP中,交换机的端口ID为什么要配置为16的倍数?

热门文章

  1. problem 1171
  2. Finger.03 - ESP8266与MQTT服务器通信
  3. 10月第1周安全回顾 微软下周发补丁包 小型僵尸网络增多
  4. 震惊,登入P站的post_key竟然在!!!
  5. 使用八叉树结构来管理场景
  6. C++ | 标准库 string 的内存结构(前8字节是指针,接着8字节是字符个数,最后16字节可能是字符串本身)
  7. RPA技术这么强,为什么机器人还会让人失望呢?
  8. 1x9 Dual SC Optical Transceivers
  9. 读书记录|《2001 太空漫游》
  10. c语言建立位图坐标,位图(bitmap)—— C语言实现