面试常见题:

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<T>

  泛型Action<T>委托表示引用一个void返回类型的方法。这个委托类存在16种重载方法。

  例如Action<in T1,In T2>调用没有参数的方法

2.Func<T>

  Func<T>调用带返回类型的方法。有16种重载方法。

  例如Func<out TResult>委托类型可以调用带返回类型且无参数的方法,

  Func<in T,out TResult>委托类型调用带有4个参数和一个返回类型的方法。

3.等等

6.怎样使用委托★★

下面我将会用个例子来讲述怎样使用委托

 1 // 声明一个委托类型,它的实例引用一个方法,该方法获取一个int参数,返回string
2 public delegate String myMethodDelegate(int myInt);
3 // 定义一些方法给委托变量引用
4 public class mySampleClass
5 {
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<T>就是泛型委托。

注意事项:

  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         //匿名方法,例1
2 Func<int, int> anon = delegate(int i)
3 {
4 i = i+1;
5 return i;
6 };
7 //输出2
8 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

C#面试:委托的更多相关文章

  1. JavaScript面试问题:事件委托和this

            JavaScript不仅门槛低,而且是一门有趣.功能强大和非常重要的语言.各行各业的人发现自己最混乱的选择是JavaSscript编程语言.由 于有着各种各样的背景,所以不是每个人都对 ...

  2. 你所不知道的 CSS 阴影技巧与细节 滚动视差?CSS 不在话下 神奇的选择器 :focus-within 当角色转换为面试官之后 NPOI 教程 - 3.2 打印相关设置 前端XSS相关整理 委托入门案例

    你所不知道的 CSS 阴影技巧与细节   关于 CSS 阴影,之前已经有写过一篇,box-shadow 与 filter:drop-shadow 详解及奇技淫巧,介绍了一些关于 box-shadow  ...

  3. 面试整理(3)js事件委托

    事件委托主要用于一个父容器下面有很多功能相仿的子容器,这时候就需要将子容器的事件监听交给父容器来做.父容器之所以能够帮子容器监听其原理是事件冒泡,对于子容器的点击在冒泡时会被父容器捕获到,然后用e.t ...

  4. .NET面试题系列[7] - 委托与事件

    委托和事件 委托在C#中具有无比重要的地位. C#中的委托可以说俯拾即是,从LINQ中的lambda表达式到(包括但不限于)winform,wpf中的各种事件都有着委托的身影.C#中如果没有了事件,那 ...

  5. [转载]C#深入分析委托与事件

    原文出处: 作者:风尘浪子 原文链接:http://www.cnblogs.com/leslies2/archive/2012/03/22/2389318.html 同类链接:http://www.c ...

  6. js_事件委托

    起因: 1.这是前端面试的经典题型,要去找工作的小伙伴看看还是有帮助的: 2.其实我一直都没弄明白,写这个一是为了备忘,二是给其他的知其然不知其所以然的小伙伴们以参考: 概述: 那什么叫事件委托呢?它 ...

  7. .Net程序员面试所需要的一些技术准备

    夜已经很深了,但却毫无睡意,最近找工作和面试感触良多,所以想记录下来这段过程. 作为一个.Net程序员,不可否认是比JAVA要难混的.甚至在智联招聘或者大街网都没有.NET程序员的备用选项.真是令人悲 ...

  8. C# ~ 从 委托事件 到 观察者模式 - Observer

    委托和事件的部分基础知识可参见 C#/.NET 基础学习 之 [委托-事件] 部分: 参考 [1]. 初识事件 到 自定义事件: [2]. 从类型不安全的委托 到 类型安全的事件: [3]. 函数指针 ...

  9. C#基础系列——再也不用担心面试官问我“事件”了

    前言:作为.Net攻城狮,你面试过程中是否遇到过这样的问题呢:什么是事件?事件和委托的区别?既然事件作为一种特殊的委托,那么它的优势如何体现?诸如此类...你是否也曾经被问到过?你又是否都答出来了呢? ...

随机推荐

  1. 企业搜索引擎开发之连接器connector(二十四)

    本人在上文中提到,连接器实现了两种事件依赖的机制 ,其一是我们手动操作连接器实例时:其二是由连接器的自动更新机制 上文中分析了连接器的自动更新机制,即定时器执行定时任务 那么,如果我们手动操作连接器实 ...

  2. delphi 拆分字符串

    最近在使用Delphi开发一种应用系统的集成开发环境.其中需要实现一个字符串拆分功能,方法基本原型应该是:procedure SplitString(src: string ; ch: Char; v ...

  3. 如何为SharePoint文档库、文件夹、文件单独设置权限

    在这里使用截图的方式简单描述两个问题:设置SharePoint Server文档库权限和文档库中的文件夹权限 一.设置SharePoint Server文档库权限 Figure 1 - 打开文档库后, ...

  4. yum初识

    yum仓库中的元数据文件: primary.xml.gz 所有RPM包的列表: 依赖关系: 每个RPM安装生成的文件列表: filelists.xml.gz 当前仓库中所有RPM包的所有文件列表: o ...

  5. (zxing.net)一维码Code 128的简介、实现与解码

    一.简介 一维码Code 128:1981年推出,是一种长度可变.连续性的字母数字条码.与其他一维条码比较起来,相对较为复杂,支持的字元也相对较多,又有不同的编码方式可供交互运用,因此其应用弹性也较大 ...

  6. C# 4种方法计算斐波那契数列 Fibonacci

    F1: 迭代法 最慢,复杂度最高 F2: 直接法 F3: 矩阵法 参考<算法之道(The Way of Algorithm)>第38页-魔鬼序列:斐波那契序列 F4: 通项公式法 由于公式 ...

  7. Linux CentOS环境下.Net Core SDK安装

    1.安装.Net SDK 在安装.NET之前,需要注册产品存储库并安装所需的依赖关系. 打开Linux命令提示符并运行以下命令: sudo rpm -Uvh https://packages.micr ...

  8. 如何进入PageAdmin CMS 安装界面

    一般下面几个应用场景如第一次使用PageAdmin配置参数.服务器迁移.主域名更换.忘记超级管理员密码等都可以在安装界面进行设置. 下面为PageAdmin安装步骤 1.地址栏输入:http://您的 ...

  9. fatal: Not a git repository (or any parent up to mount point /home)

    问题:fatal: Not a git repository (or any parent up to mount point /home) 解决:git init

  10. django系列8.3.2--django中间件实现登录验证(2) 个人构想逻辑

    middleware.py from django.utils.deprecation import MiddlewareMixin from django.shortcuts import rend ...