c#题例-2025-06-26 04:25:06
日期: 2025-06-26 分类: AI写作 8次阅读
当然可以!以下是一道**专家级别**的 C# 程序员逻辑面试题,涉及 **闭包、委托、异步编程和变量捕获机制**,非常考验对语言底层机制的理解:
---
### 🧠 面试题:闭包陷阱与异步执行
**题目:**
请分析以下 C# 代码,并回答输出结果是什么?并解释为什么。
```csharp
using System;
using System.Threading.Tasks;
class Program
{
static void Main(string[] args)
{
var tasks = new Task[5];
for (int i = 0; i < 5; i++)
{
tasks[i] = Task.Run(async () =>
{
await Task.Delay(100); // 模拟异步操作
Console.WriteLine(i);
});
}
Task.WaitAll(tasks);
Console.WriteLine("Done");
}
}
```
---
### ❓问题延伸(追问):
1. 输出顺序是怎样的?为什么?
2. 如何修改代码以确保每个任务打印的是它被创建时的 `i` 值?
3. 如果将 `Task.Run` 替换为同步调用,比如直接使用 `new Thread()` 或者 `Parallel.For`,行为会有什么不同?
---
### ✅ 参考答案概要:
#### 1. 输出可能是:
```
5
5
5
5
5
Done
```
> 不是按顺序输出 0~4。这是因为循环中的变量 `i` 是在闭包中被捕获的,所有任务共享同一个 `i` 变量。当异步操作真正开始执行时,循环已经完成,`i` 的值已经是 5。
#### 2. 修改方式:
将当前的 `i` 值复制到局部变量中,以避免闭包共享问题:
```csharp
for (int i = 0; i < 5; i++)
{
int localI = i;
tasks[i] = Task.Run(async () =>
{
await Task.Delay(100);
Console.WriteLine(localI);
});
}
```
这样就能正确输出 0~4。
#### 3. 追问解析:
- 如果使用 `Parallel.For`,默认情况下也会有类似闭包的问题。
- 如果使用线程池或新线程,仍需注意变量捕获机制。
- 强调对闭包、变量生命周期、以及异步上下文切换的理解。
---
### 💡 考察点总结:
- 对 **C# 闭包捕获机制** 的理解;
- 对 **异步编程模型(TPL)** 的掌握;
- 是否了解 **变量作用域和延迟执行** 的关系;
- 编写线程安全、预期行为代码的能力;
- 对常见并发陷阱的识别与规避经验。
---
如果你想要更多这类题目(如 LINQ 表达式树、泛型约束、反射 emit、内存泄漏排查等),我也可以继续出题!
除特别声明,本站所有文章均为原创,如需转载请以超级链接形式注明出处:SmartCat's Blog
标签:AI写作
精华推荐