C匿名函数:特性、用法与性能考量
立即解锁
发布时间: 2025-09-15 00:31:58 订阅数: 1 AIGC 

### C# 匿名函数:特性、用法与性能考量
#### 1. 匿名函数概述
在 C# 中,匿名函数是一种强大的特性,它允许开发者在不明确定义单独方法的情况下创建委托。可以将其看作是一种值为方法的特殊表达式,官方名称为匿名函数。从 C# 语言的角度来看,这些方法没有名称,尽管运行时要求所有方法都有名称,C# 会为其生成隐藏名称。
对于简单方法,以表达式形式内联编写可以减少代码冗余。并且,编译器利用委托不仅是方法引用这一特性,使匿名函数能够访问其所在方法作用域内的变量。
#### 2. 匿名函数的定义方式
C# 提供了两种定义匿名函数的方式:
##### 2.1 匿名方法(旧方式)
使用 `delegate` 关键字,示例代码如下:
```csharp
public static int GetIndexOfFirstNonEmptyBin(int[] bins)
{
return Array.FindIndex(
bins,
delegate (int value) { return value > 0; }
);
}
```
这种方式在某些方面类似于普通方法的定义语法,参数列表放在括号中,后面跟着包含方法体的代码块。但不同的是,这里使用 `delegate` 关键字代替了方法名,编译器会推断返回类型。
##### 2.2 Lambda 表达式(新方式)
示例代码如下:
```csharp
public static int GetIndexOfFirstNonEmptyBin(int[] bins)
{
return Array.FindIndex(
bins,
value => value > 0
);
}
```
Lambda 表达式以数学中的 Lambda 演算命名,`=>` 符号明确标识这是一个 Lambda 表达式。编译器根据上下文知道方法参数的类型,因此无需显式指定。对于只包含单个表达式的简单方法,Lambda 语法可以省略代码块和 `return` 语句。
Lambda 表达式有多种变体,示例如下:
```csharp
Predicate<int> p1 = value => value > 0;
Predicate<int> p2 = (value) => value > 0;
Predicate<int> p3 = (int value) => value > 0;
Predicate<int> p4 = value => { return value > 0; };
Predicate<int> p5 = (value) => { return value > 0; };
Predicate<int> p6 = (int value) => { return value > 0; };
Predicate<int> p7 = bool (value) => value > 0;
Predicate<int> p8 = bool (int value) => value > 0;
Predicate<int> p9 = bool (value) => { return value > 0; };
Predicate<int> pA = bool (int value) => { return value > 0; };
```
- 可以在参数周围添加括号,单个参数时可选,多参数时必需。
- 可以显式指定参数类型,此时即使只有一个参数也需要括号。
- 如果使用代码块,返回值时需要使用 `return` 关键字。
- C# 10.0 允许显式指定返回类型,但仅在参数列表有括号时可用。
Lambda 表达式还可以定义无参数的情况,示例如下:
```csharp
Func<bool> isAfternoon = () => DateTime.Now.Hour >= 12;
```
#### 3. 两种方式的对比
Lambda 表达式的灵活紧凑语法使其几乎取代了旧的匿名方法语法,但匿名方法有一个优势,即可以完全省略参数列表。例如:
```csharp
EventHandler clickHandler = delegate { Debug.WriteLine("Clicked!"); };
```
在某些回调场景中,可能只需要知道事件已发生,不需要使用参数,匿名方法可以方便地忽略这些参数。而 Lambda 表达式不能省略参数列表,但 C# 10.0 引入了丢弃参数的语法:
```csharp
EventHandler clickHandler = (_, _) => Debug.WriteLine("Clicked!");
```
#### 4. 捕获变量
匿名函数的一个重要特性是能够捕获其所在方法的变量。示例如下:
```csharp
public static Predicate<int> IsGreaterThan(int threshold)
{
return value => value > threshold;
}
```
在这个例子中,`threshold` 是 `IsGreaterThan` 方法的参数,当调用 `IsGreaterThan` 方法返回委托后,即使 `IsGreaterThan` 方法已经返回,`threshold` 变量仍然可用。这是因为编译器会生成一个类来保存这些变量,使其生命周期超出创建它们的方法。
生成的代码示例如下:
```csharp
[CompilerGenerated]
private sealed class <>c__DisplayClass0_0
{
public int threshold;
public bool <IsGreaterThan>b__0(int value)
{
return (value > this.threshold);
}
}
```
捕获变量不仅可以读取,还可以修改。示例如下:
```csharp
static v
```
0
0
复制全文
相关推荐









