CLR之委托的揭秘(一)
初识委托:
在之前的学习中我们已经可以把对象,值,数组当作参数传递给方法,但是有没有可能把方法也当作参数传递给方法呢?有了这个想法于是就有了委托。方法当作一种参数去传递,但是方法有的有返回值有的没有返回值,这如何处理?委托又用在什么地方?通过这篇文章我们来学习一下委托的用法
委托解密:
在C#中要使用委托。必选先定义要使用的委托,在使用时需要创建该委托的一个或多个实例,以下示例展示了如何声明委托
/*
委托的安全性非常高,所以在声明委托时,要声明委托返回的类型和参数类型
*/
//声明返回类型为double 两个参数类型为long的委托
public delegate double TwolongsOp(long first,long second);
//声明返回类型为string 无参的委托
public delegate string Getstring();
//声明返回类型为void 参数类型为int的委托
public delegate void IntMethodInvoker(int x);
由于定义一个委托实际上是定义一个类,但这个类前面必须加上delegate关键字,所以委托可以定在类中的任何位置,也可以在名称空间中把委托当作顶层对象定义,表面上看,委托声明只需要一句话public delegate double TwolongsOp(long first,long second);,但从CLR角度来看,委托实际上是很复杂的,在使用委托之前先来看一下,底层是如何处理这一句话的。
编译器在读取这行代码时,实际上会自动为其生成一个完整的类,这个类中包含有一个构造器和Invoke,BeginInvoke,EndInvoke方法。自动生成的这个类继承自MulticastDelegate,所以这个类也继承了MulticastDelegate的字段,属性和方法。这个将在委托链中使用其中的一些方法。
那么经过CLR的自动编译以后,我们就可以开始使用委托,下面代码就是如何使用委托
class Program
{
//声明返回类型为string 无参的委托
public delegate string Getstring();
static void Main(string[] args)
{
int x = ;
//实例化委托,并且将int的ToString()方法当作参数传递给委托
Getstring getstring = new Getstring(x.ToString);
//语法糖:简化委托调用和使用new效果一样
Getstring getstring1 = x.ToString;
//调用委托方法
Console.WriteLine(getstring());
//CLR生成的类中就包含的方法安全调用
Console.WriteLine(getstring1.Invoke());
}
}
实际上代码中使用getstring()方法调用和使用Invoke()调用是相同的,因为getstring()方法是委托类型的一个变量,C#编译器会用getstring.Invoke()代替getstring(),如果为了减少输入量,只需要委托示例,就可以只传送地址,这称为委托判断。
委托链:
链式语法在C#中非常常见,Linq就是典型的链式方法调用,而委托也支持链式方法调用,委托链指的就是委托对象的集合,利用链式调用集合中的委托所代表的全部方法,但是委托链是有限制和缺点的,委托链中间方法的返回值会被丢弃无法获取,所以委托返回值最好是void,如果是带有返回值的,会返回最后一个方法的返回值。
举个例子,如果我委托别人帮我去拿一个快递,我又告诉他回来路上顺便帮我带份饭,这是两件事情,如果这两件事都只是去做,不需要拿到返回值,那么委托链可以满足,但是如果我要求两个方法,第一个方法要把快递返回到我手上,第二个方法饭也要返回到我手上,那么就无法获取第一个方法的返回值,也就是说我只能拿到饭,而拿不到快递。接下来看代码比较
//声明返回类型为string 无参的委托
public delegate string Getstring();
static void Main(string[] args)
{
//实例化委托链
Getstring getstatus = null;
//语法糖:支持+=/-=添加方法/移除方法
getstatus += TakeExpress;
getstatus += beltfood;
//获得结果
Console.WriteLine(getstatus());
}
//取快递方法,返回的string当作实体类型看
public static string TakeExpress()
{
return "你的快递是XX,已经为你取了";
}
//带饭方法,返回的string当作实体类型看
public static string beltfood()
{
return "为你带了一份黄焖鸡米饭";
}

两个方法最终只输出了最后一个方法的返回值,我们得到了一份黄焖鸡米饭,但是快递没有得到,于是我们修改以下以上代码,改为如下,可以看到两个方法都被执行了
//声明返回类型为string 无参的委托
public delegate void Getstring();
static void Main(string[] args)
{
//实例化委托链
Getstring getstatus = null;
//语法糖:支持+=/-=添加方法/移除方法
getstatus += TakeExpress;
getstatus += beltfood;
//获得结果
getstatus();
}
public static void TakeExpress()
{
Console.WriteLine("你的快递是XX,已经为你取了");
}
public static void beltfood()
{
Console.WriteLine("为你带了一份黄焖鸡米饭");
}

匿名委托:
匿名方法在.NET 中提高了 代码的可读性和优雅性。对于更多操作较少的方法直接写为匿名函数,这样会大大提高代码的可读性。这里有两个值得注意的地方: 第一,不能使用跳转语句跳转到该匿名方法外,第二 不能使用ref,out修饰的参数,下面是一个匿名委托的调用
//声明返回类型为string 无参的委托
public delegate string Getstring(string str);
static void Main(string[] args)
{
//直接在委托上完善方法
Getstring Spkeak = delegate (string str)
{
if (str == "哑巴")
{
return "我是哑巴,我不能说话";
}
return "我会说话";
}; Console.WriteLine(Spkeak("哑巴"));
小结:
委托是一种比较常用的函数回掉方法,常用于某种情况下触发委托。
CLR之委托的揭秘(一)的更多相关文章
- CLR之委托的揭秘(二)
杂谈 在开始真正的代码之前,分析一下上周的一些工作内容,发现自己在代码上还是有很多小毛病需要纠正和去更改的,首先之前一直疏于文档的整理,几乎很少去写文档,第二对于接口开发过程中缺少一定的严谨性,很多问 ...
- 大话C#之委托
开篇先来扯下淡,上篇博客LZ在结尾说这篇博客会来说说C#中的事件.但是当LZ看完事件之后发现事件是以委托为基础来实现的,于是LZ就自作主张地在这篇博客中先来说说委托,还烦请各位看官见谅!!!另外关于委 ...
- 通过委托来实现异步 Delegate的BeginInvoke和EndInvoke
什么是.net的异步机制呢? 解释这个话题之前,先让我们来看看同步执行的程序 https://github.com/chucklu/Test/blob/master/DotNet4.5开发指南/并行处 ...
- C#多线程之旅(1)——介绍和基本概念
原文地址:C#多线程之旅(1)——介绍和基本概念 C#多线程之旅目录: C#多线程之旅(1)——介绍和基本概念 C#多线程之旅(2)——创建和开始线程 C#多线程之旅(3)——线程池 C#多线程之旅( ...
- .NET本质论 方法
方法和JIT编译 CLR只执行本机的机器代码.如果一个方法体由CIL组成,那么它就必须在调用之前被转换为本机的机器码(将MSIL编译为本机代码,运行库提供了两种方式.一种就是在安装与部署时的预编译(由 ...
- Win7下VS2010、IIS7配置常见问题收集
一 在Win7下应按什么次序安装vs2010和iis7 win7推荐先安装iis7,再安装vs2010:如果次序反了,必须注册iis才可以用. IIS中ASP.NET的版本号此时可选的有1.1.2.0 ...
- C# 多线程系列(一)
线程是怎样工作的 1.多线程由一个线程调度器来进行内部管理,一个功能是CLR常常委托给操做系统. 一个线程调度器确保所有激活的线程在执行期间被合适的分配,等待或者阻塞的线程(比如,一个独占锁或者等待用 ...
- C#线程 入门
Threading in C# 第一部分: 入门 介绍和概念 C#支持通过多线程并行执行代码.线程是一个独立的执行路径,能够与其他线程同时运行.C#客户端程序(控制台,WPF或Windows窗体) ...
- [CLR via C#]17. 委托
回调函数是一种非常有用的编程机制,它已经存在很多年了.Microsoft .NET Framework通过委托(delegate)来提供一种回调机制.不同于其他平台(比如非托管C++)的回调机 ...
随机推荐
- Python实战之SocketServer模块
文章出处:http://www.cnblogs.com/wupeiqi/articles/5040823.html SocketServer内部使用 IO多路复用 以及 "多线程" ...
- Java高新技术 JavaBean内省
Java高新技术 JavaBean内省 知识概要: (1)了解JavaBean内省 (2)JavaBean的简单内省操作 ...
- C# XML序列化方法和常用特性
/* C#对象XML序列化(一):序列化方法和常用特性 .Net Framework提供了对应的System.Xml.Seriazliation.XmlSerializer负责把对象序列化到XML,和 ...
- sqlserver 2005连接超时采用bat命令解决
将以下内容保存为 openSql.bat 双击运行即可 @echo ========= SQL Server Ports =================== @echo Enabling SQLS ...
- MVVM 模版里的控件怎样触发命令
public class BaseWindow : Window { public BaseWindow() { InitializeStyle(); //给样式的控件加载事件 this.Loaded ...
- Python通过future处理并发
future初识 通过下面脚本来对future进行一个初步了解:例子1:普通通过循环的方式 import os import time import sys import requests POP20 ...
- HandlerMapping 和 HandlerAdapter
HandlerMapping 负责根据request请求找到对应的Handler处理器及Interceptor拦截器,将它们封装在HandlerExecutionChain 对象中给前端控制器返回. ...
- Nginx监控-Nginx+Telegraf+Influxb+Grafana
搭建了Nginx集群后,需要继续深入研究的就是日常Nginx监控. Nginx如何监控?相信百度就可以找到:nginx-status 通过Nginx-status,实时获取到Nginx监控数据后,如何 ...
- vue.js快速搭建图书管理平台
前 言 上一期简单讲解了vue的基本语法,这一次我们做一个小项目,搭建一个简单的图书管理平台,能够让我们更深刻的理解这门语言的妙用. 1.DEMO样式 首先我们需要搭建一个简单的demo样式 ...
- 【机器学习实战】第12章 使用FP-growth算法来高效发现频繁项集
第12章 使用FP-growth算法来高效发现频繁项集 前言 在 第11章 时我们已经介绍了用 Apriori 算法发现 频繁项集 与 关联规则.本章将继续关注发现 频繁项集 这一任务,并使用 FP- ...