C#基础精华07(委托事件,委托的使用,匿名方法)
1.委托概述
委托是一种数据类型,像类一样(可以声明委托类型变量)。方法参数可以是int、string、类类型
void M1(int n){ } √
void M2(string s){ } √
void M3(Person p){ } √
委托就是一种数据类型,用来存放方法的数据类型。
那么委托到底把方法存到哪里了?其实委托还是一个类。把方法包装成了一个委托。
方法是不能直接赋值的,那么能不能声明一个能存放方法的变量呢(委托)。像存储变量一样把方法存储起来。
2.委托的使用
声明委托的方式:delegate 返回值类型 委托类型名(参数) 比如delegate void StringProcess(string s); 注意这里的除了前面的delegate,剩下部分和声明一个函数一样,但是StringProcess不是函数名,而是委托类型名
存储什么样的方法就声明什么类型(方法参数与返回值)的委托。
声明的委托是一种类型,就像int、Person一样,如果要用的话还要声明委托类型的变量,声明委托类型变量的方式:StringProcess f1;
将委托类型变量指向函数 StringProcess sp = new StringProcess(SayHello),这样就可以像调用普通函数一样把sp当成函数用了。委托可以看做是函数的指针。整数可以用整数变量指向它,对象可以用对象变量指向它,函数也可以用委托变量指向它。和直接调用函数的区别:用委托就可以指向任意的函数,哪怕是之前没定义的都可以,而不使用受限于那几种。
将委托类型变量指向函数还可以简化成StringProcess sp = SayHello,编译器帮我们进行了new。但是不能sp=PrintIt(),因为这样就成了函数调用。
3.委托用例
class Program
{
//定义一个委托类型DelegateString
public delegate string DelegateString(string text);
//定义一个ChangeString类
public class ChangeString
{
//定义一个ChangeStringText方法,包含一个字符串数组和一个委托变量
//ChangeText用来接收传进来的方法
public void ChangeStringText(string[] names,DelegateString ChangeText)
{
for (int i = ; i < names.Length; i++)
{
//调用传进来的方法改变字符串
names[i] = ChangeText(names[i]);
}
}
}
static void Main(string[] args)
{
ChangeString cs=new ChangeString();
string[] names = {"卡卡西","佐助","鸣人"};
//调用ChangeStringText方法,把names数组和JoinString方法传进去
cs.ChangeStringText(names, JoinString);
//遍历输出改变后的数组
for (int i = ; i < names.Length; i++)
{
Console.WriteLine(names[i]);
}
Console.ReadKey();
}
//定义一个NewString方法
public static string NewString(string name)
{
return "----"+name+"----";
}
//定义一个JoinString
public static string JoinString(string name)
{
return "★" + name + "★";
}
}
4.运行结果
传入NewString方法

传入JoinString方法

匿名方法
使用Delegate的时候很多时候没必要使用一个普通的方法,因为这个方法只有这个Delegate会用,并且只用一次,这时候使用匿名方法最合适。
匿名方法就是没有名字的方法。3就是没有名字的int对象。3+5就是两个匿名int对象的相加,允许匿名对象,就允许匿名方法。
ProcessWordDelegate p = delegate(string s)
{
Console.WriteLine(s);
};
知道C#中有匿名方法,看到这种写法知道是匿名函数即可。
匿名方法与lambda表达式最终编译为一个方法。
MyDelete md = delegate() { Console.WriteLine("嘎嘎"); };
md();
================================================================
public delegate void SayDelegate();
SayDelegate say = () => { Console.WriteLine("hhh"); };
public delegate int MyDelete2(int num);
MyDelete2 md2 = delegate(int number) { return number + 10; };
int result= md2(20);
Console.WriteLine(result);
Console.ReadKey();
================================================================
public delegate string SayDelegate(string n);
SayDelegate say = x => x+"好帅";
Console.WriteLine(say("小杨"));
===============================================================
T1((x, y, z) => x - y + z);
public static void T1(SayDelegate say)
{
int result = say(10, 20, 30);
Console.WriteLine(result);
}
public delegate int SayDelegate(int n1, int n2, int n3);
===============================================================
List<int> list = new List<int>() { 1,2,3,4,5,6,7,8,9};
IEnumerable ieor= list.Where(x=>x>5);
foreach (int item in ieor)
{
Console.WriteLine(item);
}
Console.ReadKey();
==============================================================
多播委托*(委托链,委托的组合)
delegate void ProcessWordDelegate(string s)
ProcessWordDelegate d = new ProcessWordDelegate(SayHello)+new ProcessWordDelegate(ToLower)
多播委托如何处理返回值?
委托绑定多个方法后,其中一个方法执行发生异常后面的方法还会继续执行吗?不会!
一个重要的方法GetInvocationList();//返回一个Delegate[]类型。Delegate类是一个抽象类,是所有委托的父类。
组合的委托必须是同一个类型
相当于创建了一个按照组合的顺序依次调用的新委托对象。
委托的组合一般是给事件用的,用普通的委托的时候很少用
为委托的增减方法
d+=SayHello,为委托增加一个方法,不要感觉奇怪,因为它就是d=d+ SayHello
d-=SayHello,将方法从委托中移除。
Delegate.Combine();
委托的一些应用:
凡是需要回调的地方都能用到委托。
自定义类(控件、通信类……(事件))
多线程
窗体之间回传值
正则表达式中替换Email掩码Replace()
委托的本质1(*)
其实就是一个类把方法包装了一下,委托都继承自System.MulticastDelegate,而System.MulticastDelegate又继承自System.Delegate
多播委托就是有一个委托数组,依次调用。
class Program
{
static void Main(string[] args)
{
UpdateDelegate upde = M1;
upde += M2;
upde += M3;
upde -= M2;
upde = M4;
upde();
Console.ReadKey();
//输出 M1 M2 M3 M4
}
public static void M1()
{
Console.WriteLine("M1");
}
public static void M2()
{
Console.WriteLine("M2");
}
public static void M3()
{
Console.WriteLine("M3");
}
public static void M4()
{
Console.WriteLine("M4");
}
}
public delegate void UpdateDelegate();
===================================================================
ResultDelegate M1 = T1;
M1 += T2;
M1 += T3;
M1 += T4;
int r = M1();
Console.WriteLine(r);
Console.ReadKey(); //输出M4
public static int T1()
{
return 1;
}
public static int T2()
{
return 2;
}
public static int T3()
{
return 3;
}
public static int T4()
{
return 4;
}
public delegate int ResultDelegate();
===========================================================
Delegate[]des= M1.GetInvocationList();
foreach (Delegate item in des)
{
ResultDelegate res = item as ResultDelegate;
Console.WriteLine(res());
}
=============================================================单独拿到里面每个方法
事件(通过委托实现的,委托才是事件能正常执行的核心内容)
事件语法:event ProcessWordDelegate 例子 OnInt
加了event关键字实现事件机制的好处:用了event事件,不可以修改事件已经注册的值;不可以冒充进行事件通知了。在IntUC类外部就不能通过OnInt(3)的方式调用注册的委托了。只能+=、-=!
事件本质论
event会自动生成一个private delegate变量和两个函数: add和remove,C#编译器用这两个方法支持+=和-=操作符 (*)。C#<>.Net。
public event MyDelegate OnEvent;
内部实现是(示例性)
private MyDelegate OnEvent;
public void Add(MyDelegate d)
{
OnEvent+=d;
}
public void Remove(MyDelegate d)
{
OnEvent-=d;
}
因为OnEvent是private的,所以在类外部不能OnEvent(1)触发事件,但是在类内部可以。
public的方法只有Add和Remove,所以只能+=、-=,其他的操作都是不可以的。
委托和事件的区别(常考)
委托和事件没有可比性,因为委托是数据类型,事件是对象(可以理解为对委托变量的封装。),下面说的是委托的对象(用委托方式实现的事件)和(标准的event方式实现)事件的区别。事件的内部是用委托实现的。(举例子:三种实现事件方式的区别(直接用委托实现、用私有委托+公有方法模拟事件,直接用event事件实现))
因为对于事件来讲,外部只能“注册自己+=、注销自己-=”,外界不可以注销其他的注册者,外界不可以主动触发事件,因此如果用Delegate就没法进行上面的控制,因此诞生了事件这种语法。add、remove。
事件是用来阉割委托实例的。事件只能add、remove自己,不能赋值。事件只能+=、-=,不能=、不能外部触发事件。
C#基础精华07(委托事件,委托的使用,匿名方法)的更多相关文章
- 委托学习过程及委托、Lambda表达式和匿名方法的关系总结及事件总结
第一章,当开始学习委托的时候,我们会问什么是委托?为什么要学习委托? 一,什么是委托? 委托是一个类,它定义了方法的类型,使得可以将方法当作另一个方法的参数来进行传递,这种将方法动态地赋给参数的做法, ...
- 泛型委托及委托中所涉及到匿名方法、Lambda表达式
泛型委托及委托中所涉及到匿名方法.Lambda表达式 引言: 最初学习c#时,感觉委托.事件这块很难,其中在学习的过程中还写了一篇学习笔记:委托.事件学习笔记.今天重新温故委托.事件,并且把最近学习到 ...
- 委托学习笔记后续:泛型委托及委托中所涉及到匿名方法、Lambda表达式
引言: 最初学习c#时,感觉委托.事件这块很难,其中在学习的过程中还写了一篇学习笔记:委托.事件学习笔记.今天重新温故委托.事件,并且把最近学习到和委托相关的匿名方法.Lambda表达式及泛型委托记录 ...
- 关于委托:异常{ 无法将 匿名方法 转换为类型“System.Delegate”,因为它不是委托类型 }
转自:http://www.cnblogs.com/xiaofei59/archive/2010/11/25/1887285.html 异常{ 无法将 匿名方法 转换为类型“System.Delega ...
- 关于委托:异常{ 无法将 匿名方法 转换为类型“System.Delegate”,因为它不是委托类型 }
异常{ 无法将 匿名方法 转换为类型"System.Delegate",因为它不是委托类型 } 委托实际上是把方法名作为参数,但是若有好多个方法时,就要指明是哪个参数 查看如下代 ...
- c#基础精华01(强调代码规范,虚方法,抽象方法,接口)
强调代码规范 规则(法律,必须遵守否则报错) 语法 规范(道德,大家都喜欢有道德的人.) 注释//,/**/,/// 骆驼命名 :第一个单词首字母小写,之后的单词首字母大写 userName.user ...
- .NET基础拾遗(4)委托和事件1
一.委托初窥:一个拥有方法的对象 (1)本质:持有一个或多个方法的对象:委托和典型的对象不同,执行委托实际上是执行它所“持有”的方法. (2)如何使用委托? ①声明委托类型(delegate关键字) ...
- 怎么理解js中的事件委托
怎么理解js中的事件委托 时间 2015-01-15 00:59:59 SegmentFault 原文 http://segmentfault.com/blog/sunchengli/119000 ...
- jQuery代码优化:事件委托篇
推荐阅读原文:http://www.ituring.com.cn/article/467# 推荐11收藏 随着DOM结构的复杂化和Ajax等动态脚本技术的运用,事件委托自然浮出了水面.jQuery为绑 ...
随机推荐
- new失败判断
使用 malloc/calloc 等分配内存的函数时,一定要检查其返回值是否为空;但是C++ 里,如果 new 分配内存失败,默认是抛出bad_alloc异常,不会返回空:但是有些编译器对c++标准支 ...
- jquery文字左右滚动
实现jquery文字左右滚动 <div class="fl">中奖名单:</div> <div class="scrollText" ...
- Unity3D编程回忆录,Unity3d视频教程,教父团队倾情之作
之前一直在看Unity3d的视频教程,包括很多老外的视频教程,老外的教程确实不错,技术含量很高,而且讲得很激情,让我有种恨不得一秒钟就想吧unity3d学个精通的冲动,只是,毕竟是英语教程,没办法,哎 ...
- undefined local variable or method ‘xxx’ for #<RSpec::Core::ExampleGroup::Nested_1::Nested_1:0xbc88d6c>错误解决方案
官方文档如下: https://github.com/rspec/rspec-rails/blob/master/Capybara.md Capybara 2.0 To use Capybara 2. ...
- 深入mongoDB(1)--mongod的线程模型与网络框架
最近工作需要开始研究mongoDB,我准备从其源代码角度,对于mongod和mongos服务的架构.sharding策略. replicaset策略.数据同步容灾.索引等机制做一个本质性的了解.其代码 ...
- Node.js 【CORS(cross origin resource sharing) on ExpressJS之笔记】
app.use(function(req, res, next) { res.header("Access-Control-Allow-Origin", "*" ...
- PyQt4学习记录之事件和信号
事件是任何 GUI程序中很重要的部分.所有 Python GUI 应用都是事件驱动的.一个应用对其生命期产生的不同的事件类型做出反应.事件是主要由应用的用户产生.但是,也可以通过其他方法产生,比如,网 ...
- vs2010配备boost编程环境
vs2010配备boost编程环境 vs2010配置boost编程环境 第一步:下载boost,我下载的方法是从http://www.boost.org/上找最新的下载.名字叫boost_1_53_0 ...
- http://phantomjs.org/page-automation.html
http://phantomjs.org/page-automation.html install brew curl -LsSf http://github.com/mxcl/homebrew/ta ...
- fedora 安装chrome
1. 下载chrome的rpm安装包 2. 安装lsb: sudo yum install redhat-lsb.x86_64 3. rpm -i google-chrome-{xxxxx}.rp ...