1。疑问:

1.委托是什么?

2.为什么需要委托?

3.委托能用来做什么?

4.如何自定义委托?

5..NET默认的委托类型有哪几种?

6.怎样使用委托?

7.多播委托是什么?

8什么是泛型委托?

9.什么是匿名方法?

10.委托是否可以回调实例方法?

11.Lambda表达式是什么?

12.Lambda表达式怎么传参?

13.Lambda多行代码怎么写?

14.什么是闭包?

2。解答:

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#学习(2):委托的更多相关文章

  1. C#学习之委托和事件

    C#学习中,关于委托和事件的一些见解: 一.C语言中的函数指针 想要理解什么是委托,就要先理解函数指针的概念.所谓函数指针,就是指向函数的指针(等于没说-.-).比如我定义了两个函数square和cu ...

  2. C#学习之委托与事件

    委托 语法:  public  delegate void MyDelegate(); 使用:  1.定义委托----public  delegate void MyDelegate(); 2.注册委 ...

  3. .net学习之委托和事件

    1.什么是委托通俗的说:委托就是一个能够存储符合某种格式(方法签名)的方法的指针的容器上传图片: 2.委托语法准备一个方法:string Hello(string userName){} string ...

  4. c#基础学习笔记-----------委托事件

    这里有一个比较简单的委托实例应用(跨窗体操作控件) http://blog.csdn.net/bdstjk/article/details/7004035 还有一个比较详细的介绍并深入理解委托事件的讲 ...

  5. C#学习之------委托

    1.向窗体中添加控件的最少步骤:                 窗体的句柄为this private System.Windows.Forms.Button button1;             ...

  6. 6.26学习 异步委托回调函数 VS 多线程 VS 并行处理

    描述: 我现在是轮询着构建实例,然后这个实例去执行一个方法,但是执行方法需要大约10s时间,全部轮询下来需要很长时间.所以我现在要更改,头给了我两个方法,1多线程 2异步委托回调函数. 异步委托回调函 ...

  7. 从一些代码方法中,去学习C#委托

    先来看看下面一个类中的一些方法: class Bc { public double Add(double number1, double number2) { return number1 + num ...

  8. C#基础学习之委托的理解和应用

    委托的使用和语法定义 委托的使用是由四步来完成的,依次为:声明委托.创建委托对象.委托关联方法.调用 我们用一个例子来说明这四步如何操作,我们完成一个老板委托员工写报告的实例,看如何实现. 首先我们应 ...

  9. C#图解教程学习笔记——委托

    一.委托概述委托和类一样,是用户自定义类型,也是引用类型.但类表示的是数据和方法的集合,而委托持有一个或多个方法,以及一系列预定义操作. 可以通过以下操作步骤来使用委托:(1)声明一个委托类型.委托声 ...

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

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

随机推荐

  1. gridview发布后,编辑改为edit 原因是未安装 dotNetFx40LP_Full_x86_x64zh-Hans中文语言包

    https://www.microsoft.com/zh-cn/download/details.aspx?id=3324

  2. jeesite快速开发平台(一)----简介

    转自:https://blog.csdn.net/u011781521/article/details/54880170

  3. html 1.0 鼠标放上去会亮 onmouseover onmouseout 以及this标签的使用

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  4. Symfony 建立一个Bundle

    如果说,这个时候你萌生了一个去看一看Symfony源码的想法,个人建议还是算了,看了之后,你就会感到非常迷茫.因为他实在是大于绝大部分你使用过的框架,并且有多达近二十个的插件,使用了一些非常精巧的设计 ...

  5. SublimeText Videos Notes

    [SublimeText Videos Notes] Getting Started 1.Hello:https://tutsplus.com/course/improve-workflow-in-s ...

  6. thymeleaf 获取项目路径

    <p th:text=${salecode}></p> <a th:href="${#httpServletRequest.getScheme()+'://'+ ...

  7. 邮槽 匿名管道 命名管道 剪贴板 进程通讯 转自http://www.cnblogs.com/kzloser/archive/2012/11/04/2753367.html#

    邮槽 通信流程: 服务器 客户端 注意: 邮槽是基于广播通信体系设计出来的,它采用无连接的不可靠的数据传输 邮槽可以实现一对多的单向通信,我们可以利用这个特点编写一个网络会议通知系统,而且实现这一的系 ...

  8. Luogu 4512 【模板】多项式除法

    高级操作,感觉非常神仙. 题目中的字母太难懂了,重新定义一下. $$A(x) = B(x) * C(x) + D(x)$$ 其中,$A(x)$的次数是$n$,$B(x)$的次数是$m$,$A, B$都 ...

  9. for(var i=0;i<5;i++){ setTimeout(function() { console.log(i) }, 100);}

    涉及异步.作用域.闭包 1.settimeout是异步执行,100ms后往任务队列里面添加一个任务 2.let不仅将i绑定到for循环块中,事实上它将其重新绑定到循环体的每一次迭代中 3.闭包 set ...

  10. Laravel 5 项目部署到生产环境的实践

    作者:mrcn链接:https://www.zhihu.com/question/35537084/answer/181734431来源:知乎著作权归作者所有.商业转载请联系作者获得授权,非商业转载请 ...