C#的委托Delegate
一、委托基础
1.什么是委托
委托(Delegate) 是存有对某个方法的引用的一种引用类型变量,用关键字delegate申明,实现相同返回值和参数的函数的动态调用,提供了对方法的抽象。
委托(Delegate)特别用于实现事件和回调方法。所有的委托(Delegate)都派生自 System.Delegate 类。
2.声明委托
委托声明后决定了该委托可以引用的方法。
public delegate string MyDelegate(int i);
上面声明的委托可以用于引用任何返回值为string类型并且参数为一个int类型的任意方法名的方法,例如下面这个:
public static string GetStr(int i){return i.ToString();}
所以委托的声明格式为:访问修饰符+delegate+返回类型+类型名+参数。
3.初始化委托变量以及赋值
声明了委托类型后,和string、int等类型一样需要声明变量才能使用。对于初始化变量的赋值有两种方式:
(1)new实例化赋值
和一般的类实例化一样,在构造函数中传入方法名即可。
MyDelegate mydelegate = new MyDelegate(GetStr);
(2)直接赋值
由于方法名称和相应的委托之间存在隐身转换,所以可以等于号赋值。
MyDelegate mydelegate = GetStr;
以上例子都是直接将方法名赋值给委托变量的,这是因为方法由static修饰。对于非静态的变量还是需要实例化使用,如下:
MyDelegate mydelegate = new People().GetStr;
由于委托是引用类型,用 '=' 重新赋值后会改变方法的引用地址,下述例子也继续使用静态方法。
4.多播委托
委托对象可以通过 ‘+’ 运算法进行组合,一个合并委托调用所组合的委托的所有指向方法引用地址,合并的委托必须是相同类型的。不仅是对象可以组合,通过 '+' 运算符可以让委托变量对方法自增。
(1)委托对象组合
MyDelegate mydelegate1 = GetStr;
MyDelegate mydelegate2 = GetStr;
MyDelegate mydelegate3 = mydelegate1 + mydelegate2;
(2)自增
MyDelegate mydelegate = GetStr;
mydelegate += GetStr;
有增自然有减,可以通过 ‘-’ 运算符进行方法引用地址的剔除,如果有多个同样的方法,只删除其中一个。
5.匿名方法
我们之前的方法都是事先声明好了的,然后使用方法名。但是有时候我们不想要声明新方法,因为这个是一个临时的方法。那么就可以用在c# 2.0版本引入的匿名方法,或者是3.0以后版本的lambda表达式。
匿名方法使用的也是delegate关键字,不需要定义返回类型,格式为: delegate (传入参数) {执行语句},如下:
MyDelegate mydelegate = delegate(int i) { return i.ToString(); };
lambda表达式简化了匿名方法的书写,去掉了delegate关键字并加入 '=>' 运算符:
MyDelegate mydelegate = (int i) => { Console.WriteLine(i.ToString()); };
6.委托调用
委托的调用和方法的调用差不多,因为委托声明的时候参数和返回值都已经确定了,所有加入委托调用列表的方法都是一样的,所以当委托调用的时候所有方法会依次执行。多播委托的情况下会返回最后一个有返回值的方法结果。但是要注意委托变量是否为空,空的执行会报错。
if(mydelegate != null)
mydelegate();
7.泛型委托
泛型委托的加入使委托的使用更加方便,简化我们的代码。常用的泛型委托有两种:Action和Func,他们的使用和一般的委托差不多,帮我们省去了声明的哪一步。
Action是无返回值的委托,封装了从无参数到16个参数的委托。
Action action1 = () => { Console.WriteLine("无参的情况"); };
Action<int> action = (int i) => { Console.WriteLine(i.ToString()); };
action += (int i) => { Console.WriteLine((i+).ToString()); };
if (action != null)
action();
Func是有返回参数,所以格式是Fun<T t1,.....,TResult result>,这个返回类型为最后一个参数,并且是必须的,传入参数类型可以没有,但是返回类型必须要。
Func<string,string> func = (string str) => { return str; };
if(func != null)
Console.WriteLine(func("hahaha"));
二、委托的应用
委托的声明和使用其实不难,但是很大的一个困扰就是不知道什么时候使用,园中有很多委托的文章我看了很多,大家都举了很多的例子,比如烧开水啥的,但是我觉得还是用实际的例子来说明比较好。可能很多人在工作了几年后都没有用过委托。所以,实践出真知。只有当真正用到的时候才能明白其中的含义。
这里举在窗体程序中的跨窗体调用方法的例子。现在有两个窗体Form1和Form2,分别由一个文本框和一个按钮。现在通过Form1中的按钮打开Form2窗体,然后通过Form2窗体中的按钮点击更新Form1中文本框的内容。
Form1窗体的代码如下:
private void OpenBtn_Click(object sender, EventArgs e)
{
Form2 form2 = new Form2();
form2.action = this.ModifyName;
form2.Show();
}
private void ModifyName(string name)
{
NameTxt.Text = name;
}
Form2窗体的代码如下:
public Action<string> action;
private void ModifyBtn_Click(object sender, EventArgs e)
{
ConfirmModify(action);
}
private void ConfirmModify(Action<string> action)
{
//省略数据库修改等操作.......
if (action != null)
action(ModifyTxt.Text);
}
代码非常简单,Form1和Form2中的方法都是私有的,只通过Form2中的委托对象来执行Form1中的私有方法。虽然还有别的方法可以实现这个功能,但是我觉得这个方案是比较好的。
三、总结
有问题可以留言讨论,希望可以给大家带来帮助,共勉!
C#的委托Delegate的更多相关文章
- C#中的委托(Delegate)和事件(Event)
原文地址:C#中的委托(Delegate)和事件(Event) 作者:jiyuan51 把C#中的委托(Delegate)和事件(Event)放到现在讲是有目的的:给下次写的设计模式--观察者(Obs ...
- (转)C#中的委托(Delegate)和事件(Event)
转自:http://blog.chinaunix.net/uid-576762-id-2733751.html 把C#中的委托(Delegate)和事件(Event)放到现在讲是有目的的:给下次写 ...
- C#的委托(delegate、Action、Func、predicate)
委托是一个类,它定义了方法的类型,使得可以将方法当作另一个方法的参数来进行传递.事件是一种特殊的委托. 1.委托的声明 delegate我们常用到的一种声明 delegate至少0个参数,至多32个参 ...
- C#中的委托 Delegate(委托 也叫代表,代表一类方法)
1. 委托类似与 C或C++中的函数指针,但委托是 面向对象的,并且是类型安全的 详情可查看官方文档:https://msdn.microsoft.com/en-us/library/ms173172 ...
- 关于C#的委托(delegate)的自我理解
首先描述一个事情,一个老师饿了,他要去买东西填饱肚子,然后他发现他的学生“小李”在玩,没学习,于是就委托“小李”去帮他买吃的. 根据这件事我们来分析: 首先得有个老师(老师饿了是他的方法,老师买东西也 ...
- C#的委托 Action<>和Func<>
其实他们两个都是委托[代理]的简写形式. 一.[action<>]指定那些只有输入参数,没有返回值的委托 Delegate的代码: [csharp] public delegate vo ...
- Java与.net的区别delegate和event
There is no delegate concept in Java The right-side C# program may be mimiced with reflection techno ...
- Objective-C Delegate
ios设计模式中的委托 Delegate 官方文档解释如下: Delegation is a simple and powerful pattern in which one object in a ...
- Delegate,Action,Func,Predicate的使用与区别
C#4.0推出后,类似Linq,Lamda表达式等许多新的程序写法层次不穷.与之相关的Delegate,Action,Func,Predicate的使用和区别也常常让大家迷惑,此处就结合实际的应用,对 ...
随机推荐
- March 11 2017 Week 10 Saturday
Wisdom outweighs any wealth. 智慧比财富更有价值. Wisdom can create wealth if used in proper ways, it can help ...
- IIS环境搭建
IIS环境搭建 IIS环境搭建首先是建立在一个干净的.无毒的系统上,再进行相应操作.本文用到的是windows 2003的镜像文件,有条件的用户也可以使用windows的系统安装光盘. 下面进入操作步 ...
- Android进阶笔记13:ListView篇之ListView刷新显示(全局 和 局部)
一.ListView内容变化后,动态刷新的步骤(全局刷新): (1)更新适配器Adapter数据源:(不要使用匿名内部类) (2)调用适配器Adapter的刷新方法notifyDataSetChang ...
- Android(java)学习笔记45:深入分析Java ClassLoader原理
1. 前言: Android中的动态加载机制能更好的优化我们的应用,同时实现动态的更新,这就便于我们管理我们的应用,通过插件化来减轻我们的内存以及CPU消耗,在不发布新版本的情况下能更新某些模块. 当 ...
- [USACO15OPEN]haybales Trappe…
嘟嘟嘟 刚开始我以为如果这头牛撞开一个干草堆的话,获得的冲刺距离只有新增的部分,但实际上是加上原来的部分的. 暴力很好写,区间排完序后一次判断每一个区间是否能逃脱,复杂度O(n2). 优化想起来也不难 ...
- [19/03/20-星期三] 常用类_Enum(枚举)类
一.概念(JDK 1.5之后才有的类) 所有的枚举(英语:enumeration) 类型隐性地继承自 java.lang.Enum.枚举实质上还是类,而每个被枚举的成员实质就是一个枚举类型的实例,他们 ...
- 2018.10.2 Eclipse中如何测地修改一个we项目步骤
找到项目的web.xml文件 大概的路径如下: 修改xml文件中的display-name 节点的值 下一步就是切换工作目录 显示的效果 打开最后一个文件修改 接下来找到这个文件 是部署的时候用的 运 ...
- 【luogu P3369 普通平衡树(Treap/SBT)】 模板 Splay
题目链接:https://www.luogu.org/problemnew/show/P3369 #include <cstdio> #include <algorithm> ...
- ipython notebook开通远程
之前只是会用,别人告诉我命令和大概怎么设置的,今天自己搭建才发现一知半解搞不定啊. 目的:远程通过ipython notebook调用服务器. 服务器是ubuntu16.04 本地机器win7 配置方 ...
- LeetCode2.两数相加 JavaScript
给定两个非空链表来表示两个非负整数.位数按照逆序方式存储,它们的每个节点只存储单个数字.将两数相加返回一个新的链表. 你可以假设除了数字 0 之外,这两个数字都不会以零开头. 示例: 输入:(2 -& ...