Young87

SmartCat's Blog

So happy to code my life!

游戏开发交流QQ群号60398951

当前位置:首页 >AI写作

c#题例-2025-06-29 13:52:27

当然可以!下面是一道**专家级别**的 C# 程序员逻辑面试题,涉及到 **闭包、异步编程、捕获变量、线程安全和TPL(任务并行库)** 的综合理解:

---

### 🧠 面试题:深入理解异步闭包与变量捕获

#### 💬 题目描述:

你被要求分析以下 C# 代码,并回答两个问题:

```csharp
using System;
using System.Threading.Tasks;

class Program
{
static async Task Main()
{
var tasks = new Task[10];

for (var i = 0; i < 10; i++)
{
tasks[i] = Task.Run(async () =>
{
await Task.Delay(100); // 模拟异步工作
Console.WriteLine(i);
});
}

await Task.WhenAll(tasks);
}
}
```

---

### ❓问题一:
这段代码的输出会是什么?为什么?

---

### ❓问题二:
如何修改这段代码,使其按预期顺序输出从 `0` 到 `9`?

---

### 🎯 参考答案要点:

#### ✅ 问题一解答:

输出可能是:
```
多个相同的值,比如全部是10 或者 不同但不连续的数字
```

**原因:**

- 这是因为在 `for` 循环中使用了循环变量 `i`,它被多个任务所捕获。
- 在 C# 5.0 及以后版本中,`for` 循环变量 `i` 是“循环体内部声明”的,因此在每次迭代中共享同一个变量。
- 所有闭包捕获的是同一个变量 `i`,而不是它的值副本。
- 当异步操作执行时,`i` 的值可能已经递增到 `10`,导致所有任务打印出的都是 `10`。

> ⚠️ 注意:如果你用的是 `foreach` 或者旧版本 C#(C# 5 之前),行为可能会不同。

---

#### ✅ 问题二解答:

要修复这个问题,需要确保每个任务都捕获一个**独立的变量副本**。可以通过在循环体内引入一个新的局部变量来实现:

```csharp
for (var i = 0; i < 10; i++)
{
int loopCopy = i; // 引入局部变量进行捕获
tasks[i] = Task.Run(async () =>
{
await Task.Delay(100);
Console.WriteLine(loopCopy);
});
}
```

这样,每次迭代都会创建一个新的 `loopCopy` 变量,闭包捕获的是这个新变量,保证了值的正确性。

---

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

- 如果不用 `Task.Run`,而是直接使用 `async/await` 创建任务,会发生什么?
- 如果将 `Console.WriteLine(i)` 改为调用某个同步方法,是否还存在变量捕获的问题?
- 如何在线程安全环境中处理类似问题?可以考虑使用 `ConcurrentBag` 或锁机制吗?

---

这道题能很好地考察候选人对 **异步编程模型、闭包、变量捕获机制、TPL 和线程调度** 的理解深度,非常适合用于高级或专家级 C# 开发者的面试。需要我再出一道类似的题目吗?

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

上一篇: c#题例-2025-06-29 19:25:43

下一篇: c#题例-2025-06-29 08:19:17

精华推荐