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

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

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

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

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

  等价于:

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

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

    class Student //需要排序的对象类型
{
public Student(string name, int salary)
{
this.Name = name;
this.Age = salary;
} public string Name { get; private set; }
public int Age { get; private set; } public override string ToString()
{
return string.Format("{0}, {1:C}", Name, Age);
} public static bool CompareAge(Student e1, Student e2)
{
return e1.Age < e2.Age;
}
} class Program
{
static void Main()
{
Student[] students =
{
new Student("zhangsan", ),
new Student("lisi", ),
new Student("wangwu", ),
new Student("zhaoliu", ),
}; BubbleSorter.Sort(students, Student.CompareAge); //传入对象数组,和一个方法地址
foreach (var student in students)
{
Console.WriteLine(student);
}
}
}

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

5、匿名方法

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

    class Program
{
static void Main()
{
double width = ; Func<double, double> square = delegate(double length) //这里的square是委托类型的实例
{
length *= width;
return length;
};
Console.WriteLine(square());
}
}

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

6、Lambda表达式

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

            //1、不获取任何参数
Func<string> f = () => "lining";
//2、一个参数(可以显示指定类型也可以使用类型推断)
Func<int, string> f1 = (int n) => n.ToString();
Func<int, string> f2 = (n) => n.ToString();
Func<int, string> f3 = n => n.ToString();
//3、一个或多个参数
Func<int, int, string> f4 = (int n1, int n2) => (n1 + n2).ToString();
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. 用IKVMC将jar转成dll供c#调用

    用IKVMC将jar转成dll供c#调用 ikvmc c# dll jar 用IKVMC将jar转成dll供c#调用 前言 ikvmc介绍 ikvmc下载安装 下载并解压 设置环境变量 jar-> ...

  2. java项目编译有误

    classpath component

  3. js随机生成字母数字组合的字符串 随机动画数字

    效果描述: 附件中只有一个index.html文件有效 其中包含css以及html两部分内容 纯js生成的几个随机数字 每次都不重复,点击按钮后再次切换 使用方法: 1.将css样式引入到你的网页中 ...

  4. JMeter2.13 连接 sql server

    1.安装驱动 http://www.microsoft.com/zh-CN/download/details.aspx?id=11774 下载最新的即可 解压后复制势穷力竭sqljdbc.jar到 “ ...

  5. canvas绘制文字

    绘制字体时可以使用fillText方法或者strokeText方法. fillText方法用填充的方式来绘制字符串 context.fillText (text, x,y,[maxwidth]); s ...

  6. js 月历 时间函数 月份第一天 星期的判断

    返回值为0-6,其中返回值0为星期天:如同,php中的日期函数一样判断.

  7. mysql 导入导出数据库、数据表

    Linux下 均在控制台下操作. 导入数据库: 前提:数据库和数据表要存在(已经被创建) (1)将数据表 test_user.sql 导入到test 数据库的test_user 表中 [root@te ...

  8. JS预览图像

    <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <hea ...

  9. 安装Spark集群(在CentOS上)

    环境:CentOS 6.4, Hadoop 1.1.2, JDK 1.7, Spark 0.7.2, Scala 2.9.3 1. 安装 JDK 1.7 yum search openjdk-deve ...

  10. c# float和double的“坑”

    定义一个float类型的变量=0.7,结果在IL中却是0.69999999. 乘以10之后,获取整数值.得到的却是6.通过查看IL,竟然被转换成double类型再转换.就变成6了. Demo: IL: ...