委托是一个类,它定义了方法的类型,使得可以将方法当作另一个方法的参数来进行传递。

与其他的类不同,委托类具有一个签名,并且它只能对与其签名匹配的方法进行引用

一、自定义委托类型

1.语法结构:访问修饰符 delegate 返回类型 委托类型名称(参数列表);

例如:

  1. // 声明一个委托类型,两个参数均为int类型,返回值为int类型
  2. public delegate int Calc(int a, int b);
    自定义的委托可以不带参数,也可以没有返回值。
  3.  
  4. 接下来我们看一个例子怎么使用委托

1.方法引用

  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Text;
  5. using System.Threading.Tasks;
  6.  
  7. namespace 委托
  8. {
  9. class Program
  10. {
  11. // 声明一个委托类型,两个参数均为int类型,返回值为int类型
  12. public delegate int Calc(int a, int b);
  13.  
  14. // 定义和委托签名一致的方法(参数类型和个数,返回值类型均一致)
  15. static int Add(int a, int b)
  16. {
  17. return a + b;
  18. }
  19.  
  20. static int Sub(int a, int b)
  21. {
  22. return a - b;
  23. }
  24.  
  25. static int Multi(int a, int b)
  26. {
  27. return a * b;
  28. }
  29.  
  30. static int Divis(int a, int b)
  31. {
  32. if (b == )
  33. {
  34. throw new Exception("除数不能为0!");
  35. }
  36.  
  37. return a / b;
  38. }
  39.  
  40. static void Main(string[] args)
  41. {
  42. Console.WriteLine("请输入第一个数:");
  43. int a = int.Parse(Console.ReadLine());
  44.  
  45. Console.WriteLine("请输入第二个数:");
  46. int b = int.Parse(Console.ReadLine());
  47.  
  48. // 定义一个Calc委托类型的变量,把和该委托签名一致的Add方法的引用赋值给变量
  49. Calc method = Add;
  50. Console.WriteLine("加法运算:{0}+{1}={2}", a, b, method(a, b));
  51.  
  52. method = Sub;
  53. Console.WriteLine("减法法运算:{0}-{1}={2}", a, b, method(a, b));
  54.  
  55. method = Multi;
  56. Console.WriteLine("乘法运算:{0}×{1}={2}", a, b, method(a, b));
  57.  
  58. method = Divis;
  59. Console.WriteLine("除法运算:{0}÷{1}={2}", a, b, method(a, b));
  60.  
  61. Console.ReadKey();
  62. }
  63. }
  64. }

(1)方法引用

2.匿名方法

给上述委托变量赋值时,必须先定义好一个和委托签名一致的方法。使用匿名方法,你就无需先定义好那些方法,直接通过delegate语法给委托变量赋值。

匿名方法的结构:delegate(参数列表){函数体};

例如:

  1. Calc method = delegate(int x, int y)
  2. {
  3. return x + y;
  4. };
  5.  
  6. 使用匿名方法重新实现上述例子:
(2)

  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Text;
  5. using System.Threading.Tasks;
  6.  
  7. namespace 匿名方法
  8. {
  9. class Program
  10. {
  11. // 声明一个委托类型,两个参数均为int类型,返回值为int类型
  12. delegate int Calc(int a, int b);
  13.  
  14. static void Main(string[] args)
  15. {
  16. Console.WriteLine("请输入第一个数:");
  17. int a = int.Parse(Console.ReadLine());
  18.  
  19. Console.WriteLine("请输入第二个数:");
  20. int b = int.Parse(Console.ReadLine());
  21.  
  22. // 定义一个Calc委托类型的变量
  23. Calc method = delegate(int x, int y)
  24. {
  25. return x + y;
  26. };
  27. Console.WriteLine("加法运算:{0}+{1}={2}", a, b, method(a, b));
  28.  
  29. method = delegate(int x, int y)
  30. {
  31. return x - y;
  32. };
  33. Console.WriteLine("减法法运算:{0}-{1}={2}", a, b, method(a, b));
  34.  
  35. method = delegate(int x, int y)
  36. {
  37. return x * y;
  38. };
  39. Console.WriteLine("乘法运算:{0}×{1}={2}", a, b, method(a, b));
  40.  
  41. method = delegate(int x, int y)
  42. {
  43. return x / y;
  44. };
  45. Console.WriteLine("除法运算:{0}÷{1}={2}", a, b, method(a, b));
  46.  
  47. Console.ReadKey();
  48. }
  49. }
  50. }

匿名方法

反编译生成的exe文件,你会发现编译器自动帮你生成了4个与自定义委托类型签名一致的方法,并且Main方法中的匿名方法变成了Lamdba表达式的形式,如图:

3.Lamdba表达式

Lamdba表达式其实就是一种语法糖,让你更能简洁的编写代码。

其语法结构:(参数列表)=>{函数体};

用Lamdba表达式实现上述例子:

(3)

  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Text;
  5. using System.Threading.Tasks;
  6.  
  7. namespace Lamdba表达式
  8. {
  9. class Program
  10. {
  11. // 声明一个委托类型,两个参数均为int类型,返回值为int类型
  12. delegate int Calc(int a, int b);
  13.  
  14. static void Main(string[] args)
  15. {
  16. Console.WriteLine("请输入第一个数:");
  17. int a = int.Parse(Console.ReadLine());
  18.  
  19. Console.WriteLine("请输入第二个数:");
  20. int b = int.Parse(Console.ReadLine());
  21.  
  22. // 定义一个Calc委托类型的变量
  23. Calc method = (x, y) => { return x + y; };
  24. Console.WriteLine("加法运算:{0}+{1}={2}", a, b, method(a, b));
  25.  
  26. method = (x, y) => x - y; // 也可以这样写
  27. Console.WriteLine("减法法运算:{0}-{1}={2}", a, b, method(a, b));
  28.  
  29. method = (x, y) => { return x * y; };
  30. Console.WriteLine("乘法运算:{0}×{1}={2}", a, b, method(a, b));
  31.  
  32. method = (x, y) => { return x / y; };
  33. Console.WriteLine("除法运算:{0}÷{1}={2}", a, b, method(a, b));
  34.  
  35. Console.ReadKey();
  36. }
  37. }
  38. }

Lamdba表达式

你也可以反编译生成的exe文件,你会发现结果与匿名方法反编译的效果一样。

二、.Net自带的委托类型

1.Func委托类型

Func是有返回值的泛型委托,可以没有参数,但最多只有16个参数,并且必须要有返回值,不能为void类型。如图:

  1. Func<int, int, int> // 第一,二个参数为int类型,返回值为int类型
  2. Func<string, string, bool> // 第一,二个参数string类型,返回值为bool类型
  3. Func<int, string, decimal> // 第一个参数为int类型,第二个参数为string类型,返回值为decimal类型

同自定义的委托类型一样,你可以为Func委托变量赋值为方法引用,匿名方法或者Lamdba表达式:

(1)方法引用 

(2)匿名方法

(3)Lamdba表达式

2.Action委托类型 
Action是没有返回值的泛型委托,可以没有参数,但最多只有16个参数,返回值为void类型。如图:

直接看例子:

  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Text;
  5. using System.Threading.Tasks;
  6.  
  7. namespace Action委托类型
  8. {
  9. class Program
  10. {
  11. static void Main(string[] args)
  12. {
  13. Action<string, string> method = (s1, s2) => { Console.WriteLine(s1 + s2); };
  14.  
  15. method("1+1=", "2");
  16. Console.ReadKey();
  17. }
  18. }
  19. }

3.Predicate委托类型 
Predicate是只有一个参数,且返回值为bool类型的泛型委托。

  1. // 摘要:
  2. // 表示定义一组条件并确定指定对象是否符合这些条件的方法。
  3. //
  4. // 参数:
  5. // obj:
  6. // 要按照由此委托表示的方法中定义的条件进行比较的对象。
  7. //
  8. // 类型参数:
  9. // T:
  10. // 要比较的对象的类型。
  11. //
  12. // 返回结果:
  13. // 如果 obj 符合由此委托表示的方法中定义的条件,则为 true;否则为 false。
  14. public delegate bool Predicate<in T>(T obj);

直接看例子:

  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Text;
  5. using System.Threading.Tasks;
  6.  
  7. namespace Predicate委托类型
  8. {
  9. class Program
  10. {
  11. static void Main(string[] args)
  12. {
  13. Predicate<int> method = (x) => { return x > 3; };
  14.  
  15. Console.WriteLine(method(4));// 输出:True
  16. Console.ReadKey();
  17. }
  18. }
  19. }

三、综合应用

这些自带的委托类型在泛型集合中使用的比较多,如:

接下来再看一个综合例子:

  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Text;
  5. using System.Threading.Tasks;
  6.  
  7. namespace 运用
  8. {
  9. class Program
  10. {
  11. static void Main(string[] args)
  12. {
  13. List<Student> list = new List<Student>
  14. {
  15. new Student{Name="张三",Age=},
  16. new Student{Name="李四",Age=},
  17. new Student{Name="王五",Age=},
  18. new Student{Name="马六",Age=},
  19. new Student{Name="李七",Age=}
  20. };
  21.  
  22. // Func委托类型
  23. List<Student> list2 = list.Where(item => item.Age < ).ToList();
  24. foreach (Student stu in list2)
  25. {
  26. Console.WriteLine("姓名:{0},年龄:{1}。", stu.Name, stu.Age);
  27. }
  28. Console.WriteLine("============================");
  29.  
  30. // Action委托类型
  31. list.ForEach((s) => { Console.WriteLine("姓名:{0},年龄:{1}。", s.Name, s.Age); });
  32. Console.WriteLine("============================");
  33.  
  34. // Predicate委托类型
  35. Student student = list.Find(item => item.Age > );
  36. Console.WriteLine("姓名:{0},年龄:{1}。", student.Name, student.Age);
  37. Console.WriteLine("============================");
  38.  
  39. Console.ReadKey();
  40. }
  41. }
  42.  
  43. class Student
  44. {
  45. public string Name { get; set; }
  46.  
  47. public int Age { get; set; }
  48. }
  49. }

运行结果: 

原文:http://www.tuicool.com/articles/maYBRb

自定义委托类型 - .Net自带委托类型的更多相关文章

  1. 泛型 System.Collections.Generic及泛型继承、运算符、结构、接口、方法、委托、事件、可空类型等

    一.定义泛型类 void Main() { //实例化泛型类时,才指定具体的类型 MyGenericClass<); Console.WriteLine(MyGeneri.InnerT1Obje ...

  2. .Net自带的委托类型—Func,Action 和 Predicate

    委托是一个类,它定义了方法的类型,使得可以将方法当作另一个方法的参数来进行传递. 与其他的类不同,委托类具有一个签名,并且它只能对与其签名匹配的方法进行引用. 一.自定义委托类型 1.语法结构:访问修 ...

  3. C#简单问题,不简单的原理:不能局部定义自定义类型(不含匿名类型)

    今天在进行代码测试时发现,尝试在一个方法中定义一个委托,注意是定义一个委托,而不是声明一个委托变量,在编写的时候没有报错,VS也能智能提示,但在编译时却报语法不完整,缺少方括号,但实际查询并没有缺少, ...

  4. 事件,使用.net自带委托EventHandler

    using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.T ...

  5. 《Go语言实战》Go 类型:基本类型、引用类型、结构类型、自定义类型

    Go 语言是一种静态类型的编程语言,所以在编译器进行编译的时候,就要知道每个值的类型,这样编译器就知道要为这个值分配多少内存,并且知道这段分配的内存表示什么. 提前知道值的类型的好处有很多,比如编译器 ...

  6. 《精通C#》自定义类型转化-扩展方法-匿名类型-指针类型(11.3-11.6)

    1.类型转化在C#中有很多,常用的是int类型转string等,这些都有微软给我们定义好的,我们需要的时候直接调用就是了,这是值类型中的转化,有时候我们还会需要类类型(包括结构struct)的转化,还 ...

  7. Mybatis中使用自定义的类型处理器处理枚举enum类型

    知识点:在使用Mybatis的框架中,使用自定义的类型处理器处理枚举enum类型 应用:利用枚举类,处理字段有限,可以用状态码,代替的字段,本实例,给员工状态字段设置了一个枚举类 状态码,直接赋值给对 ...

  8. 026 Android 带不同类型条目的listview(纯文本类型的条目,图片+文字类型的条目)+读取内存空间、手机进程信息+常驻悬浮框

    1.目标效果 带不同类型条目的listview(纯文本类型的条目,图片+文字类型的条目)+常驻悬浮框 2.页面布局文件 (1)activity_process_manager.xml <?xml ...

  9. 带Boolean类型的参数的接口用postman测试时传参问题

    带Boolean类型的参数的接口用postman测试时传参问题 @Data public class ATest { private Boolean isCommit; } postman 测试时传参 ...

随机推荐

  1. Python读写csv

    读取csv: http://blog.csdn.net/lixiang0522/article/details/7755059 读取Excel: http://www.cnblogs.com/lhj5 ...

  2. MyBatis:统计数量

    dao: /** * 统计商家的案例数量 * * @param shopId * @return */ long countByShopId(Long shopId); @Override publi ...

  3. xpath定位中starts-with、contains和text()的用法

    starts-with 顾名思义,匹配一个属性开始位置的关键字 contains 匹配一个属性值中包含的字符串 text() 匹配的是显示文本信息,此处也可以用来做定位用 eg //input[sta ...

  4. Redis 3.0 Cluster集群配置

    Redis 3.0 Cluster集群配置 安装环境依赖 安装gcc:yum install gcc 安装zlib:yum install zib 安装ruby:yum install ruby 安装 ...

  5. kvm虚拟机静态和动态迁移

    一.kvm虚拟机静态迁移 1.静态迁移就是虚拟机在关机状态下,拷贝虚拟机虚拟磁盘文件与配置文件到目标虚拟主机中,实现的迁移. (1)虚拟主机各自使用本地存储存放虚拟机磁盘文件 本文实现基于本地磁盘存储 ...

  6. Python使用TuShare将股票数据保存到Oracle数据

    TuShare是个获取股票数据的模块包,我们进行分析,需要将股票数据保存到本地,避免每次都从网上获取,由于本机装有ORCALE,以ORACLE为例介绍如何保存股票数据到本地. 一.大致思路:我们先获取 ...

  7. windows server 2008 wamp安装报000F15A0解决方法

    wampserver2.2c-x64 原因:缺少Visual C++ 2008 Runtime x64,官网地址http://www.microsoft.com/zh-cn/download/deta ...

  8. checkbox check all or ancheck all

    <script type="text/javascript" src="js/jQuery.1.8.3.min.js"></script> ...

  9. sqlserver添加主键

    sqlServer中给表添加主键的sql: alter table market_media_medical_history alter column pk_id bigint not null; a ...

  10. tp5 model 的时间戳

    单独在模型里面设置:(推荐) protected $autoWriteTimestamp = true; // int 型 protected $autoWriteTimestamp = 'datet ...