c#题例-2025-07-14 18:32:53
日期: 2025-07-14 分类: AI写作 6次阅读
当然可以!下面是一道**专家级别**的 C# 程序员逻辑面试题,涉及 **闭包、委托、异步编程和变量捕获机制**,这些都是考察候选人对 C# 深层理解的经典点:
---
### 🧠 面试题:闭包与异步任务中的变量捕获陷阱
**题目如下:**
请分析以下 C# 控制台程序的输出,并解释原因。然后提出一种修改方式以达到预期效果。
```csharp
using System;
using System.Threading.Tasks;
class Program
{
static async Task Main(string[] args)
{
for (var i = 0; i < 5; i++)
{
Task.Run(async () =>
{
await Task.Delay(100); // 模拟异步工作
Console.WriteLine(i);
});
}
await Task.Delay(1000); // 等待所有任务完成
}
}
```
---
### ✅ 考察点解析:
- **变量捕获(Variable Capturing)机制**
- **值类型 vs 引用类型的捕获差异**
- **异步 lambda 表达式中闭包的行为**
- **如何正确地在循环中捕获当前变量值**
---
### 📌 可能的输出:
由于 `i` 是在循环外部被捕获的,所有任务最终都会打印 **5**,因为循环执行完毕后 `i` 的值已经是 5。
输出可能是:
```
5
5
5
5
5
```
---
### ✍️ 解答建议:
#### 为什么是 5?
- `i` 使用的是 `var`(注意不是 `int`),但在 C# 中 `var i = 0` 会被推断为 `int`。
- 所有任务都引用了同一个变量 `i`,而这个变量在循环结束后已经变成了 5。
- 当任务真正执行时,它们读取的是此时的 `i` 值。
#### 如何修正?
在每次循环中创建一个副本:
```csharp
for (var i = 0; i < 5; i++)
{
int copy = i;
Task.Run(async () =>
{
await Task.Delay(100);
Console.WriteLine(copy);
});
}
```
这样每个闭包都捕获了不同的局部变量副本,输出就会变成:
```
0
1
2
3
4
```
---
### 🎯 扩展问题(进阶讨论):
- 如果将 `var` 改为 `int`,行为是否改变?为什么?
- 如果使用 `foreach` 替代 `for`,结果会不同吗?(C# 5.0 之后有变化)
- 在 .NET Core/.NET 5+ 下运行此代码,结果是否有不同?
- 如何使用 `async/await` 正确等待所有任务完成?
---
如果你需要更多类似级别的题目,比如涉及表达式树、反射 Emit、泛型约束、协变逆变、线程同步上下文等,请告诉我,我可以继续出题 😄
除特别声明,本站所有文章均为原创,如需转载请以超级链接形式注明出处:SmartCat's Blog
标签:AI写作
上一篇:无
精华推荐