1、委托的声明和编译原理

声明委托:

 delegate void Translate(string str);

通过反编译之后可得下面代码

    private sealed class Translate:System.MulticastDelegate//就是一个多播委托
{
public Translate(object o, Method m) { }//(实现委托方法),隐性传进来的 o 就是 当前类的 this对象,第二个参数是传进来的事件
public void Invoke(string str) { }//实现 委托的方法(向委托事件里面 传递参数) // 所以可以通过 new 调用 委托业务函数 ,可以 调用 Invoke()方法来实现
}

委托是由三部分组成:1、Target(指向方法的实例(就是方法的类),对应上面的 o)2、Method(指向方法的 类型) 3、委托链(InvorkList):多播委托。委托时一个object数组,每增加一个方法,实际CLR会将其封装成一个委托,将其添加到object[]中。然后调用的时候,通过“类型指针”指向对应的委托的地址,然后指针在向下指向下一个委托,知道数组中所有委托都执行完毕。)

2、委托的使用

            //1.向方法 里面添加 委托
tran = new Translate(TranSlateCN);//创建委托
//tran = TranSlateCN;//第二种创建委托的方法(效果同上) tran.Invoke("北疆");//实现委托的方法
tran("北疆");//调用 委托事件(实现的 就是上面的 方法)

匿名的方式给委托赋值:

            AddDel adddemo2 = delegate(int c, int b)
{
return c + b;
};

 3、委托的作用:

占位:向一个方法函数中传递一个委托类型的变量,因为方法函数中不知道要执行什么方法,但是知道方法的类型,所以用一个委托作为形参传递进去,然后实参由使用的用户自行定义,只要符合委托类型就可以了。(实际上:就是传递进去一个委托类型的形参,就可以传递不同的(只要符合委托类型)的实参方法。)

演示:实现不同排序方法

首先定义委托:

    public delegate int GetMaxDel(object o1, object o2);

定义排序函数:

         public object GetMax(object[] objs, GetMaxDel maxdel)
{
object maxobj = objs[];
foreach (var item in objs)
{
if (maxdel(item, maxobj) > )
{
maxobj = item;
}
}
return maxobj;
}

第一种排序:

             GetMaxDel maxdel1 = delegate(object o1, object o2)
{
int num1 = Convert.ToInt32(o1);
int num2 = Convert.ToInt32(o2);
return num1 - num2;
}; object[] objs = { , , , , };
object result = d.GetMax(objs, maxdel1); Console.WriteLine(result.ToString());

第二种排序

             GetMaxDel maxdel2 = delegate(object o1, object o2)
{
Person p1 = o1 as Person; //Person是实现定义的类
Person p2 = o2 as Person;
if (p1.Age > p2.Age)
return ;
else
return -;
};

4、多播委托

委托含有一个“委托链”,是一个object[]类型的数组,执行的之后,委托的“类型指针”(方法指针)会执行下一个委托,一次类推,执行完成所有的委托

            SayHi sayhi = new SayHi(d.SayHiInChinese);
// sayhi = (SayHi) Delegate.Combine(sayhi, new SayHi(d.SayHiInEnglish)); 反编译之后:所以执行的还是两个委托 相加
sayhi += d.SayHiInEnglish;
sayhi += d.SayHiInFresh; sayhi("大家好"); sayhi -= d.SayHiInFresh; //调用的是Delegate.Remove(new Delegate(d.SayHiInFresh));
//下面是 将方法 封装成 委托 在进行相加(和上面直接加 方法 是一样的(编译成相同的代码))
SayHi sayhello = new SayHi(d.SayHiInFresh);
//两个委托相加
sayhi += sayhello;

注意:多播委托的委托最好不要要返回值。如果有返回值,那么执行多播委托的时候,多播委托的返回值是最后一个委托方法执行的返回值。

 5、泛型委托

泛型:就是约束:约束的是传入的参数的个数类型和返回值的类型。

分为两种:有返回值泛型委托:Func 和 无返回的泛型委托:Action

有返回值的泛型委托

             List<int> listInt = new List<int>() { , , , ,  };
//有返回值的 泛型委托。(使用的最多)
//前面可以传递 最多 (出入参数)十六参数 最后一个传出参数(out 类型)的是bool类型的(判断是否满足要求)
Func<int, bool> funcdel = a => a > ;
//函数原型:public delegate TResult Func<in T, out TResult>(T arg); 实质:也是委托,只不过对 传入参数 和返回值 做了约束 //List 的where方法(用户筛选 List里面 的 满足 泛型 委托 函数的 )
var result = listInt.Where(funcdel);
foreach (var i in result)
{
Console.WriteLine(i);
}

无返回值的泛型委托:

             //无返回值的  泛型委托 Action,,很少使用
//委托的 函数原型:public delegate void Action<in T1, in T2>(T1 arg1, T2 arg2);
Action<int, int> act = (a, b) => {
Console.WriteLine(a+"+"+b+"+"+(a+b));
};
act.Invoke(,);

6、异步委托

什么是异步委托:当当前主线程执行的时候,定义一个新的 线程,执行相应的代码,但是不影响主线程。

第一种:不使用回调函数

             //第一种(EndInvoke会阻塞当前线程(主线程))
//异步委托:就是 当主线程 执行的时候, 定义 一个新的线程执行 代码,不影响 主线程的 运行
IAsyncResult delResult = newdel.BeginInvoke(, , null, null);//返回值为 异步委托的结果
while (!delResult.IsCompleted)
{
//当 异步委托 没有执行完成的 时候 主线程 可以继续执行 自己的代码
}
//执行 委托的 EndInvoke 方法 之后返回值就是 委托传进来的 参数方法的 返回值
int addResult = newdel.EndInvoke(delResult);//阻塞当前线程的 执行(直到 异步委托执行完成之后)
Console.WriteLine("线程执行完成之后 的结果" + addResult);

第二种:使用回调函数

首先为回调函数定义方法:

         //为回调函数 定义 一个方法(根据委托类型  来定义方法 (void 还有参数为 接口))
public static void ForSayCallBack(IAsyncResult iasyResult)
{
//将接口类型 转换成 实例类型(只要是继承与 此接口的 类 都可以将 接口参数 转换成 实例类型)(*面向接口编程*)
AsyncResult asyResult = iasyResult as AsyncResult;
//AsyncDelegate:获取 对应的 委托对象 (并将 获得的委托对象 转换成 自己定义的 委托对象)
myNewdel mydel= asyResult.AsyncDelegate as myNewdel;
//获得了自己的 委托对象 就可以调用 EndInvoke方法了
int result= mydel.EndInvoke(iasyResult);
Console.WriteLine("次异步委托执行了,执行的返回结果为{0},线程Id为:{1}",result,
Thread.CurrentThread.ManagedThreadId);
//取到 为回调函数 传递的值(**)
int state =(int) iasyResult.AsyncState;
}

执行异步委托:

             newdel.BeginInvoke(, , new AsyncCallback(ForSayCallBack), );//最后一个参数(object类型:可以传递多个值(比如传递一个List类型)) :为回调函数传值

             //(**)BeginInvoke内部实现:第一步:从线程池 里面 拿过来一个 新的线程  第二步:用此线程 执行 当前委托(调用异步委托的委托)要执行的方法  第三步:执行 回调函数
Console.WriteLine("主线程执行完毕!");

c#之委托总结的更多相关文章

  1. HTML 事件(三) 事件流与事件委托

    本篇主要介绍HTML DOM中的事件流和事件委托. 其他事件文章 1. HTML 事件(一) 事件的介绍 2. HTML 事件(二) 事件的注册与注销 3. HTML 事件(三) 事件流与事件委托 4 ...

  2. C#基础篇 - 理解委托和事件

    1.委托 委托类似于C++中的函数指针(一个指向内存位置的指针).委托是C#中类型安全的,可以订阅一个或多个具有相同签名方法的函数指针.简单理解,委托是一种可以把函数当做参数传递的类型.很多情况下,某 ...

  3. [.NET] C# 知识回顾 - 委托 delegate (续)

    C# 知识回顾 - 委托 delegate (续) [博主]反骨仔 [原文]http://www.cnblogs.com/liqingwen/p/6046171.html 序 上篇<C# 知识回 ...

  4. [C#] C# 知识回顾 - 委托 delegate

    C# 知识回顾 - 委托 delegate [博主]反骨仔 [原文]http://www.cnblogs.com/liqingwen/p/6031892.html 目录 What's 委托 委托的属性 ...

  5. 9、委托、事件、Lambda

    开始 关于委托,肯定是要有问题的. 第一个问题,委托用来干什么? 看.net中的表述:在.net平台下,委托类型用来定义和相应应用程序中的回调.(回调?处理内存中两个实体双向通信的一种技术.)   第 ...

  6. iOS 委托与文本输入(内容根据iOS编程编写)

    文本框(UITextField) 本章节继续编辑 JXHypnoNerd .文件地址 . 首先我们继续编辑  JXHypnosisViewController.m 修改  loadView 方法,向  ...

  7. C#委托异步调用

    参考页面: http://www.yuanjiaocheng.net/webapi/mvc-consume-webapi-get.html http://www.yuanjiaocheng.net/w ...

  8. JavaScript事件代理和委托(Delegation)

    JavaScript事件代理 首先介绍一下JavaScript的事件代理.事件代理在JS世界中一个非常有用也很有趣的功能.当我们需要对很多元素添加事件的时候,可以通过将事件添加到它们的父节点而将事件委 ...

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

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

  10. .NET基础拾遗(4)委托、事件、反射与特性

    Index : (1)类型语法.内存管理和垃圾回收基础 (2)面向对象的实现和异常的处理基础 (3)字符串.集合与流 (4)委托.事件.反射与特性 (5)多线程开发基础 (6)ADO.NET与数据库开 ...

随机推荐

  1. 如何用Python输出PPT中的文字信息

    在这里,会用到win32com模块 模块下载地址:http://sourceforge.net/projects/pywin32/files/pywin32/ 代码如下: import win32co ...

  2. CSS 外边距(margin)重叠及防止方法

    边界重叠是指两个或多个盒子(可能相邻也可能嵌套)的相邻边界(其间没有任何非空内容.补白.边框)重合在一起而形成一个单一边界. 两个或多个块级盒子的垂直相邻边界会重合.结果的边界宽度是相邻边界宽度中最大 ...

  3. Fiddler使用总结一(使用Fiddler捕获手机所有http/https通信)

    与后端数据通信是前端日常开发的重要一环,在与后端接口联调的时候往往需要通过查看后端返回的数据进行调试.如果在PC端,Chrome自带的DevTools就已经足够用了,Network面板可以记录所有网络 ...

  4. 第3章 结束会话端点(EndSession Point) - IdentityModel 中文文档(v1.0.0)

    该RequestUrl类可用于构造URL发送到OpenID Connect EndSession endpoint. 该CreateEndSessionUrl扩展方法支持最常用的参数: /// < ...

  5. Java volatile关键字的用法

    volatile不能解决同步问题 如果想要理解volatile关键字的作用不得不先了解Java内存模型 摘抄一下来自百度百科的话 在本次线程内,当读取一个变量时,为提高存取速度,编译器优化时有时会先把 ...

  6. 混沌分形之谢尔宾斯基(Sierpinski)

    本文以使用混沌方法生成若干种谢尔宾斯基相关的分形图形. (1)谢尔宾斯基三角形 给三角形的3个顶点,和一个当前点,然后以以下的方式进行迭代处理: a.随机选择三角形的某一个顶点,计算出它与当前点的中点 ...

  7. 一个PHP操作大变量的例子

    By C extensions we can directly manipulate the large PHP variables, such as:GET,POST,SERVER You can ...

  8. php 类和对象

    ⾯向对象是⼀种编程范式,它将对象作为程序的基本单元,将程序和数据封装起来, 以此来提⾼程序的重⽤性.灵活性和可扩展性. ⽬前很多语⾔都⽀持⾯向对象编程,既然对象对象是⼀种范式,其实这就和具体的编程语⾔ ...

  9. 20155307 实验四 Android程序设计

    在安装as的过程中一路顺风,一点问题都没有,但是在编译的时候总是出现错误,无论是我用自己的手机还是虚拟的手机都不能成功. 但是我上网百度,发现错误原因为compileSdkVersion的版本出了问题 ...

  10. 冲刺ing-6

    第六次Scrum冲刺 队员完成的任务 队员 完成任务 吴伟华 Leangoo的看板截图,燃尽图 蔺皓雯 编写博客,界面设计 蔡晨旸 界面设计 曾茜 测试 鲁婧楠 学习后端设计 杨池宇 界面设计 成员遇 ...