c#题例-2025-07-30 00:25:30
日期: 2025-07-30 分类: AI写作 12次阅读
当然可以!下面是一道**专家级别**的 C# 程序员逻辑面试题,涉及 **闭包、委托、异步编程和变量捕获机制**,非常考验对 C# 语言特性和底层机制的理解:
---
### 🧠 面试题:闭包与循环变量捕获陷阱(Expert Level)
**题目:**
请分析以下 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. **闭包与变量捕获机制**(Closure and variable capture)
2. **循环变量的作用域与引用捕获问题**
3. **如何修复循环变量捕获陷阱**
4. **对委托和延迟执行的理解**
---
### 📌 正确答案概要:
#### 输出结果:
```
5
5
5
5
5
```
#### 原因分析:
- `i` 是在 `for` 循环中声明的变量,使用 `var`(注意不是 `int`)。
- 在 C# 中,`for` 循环变量 `i` 的作用域是整个 `Main()` 方法(C# 5+)。
- 所有 `Action` 委托都**引用了同一个变量 `i`**,而不是捕获其当前值。
- 当循环结束后,`i` 的值为 `5`,此时调用所有 `Action` 都会打印 `5`。
#### 修复方法:
将循环变量的当前值**复制到局部变量中**,让每次迭代捕获不同的变量:
```csharp
for (var i = 0; i < 5; i++)
{
int temp = i;
actions.Add(() => Console.WriteLine(temp));
}
```
这样,每次迭代都会创建一个新的 `temp` 变量,闭包捕获的是该变量的副本,输出结果将为:
```
0
1
2
3
4
```
---
### 💡 深度拓展(专家追问):
1. 如果使用 `int i = 0; for (; i < 5; i++)`,结果会怎样?为什么?
2. 如果使用 `foreach` 循环代替 `for`,行为会有什么不同?
3. 在异步场景中(如使用 `Task.Run`),同样的问题是否仍然存在?如何处理?
4. 使用 `ValueTask` 或 `async/await` 是否会影响闭包捕获行为?
---
如果你能完整解释上述问题,并给出不同场景下的解决方案,说明你对 C# 的闭包机制、委托、变量生命周期和异步编程都有深入理解。
需要更多类似题目吗?我可以继续出。
除特别声明,本站所有文章均为原创,如需转载请以超级链接形式注明出处:SmartCat's Blog
标签:AI写作
精华推荐