接上篇(C#委托详解(2):实现方式大全),本篇继续介绍委托的实现方式。

4、Action<T>和Func<T>委托

  使用委托时,除了为每个参数和返回类型定义一个新委托类型之外,还可以使用.NET Framework提供的泛型委托Action<T>和Func<T>,它们提供了从无参一直到最多16个参数的重载,如果方法需要获取16个以上的参数,就必须定义自己的委托类型,但这种情况应该是及其罕见的。其中Action<T>类可以调用没有返回值的方法,Func<T>允许调用带返回类型的方法。

  所以对于上一代码例子中的委托可以使用Func<double T, out Tresult>这样实现:

  1. Func <double, double> operations = MathOperations.MultiplyByTwo;

  等价于:

  1. delegate double Operations(double x);
  2. Operations operations = MathOperations.MultiplyByTwo;
  1. 即省略了对于委托类的定义。
  1.   下面这个例子使用泛型委托实现了一个普通的冒泡排序算法,来看看跟普通的冒泡排序有什么不一样的:
  1.   class BubbleSorter
  2. {
  3. static public void Sort<T>(IList<T> sortArray, Func<T, T, bool> comparison)
  4. {
  5. bool swapped = true;
  6. while (swapped)
  7. {
  8. swapped = false;
  9. for (int i = ; i < sortArray.Count - ; i++)
  10. {
  11. if (comparison(sortArray[i+], sortArray[i]))
  12. {
  13. T temp = sortArray[i];
  14. sortArray[i] = sortArray[i + ];
  15. sortArray[i + ] = temp;
  16. swapped = true;
  17. }
  18. }
  19. }
  20. }
  21. }

可以看到,代码实现没有什么不同,不同的是方法签名,第一个参数类型是IList<T>,它可以支持传入各种集合数据,第二个传入参数为一个委托对象,代表的是要排序的对象T的一个方法,这个方法会对两个对象T的大小进行比较,返回一个boolean类型的值,具体使用方法可以查看下面这段代码。

  1. class Student //需要排序的对象类型
  2. {
  3. public Student(string name, int salary)
  4. {
  5. this.Name = name;
  6. this.Age = salary;
  7. }
  8.  
  9. public string Name { get; private set; }
  10. public int Age { get; private set; }
  11.  
  12. public override string ToString()
  13. {
  14. return string.Format("{0}, {1:C}", Name, Age);
  15. }
  16.  
  17. public static bool CompareAge(Student e1, Student e2)
  18. {
  19. return e1.Age < e2.Age;
  20. }
  21. }
  22.  
  23. class Program
  24. {
  25. static void Main()
  26. {
  27. Student[] students =
  28. {
  29. new Student("zhangsan", ),
  30. new Student("lisi", ),
  31. new Student("wangwu", ),
  32. new Student("zhaoliu", ),
  33. };
  34.  
  35. BubbleSorter.Sort(students, Student.CompareAge); //传入对象数组,和一个方法地址
  36. foreach (var student in students)
  37. {
  38. Console.WriteLine(student);
  39. }
  40. }
  41. }

  上述代码中展示了委托的精髓,即将方法作为参数传递给其他方法,以增加代码的灵活性。(不清楚的童鞋一定仔细体会这种用法。)

5、匿名方法

  使用匿名方法定义委托与前面的定义没有什么区别,只是在实例化委托时,有一点区别。

  1. class Program
  2. {
  3. static void Main()
  4. {
  5. double width = ;
  6.  
  7. Func<double, double> square = delegate(double length) //这里的square是委托类型的实例
  8. {
  9. length *= width;
  10. return length;
  11. };
  12. Console.WriteLine(square());
  13. }
  14. }

  匿名方法的优点是减少了要编写的代码,不必定义仅由委托使用的方法。但如果需要用匿名方法多系编写同一个功能时就不建议使用匿名方法了。

6、Lambda表达式

  C#3.0开始支持Lambda表达式,可以使用其代替匿名方法。使用方法可以参考下面的例子:

  1. //1、不获取任何参数
  2. Func<string> f = () => "lining";
  3. //2、一个参数(可以显示指定类型也可以使用类型推断)
  4. Func<int, string> f1 = (int n) => n.ToString();
  5. Func<int, string> f2 = (n) => n.ToString();
  6. Func<int, string> f3 = n => n.ToString();
  7. //3、一个或多个参数
  8. Func<int, int, string> f4 = (int n1, int n2) => (n1 + n2).ToString();
  9. Func<int, int, string> f5 = (n1,n2) => (n1+n2).ToString();

  Lambda省去了书写方法,命名方法及传递方法的过程,可以减少代码量,提高编程效率。但其并没有对代码的执行效率带来优势。

  另外建议不要滥用lambda表达式,其对于调试和单步执行会带来一定的挑战。对于三行以上的代码推荐自己手动写一个方法,这样无论对于代码的可读性还是可服用性都是有益的。

  

本篇结束,对于委托的实现方式就先介绍这些,下一篇将介绍委托的Invoke,BeginInvoke和EndInvoke方法。

C#委托详解(3):委托的实现方式大全(续)的更多相关文章

  1. C#委托详解(2):实现方式大全

    本系列文章将详细探讨C#中的委托,列举其主要的实现方式,并分析其在设计层面和编码层面带来的好处,最后会讨论其安全性和执行效率等. 接上篇(C#委托详解(1):什么是委托)介绍完什么是委托之后,来看看C ...

  2. C#事件与委托详解

    from https://www.cnblogs.com/sjqq/p/6917497.html C#事件与委托详解[精华 多看看] Delegatedelegate是C#中的一种类型,它实际上是一个 ...

  3. 详解C#泛型(二) 获取C#中方法的执行时间及其代码注入 详解C#泛型(一) 详解C#委托和事件(二) 详解C#特性和反射(四) 记一次.net core调用SOAP接口遇到的问题 C# WebRequest.Create 锚点“#”字符问题 根据内容来产生一个二维码

    详解C#泛型(二)   一.自定义泛型方法(Generic Method),将类型参数用作参数列表或返回值的类型: void MyFunc<T>() //声明具有一个类型参数的泛型方法 { ...

  4. LVS原理详解(3种工作方式8种调度算法)--老男孩

    一.LVS原理详解(4种工作方式8种调度算法) 集群简介 集群就是一组独立的计算机,协同工作,对外提供服务.对客户端来说像是一台服务器提供服务. LVS在企业架构中的位置: 以上的架构只是众多企业里面 ...

  5. c# 委托详解

    1.委托声明 2.委托入门实例 namespace ConsoleApplication1 { public delegate void methodDelegate(string str); cla ...

  6. C#事件与委托详解【精华 多看看】

    Delegate delegate是C#中的一种类型,它实际上是一个能够持有对某个方法的引用的类.与其它的类不同,delegate类能够拥有一个签名(signature),并且它"只能持有与 ...

  7. 【C#】详解C#委托

    目录结构: contents structure [+] 委托语法 泛型委托 委托链 lambda表达式 揭秘委托 类库中的委托 委托和反射 1.委托语法 本文会详细阐述委托的使用,以及实现,想必读者 ...

  8. 详解C#委托和事件(一)

    委托(Delegate)是安全封装方法的类型,类似于C和C++中的函数指针,与函数指针不同的是,委托是面向对象的.类型安全的和可靠的: 一.委托类型是CTS中五种基础类型之一,是一种引用类型,表示对具 ...

  9. c#之委托详解(Delegate)

    一.委托的概念 在我们学习委托之前,我们来了解下,什么是委托呢? 官方概念:委托是一种安全地封装方法的类型,它与 C 和 C++ 中的函数指针类似.与 C 中的函数指针不同,委托是面向对象的.类型安全 ...

随机推荐

  1. linux 下wifi 功能的实现

    一.嵌入式linux四件套配置 1.网卡选型的依据: a.网卡不能乱选,否则没戏.网卡的依据是,kernel的menuconfig -> device drivers -> network ...

  2. 第六章_PHP数组(二)

    这篇随笔是对预定义数组变量的总结.通过预定义数组变量,我们可以获得系统环境.用户对话.表单数据等信息. 1.服务器变量:$_SERVER 利用foreach语句打印$_SERVER中的所有元素: &l ...

  3. NC V6 安装目录各文件夹作用描述

    ant:存放Apache Ant,用来执行EJB的构建. bin: 存放nc部署和系统监控等命令.configsys.log部署日志(包含NC中间件.WAS中间件等部署信息)以及NC_Client文件 ...

  4. 【转载】linux中互斥尽量用mutex,不用semaphore

    DEFINE_MUTEX是来自include/linux/mutex.h中的一个宏,用它可以定义一把互斥锁,在Linux内核中,其实是在2005年底才建立比较系统.完善的互斥锁机制,在那年冬天,来自R ...

  5. 判断手机,pc方式登录

     <script type="text/javascript">         function browserDetect() {             var  ...

  6. c#中$.ajax的使用

      <script type="text/javascript">  var telphone = { type: "getphone", &quo ...

  7. IOS基础——实例变量四种范围类型

    1.为了强制一个对象隐藏其数据,编译器限制实例变量范围以限制其在程序中的可见性. 但是为了提供灵活性,苹果也让开发者显示设置范围(四选一). 2.四种编译指令如下: @private 实例变量只能被声 ...

  8. jquery Ajax中的dataType简析

    jquery中的ajax有好几种运用方式,但是基本上都是使用的$.ajax()方法,很多人经常会使用它来从后台获取json格式的数据,但是经常发现返回的json字符串并不能自动的转换成js里的json ...

  9. zookeeper典型应用场景之一:master选举

    对于zookeeper这种东西,仅仅知道怎么安装是远远不够的,至少要对其几个典型的应用场景进行了解,才能比较全面的知道zk究竟能干啥,怎么玩儿,以后的日子里才能知道这货如何能为我所用.于是,有了如下的 ...

  10. 大体了解Lua的语法

    Lua 的语法比较简单,学习起来也比较省力,但功能却并不弱. 在Lua中,一切都是变量,除了关键字.请记住这句话. I. 首先是注释 写一个程序,总是少不了注释的. 在Lua中,你可以使用单行注释和多 ...