C#委托详解(3):委托的实现方式大全(续)
接上篇(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):委托的实现方式大全(续)的更多相关文章
- C#委托详解(2):实现方式大全
本系列文章将详细探讨C#中的委托,列举其主要的实现方式,并分析其在设计层面和编码层面带来的好处,最后会讨论其安全性和执行效率等. 接上篇(C#委托详解(1):什么是委托)介绍完什么是委托之后,来看看C ...
- C#事件与委托详解
from https://www.cnblogs.com/sjqq/p/6917497.html C#事件与委托详解[精华 多看看] Delegatedelegate是C#中的一种类型,它实际上是一个 ...
- 详解C#泛型(二) 获取C#中方法的执行时间及其代码注入 详解C#泛型(一) 详解C#委托和事件(二) 详解C#特性和反射(四) 记一次.net core调用SOAP接口遇到的问题 C# WebRequest.Create 锚点“#”字符问题 根据内容来产生一个二维码
详解C#泛型(二) 一.自定义泛型方法(Generic Method),将类型参数用作参数列表或返回值的类型: void MyFunc<T>() //声明具有一个类型参数的泛型方法 { ...
- LVS原理详解(3种工作方式8种调度算法)--老男孩
一.LVS原理详解(4种工作方式8种调度算法) 集群简介 集群就是一组独立的计算机,协同工作,对外提供服务.对客户端来说像是一台服务器提供服务. LVS在企业架构中的位置: 以上的架构只是众多企业里面 ...
- c# 委托详解
1.委托声明 2.委托入门实例 namespace ConsoleApplication1 { public delegate void methodDelegate(string str); cla ...
- C#事件与委托详解【精华 多看看】
Delegate delegate是C#中的一种类型,它实际上是一个能够持有对某个方法的引用的类.与其它的类不同,delegate类能够拥有一个签名(signature),并且它"只能持有与 ...
- 【C#】详解C#委托
目录结构: contents structure [+] 委托语法 泛型委托 委托链 lambda表达式 揭秘委托 类库中的委托 委托和反射 1.委托语法 本文会详细阐述委托的使用,以及实现,想必读者 ...
- 详解C#委托和事件(一)
委托(Delegate)是安全封装方法的类型,类似于C和C++中的函数指针,与函数指针不同的是,委托是面向对象的.类型安全的和可靠的: 一.委托类型是CTS中五种基础类型之一,是一种引用类型,表示对具 ...
- c#之委托详解(Delegate)
一.委托的概念 在我们学习委托之前,我们来了解下,什么是委托呢? 官方概念:委托是一种安全地封装方法的类型,它与 C 和 C++ 中的函数指针类似.与 C 中的函数指针不同,委托是面向对象的.类型安全 ...
随机推荐
- php5.3 连接 sqlserver2005
操作系统:XP php5.3以后,已经不对sqlserver支持连接扩展了,不过微软官方还是对php5.3以后进行了扩展解决方案. 1.确认要连接sqlserver的数据库版本为2005 2.确认ph ...
- ASP.NET验证控件二
RequiredFieldValidator 验证控件 页面布局: <div> <h1>RequiredFieldValidator 验证控件</h1> 用户名 ...
- IPHONE 字体加粗
UIFONT 没有字体加精参数,但可以修发,字体名,达到加粗的效果正常:Helvetica加粗"Helvetica-Bold""TimesNewRomanPS-BoldM ...
- linux device model简述
参考: 1)<LINUX设备驱动程序>第十四章 Linux 设备模型 2)内核源码2.6.38 内核初始化的时候会对设备模型作初始化,见init/main.c: start_kernel- ...
- Cassandra 的压缩策略STCS,LCS 和 DTCS
更新说明: 本文编写时最新的Cassandra版本为2.2,最新的稳定版本为2.1.8 2016年6月23日,增加一篇译文,当下最新版本为3.7 最新的Cassandra 2.1 或者更高的版本支持3 ...
- php抓取post方式提交的页面
function curlBy($url, $data=array()) { $ch = curl_init(); if(!empty($data)){ ...
- asp.net导出excel示例代码
asp.net导出excel的简单方法. excel的操作,最常用的就是导出和导入. 本例使用NPOI实现. 代码:/// <summary> ); ; ...
- Delphi XE5 for android 调用Java类库必看的文件
C:\Program Files\Embarcadero\RAD Studio\12.0\source\rtl\android 的目录 Androidapi.AppGlue.pasAndroidapi ...
- Mongodb 3.0 创建用户
MongoDB 3.0 安全权限访问控制,在添加用户上面3.0版本和之前的版本有很大的区别,这里就说明下3.0的添加用户的方法. 创建第一个用户(该用户需要有grant权限,即:账号管理的授权权限) ...
- MongoDB 学习笔记(二)—— MongoDB Shell
MongoDB自带一个JavaScript shell 可以从命令行中与MongoDB交互,功能非常强大.如在上一节最后一张图所看到,可以执行JavaScript程序. 运行Shell 前提是启动Mo ...