c#题例-2025-07-16 22:58:27
日期: 2025-07-16 分类: AI写作 18次阅读
当然可以!下面是一道**专家级别**的 C# 程序员逻辑面试题,涉及 **委托、泛型、异步编程、闭包、线程安全** 等多个高级知识点:
---
### 🧠 面试题:异步委托链与状态捕获陷阱
#### 题目描述:
请分析以下 C# 代码,指出其输出结果,并解释为什么。同时,提出一种**线程安全**的修复方案,使其输出符合预期。
```csharp
using System;
using System.Threading.Tasks;
class Program
{
static void Main()
{
var actions = new Action[5];
for (int i = 0; i < 5; i++)
{
Task.Delay(100).ContinueWith(_ =>
{
actions[i] = () => Console.WriteLine(i);
});
}
Task.Delay(1000).ContinueWith(_ =>
{
for (int j = 0; j < 5; j++)
{
actions[j]?.Invoke();
}
});
Console.ReadLine();
}
}
```
---
### ✅ 考察点解析:
1. **闭包捕获陷阱(Closure Capturing)**
- `i` 是在 lambda 中被捕获的变量,而不是按值捕获。
- 因为异步执行,循环结束时 `i == 5`,所以所有 `actions[i]` 都打印 `5`。
2. **异步操作顺序问题**
- `ContinueWith` 是异步执行的,无法保证执行顺序。
- `i` 的值在异步回调执行时可能已经改变。
3. **线程安全问题**
- 多线程写入 `actions[i]`,没有同步机制,可能导致数据竞争。
4. **委托数组初始化的时序问题**
- 主线程继续执行,而 `actions` 可能尚未完全初始化。
---
### 🧪 预期输出(可能):
```
5
5
5
5
5
```
(也可能抛出异常或部分输出,取决于异步执行顺序)
---
### ✅ 正确修复方案(线程安全 + 闭包正确捕获):
```csharp
using System;
using System.Threading.Tasks;
class Program
{
static async Task Main()
{
var actions = new Action[5];
for (int i = 0; i < 5; i++)
{
int localCopy = i; // 捕获副本
await Task.Delay(100); // 更可控的异步等待
await Task.Run(() =>
{
actions[localCopy] = () => Console.WriteLine(localCopy);
});
}
await Task.Delay(1000); // 确保初始化完成
for (int j = 0; j < 5; j++)
{
actions[j]?.Invoke();
}
Console.ReadLine();
}
}
```
---
### 📌 总结考察维度:
| 技术点 | 是否考察 |
|----------------------|----------|
| 闭包与变量捕获 | ✅ |
| 异步编程模型 | ✅ |
| 线程安全与同步 | ✅ |
| 委托与数组操作 | ✅ |
| 异步执行顺序控制 | ✅ |
| `async/await` 使用 | ✅ |
| 代码健壮性设计 | ✅ |
---
如果你需要更多类似级别的题目(比如涉及表达式树、反射、内存模型、TPL、TPL Dataflow、RyuJIT优化等),我也可以继续提供。
除特别声明,本站所有文章均为原创,如需转载请以超级链接形式注明出处:SmartCat's Blog
标签:AI写作
精华推荐