C#复习总结4

第十三章 委托

  1. 什么是委托

    委托就是函数的指针。

其和类相似,其实就是用户自定义的引用类型。

委托是包含有序方法列表的对象,这些方法具有相同的签名和返回类型。

MyDel delvar = new MyDel(myInstObj.mym1); < == > MyDel delvar = myInstObj.mym1; //两者之间存成隐式转换。

委托 中还存在给委托赋值,这样会重新指向,组合委托等等。

委托可以添加方法也可以移除方法。 运算符: += -=

调用委托就和调用函数是一样的。

匿名方法:就是没有了 具体的的实例化后的方法名,只有函数体。

注意作用域的范围:

利用正则表达式,可以简化 委托。

?

代码如下:

  1. ???delegate
    void PrintFunction();//定义一个没有返回值和参数的委托类型
  2. ???delegate
    void MyDel(ref
    int x);//引用参数
  3. ???class Test
  4. ???{
  5. ???????public
    void Print1()
  6. ???????{
  7. ???????????Console.WriteLine("Print1 --- instance");
  8. ???????}
  9. ???????public
    static
    void Print2()
  10. ???????{
  11. ???????????Console.WriteLine("Print2 ----- static");
  12. ???????}
  13. ???????public
    void ADD2(ref
    int x)
  14. ???????{
  15. ???????????x += 2;
  16. ???????}
  17. ???????public
    void ADD3(ref
    int x)
  18. ???????{
  19. ???????????x += 3;
  20. ???????}
  21. ???}
  22. //调用
  23. ??????????//委托是指持有一个或多个方法的对象,说白了,其实就是函数指针
  24. ???????????//也可以理解为用户自定义的引用类型
  25. ????????????//可以把delegate看成是一个包含有序方法列表的对象,这些方法具有相同的签名和返回类型
  26. ????????????//调用列表中的方法可以是静态方法也可以是实例方法
  27. ????????????//一般先申明,然后创建委托对象。一般我们可以通过+=来组合委托
  28. ????????????//MyDel delA = MyIntObj.MyM1;//都是某个方法的名称,也就是其指针了
  29. ????????????//MyDel delB = MyIntObj.MyM2;
  30. ????????????//MyDel delC = delA + delB;
  31. ????????????Test test = new Test();//创建一个测试类实例
  32. ????????????PrintFunction pf99;//创建一个空委托
  33. ????????????pf99 = test.Print1;//实例化并初始化该委托
  34. ????????????//也可以 pf99 = new PrintFunction(test.Print1);//可以省略
  35. ????????????pf99 += Test.Print2;//给委托添加3个另外的方法
  36. ????????????pf99 += test.Print1;
  37. ????????????pf99 += Test.Print2;
  38. ????????????if (pf99 != null)
  39. ????????????{
  40. ????????????????pf99();//确认委托有方法,并调用委托(无参方法)
  41. ????????????}
  42. ????????????else
  43. ????????????{
  44. ????????????????Console.WriteLine("Delegate is empty!");
  45. ????????????}
  46. ????????????//调用带返回值的委托方法,只需在其他方法中有返回值即可,其执行的是最后一个方法的返回值。
  47. ????????????//调用带引用参数的委托 参数值会根据调用列表中的一个或多个方法的返回值而改变。
  48. ????????????MyDel mydel = test.ADD2;
  49. ?????????????????mydel += test.ADD3;
  50. ?
  51. ????????????int x = 5;
  52. ????????????mydel(ref x);
  53. ?
  54. ????????????Console.WriteLine("Value: {0}", x);
  55. ?
  56. ????????????//匿名方法
  57. ????????????//匿名方法是初始化委托是内联声明的方法,即不需要函数了,而是在委托内部自定义函数
  58. ????????????//匿名方法的参数列表必须在参数数量,参数类型与位置,修饰符三个方面与委托匹配。
  59. ????????????//当然,有时候,我们也可以省略参数列表中的数据声明。params参数必须放在最后。
  60. ????????????//delegate void Mydel(int x, params int[] y) ;
  61. ????????????//Mydel mydel = delegate(int x, int[] y){ };
  62. ????????????// Lambda 表达式
  63. ????????????// Mydel mydel = delegate(int x){return x + 1};//匿名方法
  64. ????????????// Mydel mydel = (int x) => {return x + 1}; //Lambda 表达式
  65. ????????????// Mydel mydel = x => x + 1;

?

第十四章 事件

  1. 发布者与订阅者模式

    发布者就是数据的发送端,订阅者是数据的接收端,但是呢,订阅者必须先在发布者这一端注册才行。

    ?

    需要在事件中使用的代码有5个部分:

    对应的代码如下:

    //简单点理解:订阅者订阅事件,发布者触发事件,订阅者执行事件处理程序。

    ?

    利用系统的事件有一个好处不用自己单独在声明委托了,但是不能从发布者传递数据到订阅者去,怎么办?

    通过扩展的EventArgs来实现。其实,只需要声明一个派生自EventArgs类即可。

    代码如下:

  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Text;
  5. ?
  6. namespace CsharpStart
  7. {
  8. ????delegate
    void Hander();//声明委托
  9. ????//发布者类
  10. ????class Incrementer
  11. ????{
  12. ????????public
    event Hander CountedADozen;//创建事件并发布 (事件是特殊的委托)
  13. ????????public
    void DoCount()
  14. ????????{
  15. ????????????for (int i = 0; i < 100; i++) //事件调用函数,或者称为触发事件函数
  16. ????????????{
  17. ????????????????if (i % 12 ==0 && CountedADozen != null)
  18. ????????????????{
  19. ????????????????????CountedADozen();//每增加12,事件触发一次
  20. ????????????????}
  21. ????????????}
  22. ????????}
  23. ????}
  24. ????//订阅者类
  25. ????class Dozens
  26. ????{
  27. ????????public
    int DozensCount { get; private
    set; }
  28. ?
  29. ????????public Dozens(Incrementer incrementer)//以发布者类为参数
  30. ????????{
  31. ????????????DozensCount = 0;
  32. ????????????incrementer.CountedADozen += IncrementerDozensCount;//订阅事件(为事件CountedADozen增加方法)
  33. ????????}
  34. ????????void IncrementerDozensCount()
  35. ????????{
  36. ????????????DozensCount++; //声明事件处理程序
  37. ????????}
  38. ????}
  39. ?
  40. //系统自带的委托类型
  41. ????public
    delegate
    void EventHandler(object sender, EventArgs e);
  42. //其中,第一个参数是用来保存触发事件的对象的引用。
  43. ????//第二个参数用来保存状态信息,指明什么类型适用于该程序。
  44. ??//用系统自带的委托的话,就不需要自定义委托类型了
  45. ????//发布者类
  46. ????class Incrementer1
  47. ????{
  48. ????????public
    event EventHandler CountedADozen1;//创建事件并发布 (事件是特殊的委托)
  49. ????????public
    void DoCount()
  50. ????????{
  51. ????????????for (int i = 0; i < 100; i++) //事件调用函数,或者称为触发事件函数
  52. ????????????{
  53. ????????????????if (i % 12 == 0 && CountedADozen1 != null)
  54. ????????????????{
  55. ????????????????????CountedADozen1(this,null);//每增加12,事件触发一次
  56. ??????????????????????????????????????????????//触发事件时使用EventHandler的参数
  57. ????????????????}
  58. ????????????}
  59. ????????}
  60. ????}
  61. ????//订阅者类
  62. ????class Dozens1
  63. ????{
  64. ????????public
    int DozensCount1 { get; private
    set; }
  65. ?
  66. ????????public Dozens1(Incrementer1 incrementer1)
  67. ????????{
  68. ????????????DozensCount1 = 0;
  69. ????????????incrementer1.CountedADozen1 += IncrementerDozensCount1;//订阅事件
  70. ????????}
  71. ????????void IncrementerDozensCount1(object sender,EventArgs e)//事件处理程序的签名(特征)
  72. ?????????????????????????????????????????????????????????//必须和系统的委托的签名相匹配
  73. ????????{
  74. ????????????DozensCount1++; //声明事件处理程序
  75. ????????}
  76. ????}
  77. ?
  78. ??//如何传递数据到事件处理程序中
  79. ????public
    class IncrementerEventArgs : EventArgs
  80. ????{
  81. ????????public
    int IterationCount { get; set; }
  82. ????}
  83. ?
  84. ????class Incrementer2
  85. ????{
  86. ????????public
    event EventHandler<IncrementerEventArgs> CountedADozen2;//使用自定义类的泛型委托
  87. ?
  88. ????????public
    void DoCount2()
  89. ????????{
  90. ????????????IncrementerEventArgs args = new IncrementerEventArgs();//使用自定义的类对象
  91. ????????????for (int i = 0; i < 100; ++i)
  92. ????????????{
  93. ????????????????if (i % 12 == 0 && CountedADozen2 != null)
  94. ????????????????{
  95. ????????????????????args.IterationCount = i;//携带的参数
  96. ????????????????????CountedADozen2(this, args);//可以理解为sendmessage
  97. ????????????????}
  98. ????????????}
  99. ????????}
  100. ????}
  101. ?
  102. ????class Dozens2
  103. ????{
  104. ????????public
    int DozensCount2 { get; set; }
  105. ????????public Dozens2(Incrementer2 incrementer)
  106. ????????{
  107. ????????????DozensCount2 = 0;
  108. ????????????incrementer.CountedADozen2 += IncrementDozensCount;//订阅事件
  109. ????????}
  110. ????????public
    void IncrementDozensCount(object sender, IncrementerEventArgs e)//事件处理程序
  111. ????????{
  112. ????????????Console.WriteLine("Incremented at iteration : {0} in {1}",e.IterationCount,sender.ToString());
  113. ????????????DozensCount2++;
  114. ????????}
  115. ????}
  116. }
  117. ?
  118. //调用
  119. ?//1、发布者/订阅者模式,当一个特定的程序事件发生时,程序的其他部分可以得到该事件
  120. ????????????//已经发生了的通知,并执行相应的 事件处理程序。调用(invoke)
  121. ????????????//5个部分: 1)声明委托。 发布者: 2)创建事件并发布 3)触发事件
  122. ????????????// 订阅者: 4)订阅事件 5)事件处理程序
  123. ????????????Incrementer incrementer = new Incrementer(); //实例化
  124. ????????????Dozens dozensCounter = new Dozens(incrementer);
  125. ????????????incrementer.DoCount();//触发事件,调用事件。
  126. ????????????Console.WriteLine("Number of dozens = {0}",dozensCounter.DozensCount);
  127. ????????????//2、使用系统定义的EventHandler委托
  128. ????????????Incrementer1 incrementer1 = new Incrementer1(); //实例化
  129. ????????????Dozens1 dozensCounter1 = new Dozens1(incrementer1);
  130. ????????????incrementer1.DoCount();//触发事件,调用事件。
  131. ????????????Console.WriteLine("Number of dozens1 = {0}", dozensCounter1.DozensCount1);
  132. ????????????//3、通过扩展的EventArgs来传递数据,简单的说就是通过派生类来实现
  133. ????????????Incrementer2 incrementer2 = new Incrementer2();
  134. ????????????Dozens2 dozensCounter2 = new Dozens2(incrementer2);//实例化
  135. ????????????incrementer2.DoCount2();//触发事件
  136. ?
  137. ????????????//4、我们还可以通过 -= 来移除事件。
  138. ????????????//我们在添加事件的时候,不仅仅可以从构造方法中添加(订阅)事件,也可以
  139. ????????????//在实例化后,在main函数中订阅事件。
  140. ?
  141. ????????????//5、事件访问器 我们可以为事件定义事件访问器 add与remove
时间: 2024-10-12 20:59:43

C#复习总结4的相关文章

C++基础复习

一. C++与C的比较: C语言是一个结构化语言,它的重点在于算法和数据结构,C语言的设计首先要考虑的是如何通过一个过程,对输入(或环境条件)进行运算处理得到的输出(或实现过程(事物)控制). C++,首要考虑的是如何构造一个对象模型,让这个模型能够契合与之对应的问题域,这样就可以通过获取对象的状态信息得到输出或实现过程(事物)控制. 所以C语言和C++的最大区别在于它们解决问题的思想不同,一个面向过程一个面向对象. C++对C的"增强",表现在六个方面: 1.类型检测更为严格. 2.

大量逻辑判断优化的思路——责任链模式复习总结及其和状态模式对比

俗话说,自己写的代码,6个月后也是别人的代码……复习!复习!复习!涉及的总结知识点如下: 责任链模式概念和例子 使用的条件 和状态模式的比较分析 责任链的优缺点 纯的责任链和不纯的责任链 javax.servlet.Filter#doFilter()方法源码分析 基于AOP思想,模拟一个拦截器 前面说了一个状态模式,总结过程中发现和这个责任链的使用场景很类似,都是为了解耦大量复杂业务逻辑判断的,那么他们有什么不同呢?回忆状态模式——状态模式允许通过改变对象的内部状态而改变对象自身的行为,这个对象

算法分析与设计复习

算法分析与设计复习 2016年初,研一上学期期末考试前,复习并总结算法分析与设计科目的内容.复习过程参照<算法导论>中文第2版,同时参照PPT,章节划分根据PPT内容 概要: 第一章 概述 第二章 插入排序&分治策略 第三章 复杂度分析 第四章 堆与堆排序 第五章 快速排序 第六章 线性时间排序 第一章 概述 算法的应用范围 算法在诸如生物等诸多领域有其应用 算法的意义 算法在很多情况下让不可能完成的事情变成了可能,让处理的很慢的过程变快. 一个铺垫 一串不全为0的数,怎么取能拿到一段

复习PHP-语言参考-预定义接口

1.Traversable 他是一个遍历接口规范 注意:发现一个有用的函数get_declared_classes,可以以数组形式显示当前脚本下所有已经定义的类名 2.Iterator Iterator迭代器继承自Traversable,是一种遍历对象内容的对象. 你可以自己写一个子类继承自它,并写上具体遍历的方法. Iterator包含:current(返回当前元素),key(当前键),next(下一个元素),rewind(返回至初始元素),valid(检测当前元素是否存在)五种方法. 3.I

underscore 复习 对象函数 篇章

_.partial = function(func) { var boundArgs = slice.call(arguments, 1); var bound = function() { var position = 0, length = boundArgs.length; var args = Array(length); for (var i = 0; i < length; i++) { args[i] = boundArgs[i] === _ ? arguments[positio

数据结构复习之C语言指针与结构体

数据结构指针复习: #include <stdio.h> void main() { int a[5] = {8, 2, 3, 4, 5}; // a[3] == *(3+a) printf("%d\n", *(3+a)); // a[3] 4 printf("*a其实就是a[0]: %d\n", *a); // 8 // 地址是连续的 printf("%p\n", a+1); printf("%p\n", a+2

jsp servlet基础复习 Part1

jsp和servlet的一些基础知识整理,用于备忘. 一.jsp与servlet的基本关系 1.jsp-->web容器-->servlet-->加载进容器的虚拟机执行-->输出执行结果给浏览器端 在这个过程,所有位于<%%>之外的值,都被认为是out.println()中的内容进行直接输出.详细理解看代码 <html> <% //例子说明:servlet和jsp的关系 boolean b = false; if(b){ %> 这里是内容一 <

shell脚本复习

最近公司工作量很小,就复习复习,看起了马哥的视频,感觉马哥讲课讲得特别细.这才是深入到系统的讲解,补充了很多我之前只是了解到皮毛的东西. shell编程:弱类型编程语言 强:变量在使用前,必须事先声明,甚至还需要初始化 NULL: 弱:变量用时声明,甚至不区分类型: 变量赋值:VAR_NAME=VALUE 编译器,解释器 编程语言:机器语言.汇编语言.高级语言 静态语言:编译型语言 强类型(变量) 关键字: 事先转换成可执行格式 C.  C++.JAVA.C# 动态语言:解释型语言 on the

[Java面试一]面试复习大纲.

一.Java基础部分 (搞定所有技术之后才考虑复习的技术点) 1.数组中的排序问题(笔试或者机试,前者可能性更大) 2.面向对象的理解 3.集合相关的问题,比如hashmap跟hashtable的区别.搞清楚每个集合对象的特性就欧了. 4.多线程启动方式,以及产生死锁的原因和解决办法[多线程问题不是很常问,有精力就复习这块内容] 5.IO流,了解常见的几个流对象以及基本的流操作即可,被机试的可能性比较小. 二.Web基础 (1年工作经验者需要重点复习的技术点) 1.http协议(定义.常见的请求

c#复习-2

输入三个学生的信息学号.姓名.分数从大到小排序 1 using System; 2 using System.Collections; 3 using System.Collections.Generic; 4 using System.Linq; 5 using System.Text; 6 7 namespace 复习CS 8 { 9 class Program 10 { 11 struct Student 12 { 13 public int num; 14 public string C