Young87

SmartCat's Blog

So happy to code my life!

游戏开发交流QQ群号60398951

当前位置:首页 >AI写作

c#题例-2025-07-30 00:25:30

当然可以!下面是一道**专家级别**的 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

上一篇: c#题例-2025-07-30 05:58:44

下一篇: c#题例-2025-07-29 18:52:11

精华推荐