C#复习总结4
第十三章 委托
- 什么是委托
委托就是函数的指针。
其和类相似,其实就是用户自定义的引用类型。
委托是包含有序方法列表的对象,这些方法具有相同的签名和返回类型。
MyDel delvar = new MyDel(myInstObj.mym1); < == > MyDel delvar = myInstObj.mym1; //两者之间存成隐式转换。
委托 中还存在给委托赋值,这样会重新指向,组合委托等等。
委托可以添加方法也可以移除方法。 运算符: += -=
调用委托就和调用函数是一样的。
匿名方法:就是没有了 具体的的实例化后的方法名,只有函数体。
注意作用域的范围:
利用正则表达式,可以简化 委托。
代码如下:
- delegate
void PrintFunction();//定义一个没有返回值和参数的委托类型 - delegate
void MyDel(ref
int x);//引用参数 - class Test
- {
- public
void Print1() - {
- Console.WriteLine("Print1 --- instance");
- }
- public
static
void Print2() - {
- Console.WriteLine("Print2 ----- static");
- }
- public
void ADD2(ref
int x) - {
- x += 2;
- }
- public
void ADD3(ref
int x) - {
- x += 3;
- }
- }
- //调用
- //委托是指持有一个或多个方法的对象,说白了,其实就是函数指针
- //也可以理解为用户自定义的引用类型
- //可以把delegate看成是一个包含有序方法列表的对象,这些方法具有相同的签名和返回类型
- //调用列表中的方法可以是静态方法也可以是实例方法
- //一般先申明,然后创建委托对象。一般我们可以通过+=来组合委托
- //MyDel delA = MyIntObj.MyM1;//都是某个方法的名称,也就是其指针了
- //MyDel delB = MyIntObj.MyM2;
- //MyDel delC = delA + delB;
- Test test = new Test();//创建一个测试类实例
- PrintFunction pf99;//创建一个空委托
- pf99 = test.Print1;//实例化并初始化该委托
- //也可以 pf99 = new PrintFunction(test.Print1);//可以省略
- pf99 += Test.Print2;//给委托添加3个另外的方法
- pf99 += test.Print1;
- pf99 += Test.Print2;
- if (pf99 != null)
- {
- pf99();//确认委托有方法,并调用委托(无参方法)
- }
- else
- {
- Console.WriteLine("Delegate is empty!");
- }
- //调用带返回值的委托方法,只需在其他方法中有返回值即可,其执行的是最后一个方法的返回值。
- //调用带引用参数的委托 参数值会根据调用列表中的一个或多个方法的返回值而改变。
- MyDel mydel = test.ADD2;
- mydel += test.ADD3;
- int x = 5;
- mydel(ref x);
- Console.WriteLine("Value: {0}", x);
- //匿名方法
- //匿名方法是初始化委托是内联声明的方法,即不需要函数了,而是在委托内部自定义函数
- //匿名方法的参数列表必须在参数数量,参数类型与位置,修饰符三个方面与委托匹配。
- //当然,有时候,我们也可以省略参数列表中的数据声明。params参数必须放在最后。
- //delegate void Mydel(int x, params int[] y) ;
- //Mydel mydel = delegate(int x, int[] y){ };
- // Lambda 表达式
- // Mydel mydel = delegate(int x){return x + 1};//匿名方法
- // Mydel mydel = (int x) => {return x + 1}; //Lambda 表达式
- // Mydel mydel = x => x + 1;
第十四章 事件
- 发布者与订阅者模式
发布者就是数据的发送端,订阅者是数据的接收端,但是呢,订阅者必须先在发布者这一端注册才行。
需要在事件中使用的代码有5个部分:
对应的代码如下:
//简单点理解:订阅者订阅事件,发布者触发事件,订阅者执行事件处理程序。
利用系统的事件有一个好处不用自己单独在声明委托了,但是不能从发布者传递数据到订阅者去,怎么办?
通过扩展的EventArgs来实现。其实,只需要声明一个派生自EventArgs类即可。
代码如下:
- using System;
- using System.Collections.Generic;
- using System.Linq;
- using System.Text;
- namespace CsharpStart
- {
- delegate
void Hander();//声明委托 - //发布者类
- class Incrementer
- {
- public
event Hander CountedADozen;//创建事件并发布 (事件是特殊的委托) - public
void DoCount() - {
- for (int i = 0; i < 100; i++) //事件调用函数,或者称为触发事件函数
- {
- if (i % 12 ==0 && CountedADozen != null)
- {
- CountedADozen();//每增加12,事件触发一次
- }
- }
- }
- }
- //订阅者类
- class Dozens
- {
- public
int DozensCount { get; private
set; } - public Dozens(Incrementer incrementer)//以发布者类为参数
- {
- DozensCount = 0;
- incrementer.CountedADozen += IncrementerDozensCount;//订阅事件(为事件CountedADozen增加方法)
- }
- void IncrementerDozensCount()
- {
- DozensCount++; //声明事件处理程序
- }
- }
- //系统自带的委托类型
- public
delegate
void EventHandler(object sender, EventArgs e); - //其中,第一个参数是用来保存触发事件的对象的引用。
- //第二个参数用来保存状态信息,指明什么类型适用于该程序。
- //用系统自带的委托的话,就不需要自定义委托类型了
- //发布者类
- class Incrementer1
- {
- public
event EventHandler CountedADozen1;//创建事件并发布 (事件是特殊的委托) - public
void DoCount() - {
- for (int i = 0; i < 100; i++) //事件调用函数,或者称为触发事件函数
- {
- if (i % 12 == 0 && CountedADozen1 != null)
- {
- CountedADozen1(this,null);//每增加12,事件触发一次
- //触发事件时使用EventHandler的参数
- }
- }
- }
- }
- //订阅者类
- class Dozens1
- {
- public
int DozensCount1 { get; private
set; } - public Dozens1(Incrementer1 incrementer1)
- {
- DozensCount1 = 0;
- incrementer1.CountedADozen1 += IncrementerDozensCount1;//订阅事件
- }
- void IncrementerDozensCount1(object sender,EventArgs e)//事件处理程序的签名(特征)
- //必须和系统的委托的签名相匹配
- {
- DozensCount1++; //声明事件处理程序
- }
- }
- //如何传递数据到事件处理程序中
- public
class IncrementerEventArgs : EventArgs - {
- public
int IterationCount { get; set; } - }
- class Incrementer2
- {
- public
event EventHandler<IncrementerEventArgs> CountedADozen2;//使用自定义类的泛型委托 - public
void DoCount2() - {
- IncrementerEventArgs args = new IncrementerEventArgs();//使用自定义的类对象
- for (int i = 0; i < 100; ++i)
- {
- if (i % 12 == 0 && CountedADozen2 != null)
- {
- args.IterationCount = i;//携带的参数
- CountedADozen2(this, args);//可以理解为sendmessage
- }
- }
- }
- }
- class Dozens2
- {
- public
int DozensCount2 { get; set; } - public Dozens2(Incrementer2 incrementer)
- {
- DozensCount2 = 0;
- incrementer.CountedADozen2 += IncrementDozensCount;//订阅事件
- }
- public
void IncrementDozensCount(object sender, IncrementerEventArgs e)//事件处理程序 - {
- Console.WriteLine("Incremented at iteration : {0} in {1}",e.IterationCount,sender.ToString());
- DozensCount2++;
- }
- }
- }
- //调用
- //1、发布者/订阅者模式,当一个特定的程序事件发生时,程序的其他部分可以得到该事件
- //已经发生了的通知,并执行相应的 事件处理程序。调用(invoke)
- //5个部分: 1)声明委托。 发布者: 2)创建事件并发布 3)触发事件
- // 订阅者: 4)订阅事件 5)事件处理程序
- Incrementer incrementer = new Incrementer(); //实例化
- Dozens dozensCounter = new Dozens(incrementer);
- incrementer.DoCount();//触发事件,调用事件。
- Console.WriteLine("Number of dozens = {0}",dozensCounter.DozensCount);
- //2、使用系统定义的EventHandler委托
- Incrementer1 incrementer1 = new Incrementer1(); //实例化
- Dozens1 dozensCounter1 = new Dozens1(incrementer1);
- incrementer1.DoCount();//触发事件,调用事件。
- Console.WriteLine("Number of dozens1 = {0}", dozensCounter1.DozensCount1);
- //3、通过扩展的EventArgs来传递数据,简单的说就是通过派生类来实现
- Incrementer2 incrementer2 = new Incrementer2();
- Dozens2 dozensCounter2 = new Dozens2(incrementer2);//实例化
- incrementer2.DoCount2();//触发事件
- //4、我们还可以通过 -= 来移除事件。
- //我们在添加事件的时候,不仅仅可以从构造方法中添加(订阅)事件,也可以
- //在实例化后,在main函数中订阅事件。
- //5、事件访问器 我们可以为事件定义事件访问器 add与remove
C#复习总结4的更多相关文章
- iOS总结_UI层自我复习总结
UI层复习笔记 在main文件中,UIApplicationMain函数一共做了三件事 根据第三个参数创建了一个应用程序对象 默认写nil,即创建的是UIApplication类型的对象,此对象看成是 ...
- vuex复习方案
这次复习vuex,发现官方vuex2.0的文档写得太简略了,有些看不懂了.然后看了看1.0的文档,感觉很不错.那以后需要复习的话,还是先看1.0的文档吧.
- 我的操作系统复习——I/O控制和系统调用
上篇博客介绍了存储器管理的相关知识——我的操作系统复习——存储器管理,本篇讲设备管理中的I/O控制方式和操作系统中的系统调用. 一.I/O控制方式 I/O就是输入输出,I/O设备指的是输入输出设备和存 ...
- 复习(1)【Maven】
终于开始复习旧知识了,有输入必然要有输出.输入和输出之间的内化过程尤为重要,在复习的同时,真正把学到的东西积淀下来,加深理解. Maven项目概念与配置 Maven是一个项目管理和综合工具.Maven ...
- 《CSS权威指南》基础复习+查漏补缺
前几天被朋友问到几个CSS问题,讲道理么,接触CSS是从大一开始的,也算有3年半了,总是觉得自己对css算是熟悉的了.然而还是被几个问题弄的"一脸懵逼"... 然后又是刚入职新公司 ...
- JS复习--更新结束
js复习-01---03 一 JS简介 1,文档对象模型 2,浏览器对象模型 二 在HTML中使用JS 1,在html中使用<script></script>标签 2,引入外部 ...
- jQuery 复习
jQuery 复习 基础知识 1, window.onload $(function(){}); $(document).ready(function(){}); 只执行函数体重的最后一个方法,事 ...
- jQuery5~7章笔记 和 1~3章的复习笔记
JQery-05 对表单和表格的操作及其的应用 JQery-06 jQuery和ajax的应用 JQery-07 jQuery插件的使用和写法 JQery-01-03 复习 之前手写的笔记.实在懒得再 ...
- HTML和CSS的复习总结
HTML(Hypertext Markup Language)超文本标记语言:其核心就是各种标记!<html> HTML页面中的所有内容,都在该标签之内:它主要含<head>和 ...
- 2017年1月1日 java学习第二天复习
今天是新年的第一天,以前学习没有总结习惯,学习效率和成果都很不好. 学习的过程就是反复的复习和不断学习的过程,开始今天的学习总结 学习java的第二天. 今天学习了java最基础的一些内容,照着 ...
随机推荐
- [转]构建Python+Selenium2自动化测试环境(二)
构建Python+Selenium2自动化测试环境完成之后,就需要测试支持python的selenium的版本是否都支持在不同浏览器上运行,当前我们分别在三个最通用的浏览器上通过脚本来测试. 1.在I ...
- x86保护模式-七中断和异常
x86保护模式-七中断和异常 386相比较之前的cpu 增强了中断处理能力 并且引入了 异常概念 一 80386的中断和异常 为了支持多任务和虚拟存储器等功能,386把外部中断称为中断 ...
- 如何解决 错误code signing is required for product type 'xxxxx' in SDK 'iOS 8.2'
如何解决 错误code signing is required for product type 'xxxxx' in SDK 'iOS 8.2' 大家在做真机调试的时候,或许会遇到这样的问题,那如何 ...
- BZOJ 3518 点组计数 ——莫比乌斯反演
要求$ans=\sum_{i=1}^n \sum_{j=1}^m (n-i)(m-j)(gcd(i,j)-1)$ 可以看做枚举矩阵的大小,然后左下右上必须取的方案数. 这是斜率单增的情况 然后大力反演 ...
- spring DelegatingFilterProxy的原理及运用
DelegatingFilterProxy的原理及使用 DelegatingFilterProxy就是一个对于servlet filter的代理,用这个类的好处主要是通过Spring容器来管理serv ...
- ndarray:一种多维数组对象
ndarray是一个通用的同构数据多维容器,也就是说,其中的所有元素必须是相同类型的.每个数组都有一个shape(一个表示各维度大小的元组)和一个dtype(一个用于说明数组数据类型的对象). In ...
- 最长递增子序列(cogs 731)
«问题描述:给定正整数序列x1,..., xn.(1)计算其最长递增子序列的长度s.(2)计算从给定的序列中最多可取出多少个长度为s的递增子序列.(3)如果允许在取出的序列中多次使用x1和xn,则从给 ...
- android开发里跳过的坑——camera调用setDisplayOrientation设置预览显示旋转无效
问题原因,在surfaceview没有设置给camera之前调用了,所以,这个方法一定要在camera.setPreviewDisplay(surfaceHolder)这个之后,启动相机预览之前调用.
- Java远程调用BPS流程实现流程运行简单示例
1.简介:略 2.背景:略 3.目的:自我学习笔记 4.实现过程 (1).画出流程图 如下: 路由活动分支下的条件语句为复杂表达式: ((account<200&&divisio ...
- 【HDOJ6228】Tree(树)
题意:有一棵n个点的树,在树上的点涂色,每个点涂一种颜色,一共可以涂k种颜色, 然后把同一种颜色(比如说x)的点用最优方案连起来,在连线的边涂上x颜色,问涂k次的边最多有几条 k<=500 si ...