C#基础之匿名方法实例教程
本文以实例形式讲解了C#的匿名方法的用法,分享给大家供大家参考之用。具体如下:
匿名方法是C# 2.0的语言新特性。首先看个最简单的例子:
class Program
{
static void Main(string[] args)
{
List<string> names = new List<string>();
names.Add("Sunny Chen");
names.Add("Kitty Wang");
names.Add("Sunny Crystal"); List<string> found = names.FindAll( new Predicate<string>(NameMatches)); if (found != null)
{
foreach (string str in found)
Console.WriteLine(str);
}
} static bool NameMatches(string name)
{
return name.StartsWith("sunny", StringComparison.OrdinalIgnoreCase);
}
}
这段代码在开始的时候初始化了一个字符串列表(string list),然后通过列表的FindAll方法来查找以“sunny”起始的字符串,最后将所查找到的所有结果输出。
我们需要着重介绍List<T>的FindAll方法。这个方法是一个参数为Predicate<T>类型、返回值为List<T>类型的函数。注意,Predicate<T>是一个泛型委托,它指代这样一些函数:这些函数仅有一个T类型的参数,并且返回值是布尔类型。通过reflector等工具,我们可以看到Predicate<T>的定义如下:
public delegate bool Predicate<T>(T obj);
至此我们也多少能够猜到FindAll方法的具体实现。即针对List<T>中的每个元素,调用Predicate<T>所指代的函数,如果函数返回为true,则将其加入新建的列表中。遍历完所有的元素后,将新建的列表返回给调用者。如下:
public List<T> FindAll<T>(Predicate<T> match)
{
List<T> ret = new List<T>();
foreach (T elem in items)
{
if (match(elem))
ret.Add(elem);
}
return ret;
}
因此,针对上面的例子,要调用FindAll方法,我们必须先定义一个参数为string类型,返回值为布尔类型的函数,在这个函数中,对参数进行条件判断,如果符合条件(也就是以“sunny”作为起始字符串),那么就返回true,否则返回false。最后再将这个函数作为参数传递给FindAll。于是也就得到了最上面的代码。
在上面的例子中,为了调用FindAll方法,我们不得不新定义一个函数,其实这个函数除了FindAll方法要用外,别的地方都几乎很少使用到它,你还不得不给它起个名字。如果程序中有多处需要调用FindAll方法,或者类似的情况,那么整个程序也就会出现一大批“只有一个地方使用”的函数,使得代码难于阅读和维护。
由于存在这样的问题,C# 2.0引入了匿名方法。开发人员在实现方法的时候,只需要给出方法的参数列表(甚至也可以不给)以及方法具体实现,而不需要关心方法的返回值,更不必给方法起名字。最关键的是,只在需要的地方定义匿名方法,保证了代码的简洁。
匿名方法只在需要的地方定义,定义的时候,使用delegate关键字,后接参数列表,然后跟上用一对花括号包括起来的函数体即可。上面的代码可以重构成下面的形式:
class Program
{
static void Main(string[] args)
{
List<string> names = new List<string>();
names.Add("Sunny Chen");
names.Add("Kitty Wang");
names.Add("Sunny Crystal"); List<string> found = names.FindAll(
delegate(string name)
{
return name.StartsWith("sunny", StringComparison.OrdinalIgnoreCase);
}); if (found != null)
{
foreach (string str in found)
Console.WriteLine(str);
}
} //static bool NameMatches(string name)
//{
// return name.StartsWith("sunny",
// StringComparison.OrdinalIgnoreCase);
//}
}
此时,我们完全不需要NameMatches方法了,直接将匿名方法作为参数传递给FindAll方法。其实匿名方法本身还是有名字的,只是我们并不关心它究竟该取什么名字,因而.NET帮我们随便取了个名字罢了。
匿名方法在C#中应用十分广泛,因为委托作为函数参数是件非常平常的事情。在定义简单的事件处理过程时,我们同样可以使用匿名方法。比如:
ServiceHost host = new ServiceHost(typeof(FileTransferImpl));
host.Opened += delegate(object sender, EventArgs e)
{
Console.WriteLine("Service Opened.");
};
匿名方法可以很方便地使用本地变量,这与单独定义的命名方法相比,能够简化编程。比如上文的例子中,假如Main函数里面定义了一个整型本地变量(局部变量)number,那么可以在delegate (string name)这一匿名方法定义中使用number变量。
上文提到,在定义匿名方法的时候,连参数列表都可以省略。因为编译器可以根据委托的签名来确定函数的签名,然后只要再给函数起个名字就可以了。下面的代码演示了这种使用方式:
delegate void IntDelegate(int x); // 带参数的定义方式
IntDelegate d2 = delegate(int p) { Console.WriteLine(p); };
// 不带参数的定义方式(当然也没带返回值)
IntDelegate d3 = delegate { Console.WriteLine("Hello."); };
在使用不带参数和返回值的匿名方法定义时,需要注意以下两点:
1.如果在你的匿名方法中需要对参数进行处理,那么你不能使用不定义参数列表的声明方式。也就是在定义匿名方法的时候,需要给出参数列表。
2.不带参数和返回值的匿名方法,可以被具有任何形式签名的委托所指代。
上述第一点显而易见,因为你没有定义参数列表,也就没有办法使用参数;要说明第二点,我们可以看下面的代码:
class Program
{
delegate void IntDelegate(int x);
delegate void StringDelegate(string y); static void Output(IntDelegate id)
{
} static void Output(StringDelegate sd)
{
} static void Main(string[] args)
{
/*
* ERROR: The call is ambiguous between
* Output(IntDelegate)
* and
* Output(StringDelegate)
*/
Output(delegate { });
}
}
上面的代码没法编译通过,因为编译器不知道应该将delegate { }这一匿名方法还原为由IntDelegate指代的函数,还是还原为由StringDelegate指代的函数。此时只能显式给定参数列表,以便让编译器知道,我们究竟是想调用哪个Output函数。
希望本文所述对大家的C#程序设计有所帮助
C#基础之匿名方法实例教程的更多相关文章
- [C#] C# 基础回顾 - 匿名方法
C# 基础回顾 - 匿名方法 目录 简介 匿名方法的参数使用范围 委托示例 简介 在 C# 2.0 之前的版本中,我们创建委托的唯一形式 -- 命名方法. 而 C# 2.0 -- 引进了匿名方法,在 ...
- C#基础知识---匿名方法使用
一.匿名方法使用 1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Tex ...
- js获取IP地址多种方法实例教程
js获取IP地址方法总结 js代码获取IP地址的方法,如何在js中取得客户端的IP地址.原文地址:js获取IP地址的三种方法 http://www.jbxue.com/article/11338. ...
- ICONIX方法(用例分析方法实例教程)
- C# 知识回顾 - 匿名方法
C# 基础回顾 - 匿名方法 目录 简介 匿名方法的参数使用范围 委托示例 简介 在 C# 2.0 之前的版本中,我们创建委托的唯一形式 -- 命名方法. 而 C# 2.0 -- 引进了匿名方法,在 ...
- Silverlight实例教程 - Validation数据验证基础属性和事件(转载)
Silverlight 4 Validation验证实例系列 Silverlight实例教程 - Validation数据验证开篇 Silverlight实例教程 - Validation数据验证基础 ...
- 30天C#基础巩固-----值类型/引用类型,泛型,空合并操作符(??),匿名方法
一:值类型/引用类型的区别 值类型主要包括简单类型,枚举类型,和结构体类型等,值类型的实例通常被分配在线程堆栈上面变量保存的内容是实例数据本身.引用类型被分配在托管堆上,变量保存的是地址.引 ...
- AutoCAD ObjectARX(VC)开发基础与实例教程2014版光盘镜像
AutoCAD ObjectARX(VC)开发基础与实例教程2014,最新版,光盘镜像 作者:张帆 朱文俊 编著 出版社:中国电力出版社 出版时间:2014年6月 点击一下
- C#基础精华07(委托事件,委托的使用,匿名方法)
1.委托概述 委托是一种数据类型,像类一样(可以声明委托类型变量).方法参数可以是int.string.类类型 void M1(int n){ } √ void M2(string s){ } √ ...
随机推荐
- MVC 实现表格数据导出Excel(NPOI方式)
前端View(@ViewBag为查询条件): <span id="exprobtn" class="btn_blue" style="dispa ...
- hMailServer 附件大小限制
修改php.ini文件 1.post_max_size = 10M 表单提交最大数据为10M.此项不是限制上传单个文件的大小,而是针对整个表单的提交数据进行限制的. 2.file_uploads = ...
- 设计模式中类的关系之组合关系(Composition)
组合也是关联关系的一种特例,它体现的是一种contains-a的关系,这种关系比聚合更强,也称为强聚合:它同样体现整体与部分间的关系,但此时整体与部分是不可分的,它们具有统一的生存期,整体的生命周期结 ...
- IOS设计模式浅析之适配器模式(Adapter)
引言 在项目开发中,有时候会遇到这样的一种情景:需要使用以前开发的“一些现存的对象”,但是新环境中要求的接口是这些现存对象所不满足的.怎样应对这种迁移的需求?使得可以复用这些对象,以满足新的应用环境, ...
- Appium python自动化测试系列之元素的定位(六)
6.1 常用定位方法讲解 对象定位是自动化测试中很关键的一步,也可以说是最关键的一步,毕竟你对象都没定位那么你想操作也不行.所以本章节的知识我希望大家多动手去操作,不要仅仅只是书本上的知识,毕竟这个 ...
- 十年WEB技术发展历程
一个小分享,知识有限,抛砖引玉. ajax 03年的时候我上六年级,那时候网吧刚在小县城的角落萌生.传奇,大话西游第一代网游一时风靡.我抱着试一试的心态给了网吧老板两块钱想申请个号玩玩,然后接下来的一 ...
- Spring学习笔记及资源
极客学院团队出品 Spring 教程 http://wiki.jikexueyuan.com/project/spring/ Spring 提供了以下两种不同类型的容器. 序号 容器 & 描 ...
- Python中的多进程与多线程/分布式该如何使用
在批评Python的讨论中,常常说起Python多线程是多么的难用.还有人对 global interpreter lock(也被亲切的称为“GIL”)指指点点,说它阻碍了Python的多线程程序同时 ...
- Map的两张遍历方法 keySet(),entrySet()
源博客 http://blog.csdn.net/liu826710/article/details/9001254 在Map集合中 values():方法是获取集合中的所有的值----没有键,没有对 ...
- java8 关于日期的处理
Java8 为我们提供了一种新的日期格式:LocalDate和LocalDateTime 获取当前的时间及前一天时间的方法: import java.time.LocalDateTime; impor ...