Young87

SmartCat's Blog

So happy to code my life!

游戏开发交流QQ群号60398951

当前位置:首页 >AI写作

c#题例-2025-07-01 18:18:24

当然可以!以下是一道**专家级别**的 C# 逻辑面试题,涉及 **闭包(Closure)、捕获变量、循环作用域和委托执行顺序** 等高级概念:

---

### 🧠 面试题:理解闭包与延迟执行

#### 💬 问题描述:

考虑以下 C# 代码片段:

```csharp
using System;
using System.Collections.Generic;

class Program
{
static void Main()
{
var actions = new List();

for (var i = 0; i < 5; i++)
{
actions.Add(() => Console.WriteLine(i));
}

foreach (var action in actions)
{
action();
}
}
}
```

#### ❓问题:

1. 上面的程序会输出什么?
2. 为什么是这样的结果?请解释背后的机制。
3. 如何修改代码,使其输出 `0, 1, 2, 3, 4`?

---

### ✅ 参考答案:

#### 1. 输出结果:
```
5
5
5
5
5
```

#### 2. 原因分析:

- C# 中的 **lambda 表达式捕获的是变量本身(variable capture),而不是变量的值**。
- 在 `for` 循环中,`i` 是在外部定义的。所有的 `Action` 捕获的是同一个变量 `i`。
- 当循环结束后,`i` 的值为 `5`,此时才调用所有的 `action()`,所以它们都打印出 `5`。

这是典型的 **闭包变量捕获陷阱(Closure Captures Loop Variable)**。

#### 3. 修改方式:

##### ✅ 方法一:在循环内部创建副本

```csharp
for (var i = 0; i < 5; i++)
{
int temp = i;
actions.Add(() => Console.WriteLine(temp));
}
```

因为每次循环都会创建一个新的 `temp` 变量,lambda 表达式捕获的是这个局部副本,从而保留了当前循环的值。

##### ✅ 方法二(适用于 C# 5 及以上):

使用 `foreach` 时,C# 5 起对循环变量进行了优化,每个迭代都会创建一个新变量:

```csharp
foreach (var j in Enumerable.Range(0, 5))
{
actions.Add(() => Console.WriteLine(j));
}
```

> ⚠️ 注意:这仅适用于 `foreach`,不是 `for`。

---

### 🧩 扩展思考(可选追问):

- 如果你把 lambda 替换成 `async/await` 或者放在线程池中执行,会发生什么?
- 如何避免闭包带来的性能或内存泄漏问题?
- 使用 `Expression` 替代 `Action` 会影响捕获行为吗?

---

这道题不仅考察候选人对闭包和变量生命周期的理解,还深入到了语言设计层面的知识,非常适合用于筛选中高级甚至专家级 C# 开发人员。需要结合 IL 分析和 CLR 行为来完整回答。

除特别声明,本站所有文章均为原创,如需转载请以超级链接形式注明出处:SmartCat's Blog

上一篇: c#题例-2025-07-01 23:51:47

下一篇: c#题例-2025-07-01 11:32:56

精华推荐