C#-委托delegate
1.委托的定义
【定义】:委托是C#中函数回调机制,就是c语言中的函数指针在面向对象中的封装;简而言之就是函数指针。
它定义了方法的类型,使得可以将方法当作另一个方法的参数来进行传递。
委托和类相似,都是用户自定义的一种类型,只不过类表示的数据的集合,而委托表示的是一个或多个方法
【理解】:类比声明一个字符类型的变量“string name ”,其中string 是一个类,定义了name参数所能代表的值的种类,也就是name参数的类型。
【作用与意义】:
这种将方法动态地赋给参数的做法,可以避免在程序中大量使用If-Else(Switch)语句,同时使得程序具有更好的可扩展性。
2.委托的声明
【使用方法】:
关键字 delegate
委托和所引用的方法必须保持一致:
1、参数个数、类型、顺序必须完全一致。
2、返回值必须一致。
3. 委托的实例
//声明一个委托指向一个函数,注意声明在同一个命名空间
public delegate void DelSayhi(string name);
class Program
{
static void Main(string[] args)
{
//---------------------------------------------------------------------法1
//DelSayhi del=new DelSayhi (SayhiChinese );
//☆注意函数名直接赋值给委托,不需要在函数名之后加括号
//Sayhi("志铭", del);
//委托就是为把一个函数当参数,但这样不明显
//---------------------------------------------------------------------法2
//可以直接把一个函数给委托
//DelSayhi del = SayhiChinese;
//☆注意函数名直接赋值给委托,不需要在函数名之后加括号
//Sayhi("志铭", del);
//---------------------------------------------------------------------法3
//既然可以法2 ,那干脆直接如下,这样你就可以发现函数作为了参数
//Sayhi ("志铭", SayhiChinese);
//---------------------------------------------------------------------多播委托
//委托可以将多个方法赋给同一个委托,或者叫将多个方法绑定到同一个委托,
//这就是——多播委托
//当调用这个委托的时候,将依次调用其所绑定的方法。在这个例子中,语法如下
//DelSayhi del=new DelSayhi (SayhiChinese );
//del += SayhiEnglish;//使用+=给此委托变量再绑定一个方法
//Sayhi("志铭", del);
//---------------------------------------------------------------------取消绑定
//既然给委托可以绑定一个方法,
//那么也应该有办法取消对方法的绑定,很容易想到,这个语法是“-=”:
//DelSayhi del = new DelSayhi(SayhiChinese);
//del += SayhiEnglish;//使用+=给此委托变量再绑定一个方法
//Sayhi("志铭", del);
//del -= SayhiChinese;//使用-=给此委托变量取消绑定一个方法
//Sayhi("志铭", del);
//不使用SayHi函数,在新建了了委托对象后直接使用委托作函数
//注:当然我们知道可以在这里直接使用SayhiChinese和SayHiEnglish俩个函数,我们在这里就是举例子
DelSayhi del = new DelSayhi(SayhiChinese);
if (null != del)//注意调用委托的时候一定要先判断委托是否为空,为空时会抛异常
{
del("志铭");//其实是del.Invoke("志铭")的简写
}
Console.ReadKey();
}
//Sayhi这个函数就是为了把下面两个函数SayhiChinese和SayhiEnglish统一起来
//我想在这个函数中调用这两个函数,也就是有一个函数作为参数,但具体哪一个不确定
//所以我定义了一个委托DelSayhi指向这两个函数
public static void Sayhi(string name, DelSayhi del)
{
del(name);
}
public static void SayhiChinese(string name)
{
Console.WriteLine("你好" + name);
}
public static void SayhiEnglish(string name)
{
Console.WriteLine("Hello" + name);
}
}
4.委托的注意细节
如果委托有返回值并且在调用列表中有一个以上的方法(即多播委托),会发生下面的情况:
- 调用列表中最后一个方法返回的值就是委托调用返回的值。
- 调用列表中所有其他方法的返回值都会被忽略(忽略不是不执行)。
例如
delegate int mypel();//声明有返回值的方法
class MyClass
{
int IntValue 5;
public int Add2(){ Intvalue +=2;return IntValue;}
public int Add3(){ IntValue +=3;return IntValue;}
}
class Program
{
static void Main()
{
MyClass mc=new MyClass();
MyDel mDel=mc.Add2;//创建并初始化委托
mDel +=mc.Add3//增加方法
mDel +=mc.Add2//增加方法
Console.Writeline("value:{0}",mDe1());调用委托并使用返回值
}
}
结果:value:12;
5.泛型委托
(详见《精通C#》--10.4泛型委托)
.net中内置类两个委托类型Action<>和Func<>,用法和自己定义的委托一样,只是不需要我们自己声明。
建议使用委托的时候就先考虑这两种委托。
5.1.Action<>委托
Action<>类型的委托指向--最多16个参数并返回值为void的方法。
class Program
{
static void Main(string[] args)
{
Action<string> del=SayhiChinese;//定义一个Action<string>委托,指向的方法返回值为void,有一个string类的参数。
//你想想,你之前使用委托是不是要要自己声明一个委托类型了
//这里就相当于.net已经帮我们 delegate void Action<T>(T p)
if (null != del)
{
del("志铭");
}
Console.ReadKey();
}
public static void SayhiChinese(string name)
{
Console.WriteLine("你好" + name);
}
public static void SayhiEnglish(string name)
{
Console.WriteLine("Hello" + name);
}
}
5.2.Func<>委托
Func<>类型的委托指向--最多16个参数且有返回值的方法。
有一点要注意的就是,类型列表的顺序:Func<>最后的一个类型参数是返回值的类型
show your code:
class Program
{
static void Main(string[] args)
{
Func<int,int,string> del=SumToString;
//注意类型参数列表中的类型顺序,最后一个string 是函数返回值的类型
//这里就相当于.net已经给我们 delegate RT Func<T1,T2,RT>(T1 x,T2 y)
Console.WriteLine(del(1,2));
}
public static string SumToString(int x,int y)
{
return (x+y).ToString();
}
}
6.委托的意义
在代码结构的设计上使用委托可以降低类与类之间的耦合性。
有两个类AClass和BClass,现在当某个条件得到满足的时候,AClass中的方法AFunc调用BClass中的方法BFunc()。
代码如下:
public class Program
{
AClass AObj = new AClass();
void Main()
{
AObj.AFunc();
}
}
public class AClass
{
BClass BObj=new BClass();
public void AFunc()
{
//当某个条件满足时
if(true)
{
BObj.BFunc();
}
}
}
public class BClass
{
public void BFunc()
{
}
}
这样的写法使得A类和B类之间的关系为强耦合的关系,B的变化会在很大的几率上影响到A,我们将这样的关系称之为不稳定的关系,这是面向对象编程设计所不提倡的,那么如何将不稳定的关系变为稳定的关系呢?方法有多种,委托的应用就是其中一种。
代码如下:
//声明一个委托类型,它能接受的函数类型是没有返回也没有参数
public delegate void MyDelegate();
public class AClass
{
//定义一个委托类型的变量 ,变量名字为 mydelagate
public MyDelegate mydelagate = null;
public void AFunc()
{
//当某个条件满足时
if(true)
{
if(mydelagate != null)
{
mydelagate();
}
}
}
}
public class BClass
{
public void BFunc()
{
}
}
public class Pragrom
{
AClass AObj = new AClass();
BClass BObj = new BClass();
void Main()
{
AObj.mydelagate = BObj.BFunc();
AObj.AFunc();
}
}
可以看到,只需要将B类中的方法通过公开的委托注册到A类去执行,这样就避免了A类和B类之间的相互引用,提高了类关系之间的稳定性。
其实早期的delegate
是翻译成代表
,我们是可以这样理解的,委托是被调用函数的代表,函数调用者调用委托,委托调用其代表的函数,这用就形成了一种间接调用,从而实现调用者和被调用函数的解耦!
7.匿名方法
委托的初始化是对其赋值一个方法,但是有时候这个方法就只在初始化这个委托的时候使用,我们没有必用去完整的声明一个方法,所以在C#2.0中引入了匿名方法(anonymous method)的概念。
- 匿名方法的语法
- 使用
delegate
关键字 - 不需要标注返回值类型(若是匿名方法有返回值,其类型要符合相应委托定义的类型)
- 参数列表和普通方法声明的格式一样,若是没有参数则不需要写(包括参数列表的括号,不省略圆括号也是可以的)
如下:
delegate (Parameters){方法体...}//注意若是没有参数则省略参数列表(Parameters)
- 实例:
delegate void Del();
static void Main()
{
Del del=delegate
{
Console.WriteLine("Hello world ");
}
del();
}
8.Lambda表达式
C#2.0中引入匿名方法,但是语法依旧有点麻烦,C#3.0中引入Lambda表达式
Lambda表达式使用=>
符号编写,读作goes to
见匿名方法到Lambda表达式的演变过程如下:
public delegate int Del(int x);
Del del1 = delegate(int x) {return x+1;};//匿名方法
Del del2= (int x) => {return x+1;};//Lambda表达式
Del del3= (x) => {return x+1;}
Del del4= x => x+1;
【注意】
若是没有参数则Lambda表达式的参数使用一个空括号表示()
。
若是函数体中有多句代码,大括号不可以省略。
注意参数的圆括号只有是参数只有一个并且是隐式类型的才可以省略,否则不可以省略,见上面代码的del2
9.源代码下载
C#-委托delegate的更多相关文章
- [.NET] C# 知识回顾 - 委托 delegate (续)
C# 知识回顾 - 委托 delegate (续) [博主]反骨仔 [原文]http://www.cnblogs.com/liqingwen/p/6046171.html 序 上篇<C# 知识回 ...
- [C#] C# 知识回顾 - 委托 delegate
C# 知识回顾 - 委托 delegate [博主]反骨仔 [原文]http://www.cnblogs.com/liqingwen/p/6031892.html 目录 What's 委托 委托的属性 ...
- C# 委托Delegate(一) 基础介绍&用法
本文是根据书本&网络 前人总结的. 1. 前言 定义&介绍: 委托Delegate是一个类,定义了方法的类型, 使得可以将方法当做另一个方法的参数来进行传递,这种将方法动态地赋给参数的 ...
- 为什么不能把委托(delegate)放在一个接口(interface)当中?
stackoverflow上有人问,为什么不能把委托放在一个接口当中? 投票最多的第一个答案第一句话说,“A Delegate is just another type, so you don't g ...
- C# 代理/委托 Delegate
本文转载自努力,努力,努力 1. 委托的定义:委托是函数的封装,它代表一"类"函数.他们都符合一定的签名:拥有相同的参数列表,返回值类型.同时,委托也可以看成是对函数的抽象,是函数 ...
- c# 委托 delegate
委托是一种存储函数引用的类型,在事件和事件的处理时有重要的用途 通俗的说,委托是一个可以引用方法的类型,当创建一个委托,也就创建一个引用方法的变量,进而就可以调用那个方法,即委托可以调用它所指的方法. ...
- 理解委托(delegate)及为什么要使用委托
理解委托(delegate)及为什么要使用委托 委托:是一种定义方法签名的类型. 当实例化委托时,您可以将其实例与任何具有兼容签名的方法相关联. 您可以通过委托实例调用方法. 上述为官方说法,理解起来 ...
- 深入理解委托(Delegate)
前言 委托其实一直以来都感觉自己应该挺熟悉的,直到最近又去翻了翻 CLR via C#,感觉我之前的理解可能还有失偏颇.在这记录一下. 之前文章的链接: 接口和委托的泛型可变性 C#高级编程笔记 De ...
- C# -- 使用委托 delegate 执行异步操作
C# -- 使用委托 delegate 执行异步操作 委托是一种安全地封装方法的类型,它与 C 和 C++ 中的函数指针类似. 与 C 中的函数指针不同,委托是面向对象的.类型安全的和保险的. 委托的 ...
- 委托delegate
委托delegate没有函数体.委托可以指向函数(要与指向的函数格式.类型相一致) namespace demo { public delegate double MyDelegate(double ...
随机推荐
- H5 页面调试小帮手-UC 开发者工具
调试web页面难 接触过app自动化的同学都比较清楚,如果想要对web应用或者Hybrid应用进行调试时(获取页面元素信息等等),必定绕不开的就是chrome浏览器的inspect功能了:在chrom ...
- java中子类继承父类程序执行顺序问题
Java中,new一个类的对象,类里面的静态代码块.非静态代码.无参构造方法.有参构造方法.类的一般方法等部分,它们的执行顺序相对来说比较简单,用程序也很容易验证.比如新建一个测试父类. public ...
- Python爬虫入门项目
Python是什么 Python是著名的"龟叔"Guido van Rossum在1989年圣诞节期间,为了打发无聊的圣诞节而编写的一个编程语言. 创始人Guido van Ros ...
- 【朝花夕拾】Android性能篇之(六)Android进程管理机制
前言 Android系统与其他操作系统有个很不一样的地方,就是其他操作系统尽可能移除不再活动的进程,从而尽可能保证多的内存空间,而Android系统却是反其道而行之,尽可能保留进程.An ...
- K60平台智能车开发工作随手记
(图片仅为示例,并不一定固定为这种造型) 第十二届全国大学生智能汽车竞赛有一个分项是光电四轮车的竞速(任务A),Seven她们组采购到的配件使用了freescale Crotex-M4内核的CPU,T ...
- SQL语句查询表结构
SQL语句查询表结构 刚刚在做一个小项目,数据库中一张表有20来个字段,用我以前做的一个.NET实体类生成器一个一个的输入还是闲麻烦,于是打算找个时间来重新的改造一个那个.NET实体类,能够通过选 ...
- Mybatis动态SQL简单了解 Mybatis简介(四)
动态SQL概况 MyBatis 的强大特性之一便是它的动态 SQL 在Java开发中经常遇到条件判断,比如: if(x>0){ //执行一些逻辑........ } Mybatis应用中,S ...
- 痞子衡嵌入式:飞思卡尔i.MX RT系列MCU启动那些事(13)- 从Serial(1-bit SPI) EEPROM/NOR恢复启动
大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家介绍的是飞思卡尔i.MX RT系列MCU的Serial EEPROM/NOR恢复启动. 在前几篇里痞子衡介绍的Boot Device都属于主动启 ...
- Linux find常用用法示例
在此处只给出find的基本用法示例,都是平时我个人非常常用的搜索功能.如果有不理解的部分,则看后面的find运行机制详解对于理论的说明,也建议在看完这些基本示例后阅读一遍理论说明,它是本人翻译自fin ...
- Docker多主机管理(八)--技术流ken
docker多主机管理 前面我们的实验环境中只有一个 docker host,所有的容器都是运行在这一个 host 上的.但在真正的环境中会有多个 host,容器在这些 host 中启动.运行.停止和 ...