在 2.0 之前的 C# 版本中,声明委托的唯一方式是使用命名方法。 C# 2.0 引入匿名方法,在 C# 3.0 及更高版本中,Lambda 表达式取代匿名方法作为编写内联代码的首选方式。 但是,本主题中有关匿名方法的信息也适用于 Lambda 表达式。 在有一种情况下,匿名方法提供 Lambda 表达式中没有的功能。 使用匿名方法可省略参数列表。 这意味着匿名方法可转换为具有多种签名的委托。 Lambda 表达式无法实现这一点。 有关 Lambda 表达式的详细信息,请参阅 Lambda 表达式

创建匿名方法实际上是一种将代码块作为委托参数传递的方式。 这里是两个示例:

// 为单击事件创建处理程序
button1.Click += delegate(System.Object o, System.EventArgs e)
{ System.Windows.Forms.MessageBox.Show("Click!"); };
// 创建一个委托.
delegate void Del(int x); // 使用匿名方法实例化委托
Del d = delegate(int k) { /* ... */ };

由于使用匿名方法无需创建单独的方法,因此可减少对委托进行实例化的编码开销。

例如,在因不得不创建方法而可能出现非必要开销的情况下,指定代码块(而不是委托)很有用处。 开始新线程就是一个很好的示例。 此类创建一个线程,且还包含该线程执行的代码,而无需为委托创建其他方法。

void StartThread()
{
System.Threading.Thread t1 = new System.Threading.Thread
(delegate()
{
System.Console.Write("Hello, ");
System.Console.WriteLine("World!");
});
t1.Start();
}

备注

匿名方法的参数范围为匿名方法块。

如果目标在匿名方法块之外,匿名方法块内具有 gotobreakcontinue 等跳转语句是一种错误。 如果目标在匿名方法块之内,匿名方法块外具有 gotobreakcontinue 等跳转语句也是一种错误。

范围包含匿名方法声明的本地变量和参数称为此匿名方法的外部变量。 例如,在如下代码段中,n 是一个外部变量:

int n = ;
Del d = delegate() { System.Console.WriteLine("Copy #:{0}", ++n); };

创建委托时,对外部变量 n 的引用被视为已捕获。 不同于本地变量,已捕获的变量的生存期一直延伸至引用匿名方法的委托具有垃圾回收资格为止。

匿名方法无法访问外部范围的 inrefout 参数。

无法在匿名方法块内访问任何不安全代码。

不允许在 is 运算符左侧使用匿名方法。

示例

如下示例演示实例化委托的两种方式:

  • 将委托与匿名方法相关联。

  • 将委托与命名方法 (DoWork) 相关联。

在每一种情况下,调用委托时均显示一条消息。

// 定义委托.
delegate void Printer(string s); class TestClass
{
static void Main()
{
// 使用匿名方法实例化委托类型
Printer p = delegate(string j)
{
System.Console.WriteLine(j);
}; // 匿名委托调用的结果
p("The delegate using the anonymous method is called."); // 使用命名方法“DoWork”的委托实例化
p = DoWork; // 传统方式委托调用的结果
p("The delegate using the named method is called.");
} // 与命名委托关联的方法。
static void DoWork(string k)
{
System.Console.WriteLine(k);
}
}
/* 输出:
The delegate using the anonymous method is called.
The delegate using the named method is called.
*/

其他更详细的技术请参考:

C#2.0新增功能03 匿名方法的更多相关文章

  1. C#3.0新增功能03 隐式类型本地变量

    连载目录    [已更新最新开发文章,点击查看详细] 从 Visual C# 3.0 开始,在方法范围内声明的变量可以具有隐式“类型”var. 隐式类型本地变量为强类型,就像用户已经自行声明该类型,但 ...

  2. C#3.0新增功能02 匿名类型

    连载目录    [已更新最新开发文章,点击查看详细] 匿名类型提供了一种方便的方法,可用来将一组只读属性封装到单个对象中,而无需首先显式定义一个类型. 类型名由编译器生成,并且不能在源代码级使用. 每 ...

  3. C#3.0新增功能04 扩展方法

    连载目录    [已更新最新开发文章,点击查看详细] 扩展方法使你能够向现有类型“添加”方法,而无需创建新的派生类型.重新编译或以其他方式修改原始类型. 扩展方法是一种特殊的静态方法,但可以像扩展类型 ...

  4. C#4.0新增功能03 泛型中的协变和逆变

    连载目录    [已更新最新开发文章,点击查看详细] 协变和逆变都是术语,前者指能够使用比原始指定的派生类型的派生程度更大(更具体的)的类型,后者指能够使用比原始指定的派生类型的派生程度更小(不太具体 ...

  5. C#3.0新增功能05 分部方法

    连载目录    [已更新最新开发文章,点击查看详细]    分部类或结构可以包含分部方法. 类的一个部分包含方法的签名. 可以在同一部分或另一个部分中定义可选实现. 如果未提供该实现,则会在编译时删除 ...

  6. C#2.0新增功能06 协变和逆变

    连载目录    [已更新最新开发文章,点击查看详细] 在 C# 中,协变和逆变能够实现数组类型.委托类型和泛型类型参数的隐式引用转换. 协变保留分配兼容性,逆变则与之相反. 以下代码演示分配兼容性.协 ...

  7. C#2.0新增功能01 分布类与分部方法

    连载目录    [已更新最新开发文章,点击查看详细] 分部类型 拆分一个类.一个结构.一个接口或一个方法的定义到两个或更多的文件中, 每个源文件包含类型或方法定义的一部分,编译应用程序时将把所有部分组 ...

  8. C#基础拾遗系列之二:使用ILSpy探索C#7.0新增功能点

    C#基础拾遗系列之二:使用ILSpy探索C#7.0新增功能点   第一部分: C#是一种通用的,类型安全的,面向对象的编程语言.有如下特点: (1)面向对象:c# 是面向对象的范例的一个丰富实现, 它 ...

  9. C#3.0新增功能09 LINQ 基础07 LINQ 中的查询语法和方法语法

    连载目录    [已更新最新开发文章,点击查看详细] 介绍性的语言集成查询 (LINQ) 文档中的大多数查询是使用 LINQ 声明性查询语法编写的.但是在编译代码时,查询语法必须转换为针对 .NET ...

随机推荐

  1. Qt:移动无边框窗体(使用Windows的SendMessage)

    移动无边框窗体的代码网上很多,其原理都是一样的,但是是有问题的,我这里只是对其修正一下 网上的代码仅仅实现了两个事件 void EditDialog::mousePressEvent(QMouseEv ...

  2. C语言宏定义##连接符和#符的使用(MFC就是靠##自动把消息和消息函数对应起来了,借助宏来减少switch case代码的编写量)

    C语言中如何使用宏C(和C++)中的宏(Macro)属于编译器预处理的范畴,属于编译期概念(而非运行期概念).下面对常遇到的宏的使用问题做了简单总结. 关于#和## 在C语言的宏中,#的功能是将其后面 ...

  3. 程序跳过UAC研究及实现思路(两种方法,现在可能都不行了)

    网上很对跳过UAC资料都是说如果让UAC弹出窗体,并没有真正跳过弹窗,这里结合动态提权+计划任务实现真正意义上的跳过UAC弹窗,运行程序的时候可以不出现UAC窗体,并且程序还是以高权限运行. vist ...

  4. 为什么说 2017 年你必须要学习 Go 了(多核,网络,多人协作,简单非OO,没有注解,Native,垃圾收集,代码优雅),附两个评论

    为什么要学习Go Go是未来的服务端语言— Tobias Lütke, Shopify.在过去的几年中,Golang逐步流行起来. 还有什么能比一门新语言让码农们疯狂呢? 因此,我开始学习了一段时间G ...

  5. Codility---PermCheck

    Task description A non-empty zero-indexed array A consisting of N integers is given. A permutation i ...

  6. 【图文】[新手]C++ 动态库导出函数名“乱码”及解决

    刚接触C++,在尝试从 dll 中导出函数时,发现导出的函数名都"乱码"了. 导出过程如下: 新建一个Win32项目: 新建的解决方案里有几个导出的示例: // 下列 ifdef ...

  7. 深度强化学习day01初探强化学习

    深度强化学习 基本概念 强化学习 强化学习(Reinforcement Learning)是机器学习的一个重要的分支,主要用来解决连续决策的问题.强化学习可以在复杂的.不确定的环境中学习如何实现我们设 ...

  8. Oracle数据库视图的创建以及使用

    创建视图语句: CREATE [OR REPLACE] [FORCE|NOFORCE] VIEW view_name [(alias[, alias]...)] AS subquery [WITH C ...

  9. spring boot 2.x 系列 —— spring boot 整合 kafka

    文章目录 一.kafka的相关概念: 1.主题和分区 2.分区复制 3. 生产者 4. 消费者 5.broker和集群 二.项目说明 1.1 项目结构说明 1.2 主要依赖 二. 整合 kafka 2 ...

  10. Maven版本管理-Maven Release Plugin插件

    一.什么是版本管理 首先,这里说的版本管理(version management)不是指版本控制(version control),但是本文假设你拥有基本的版本控制的知识,了解subversion的基 ...