c#题例-2025-07-17 04:31:59
日期: 2025-07-17 分类: AI写作 13次阅读
当然可以!下面是一道**专家级别**的 C# 程序员逻辑面试题,涉及到 **委托、泛型、闭包、线程安全和延迟执行**等多个高级概念:
---
### 🧠 面试题:理解委托链与闭包捕获
#### 问题描述:
请看以下代码片段:
```csharp
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
class Program
{
static void Main()
{
var actions = new List
for (int i = 0; i < 5; i++)
{
Task.Delay(10).Wait(); // 模拟异步操作,不影响逻辑
int captured = i;
actions.Add(() =>
{
Console.WriteLine($"i: {i}, captured: {captured}");
});
}
Parallel.Invoke(actions.ToArray());
}
}
```
#### 问题如下:
1. **输出结果是什么?为什么?**
2. 如果将 `int captured = i;` 改为 `var captured = i;` 是否会影响结果?为什么?
3. 如何修改该代码以确保每个 `Action` 输出的是循环当时的 `i` 值(即 0 到 4)?
4. 如果使用 `Task.Run` 替代 `Parallel.Invoke`,会出现什么潜在问题?如何解决?
---
### 💡 考察点解析:
| 考察点 | 解析 |
|--------|------|
| 闭包捕获 | 使用 lambda 表达式时对外部变量的捕获机制 |
| 变量捕获陷阱 | 在循环中直接捕获循环变量 `i` 会导致所有委托看到的是最终值 |
| 值类型 vs 引用类型 | 捕获 `int` 是值类型,但闭包会提升为类字段,导致共享状态 |
| 并行执行 | `Parallel.Invoke` 会并发执行委托,涉及线程调度和输出顺序不确定 |
| 泛型委托 | Action 的使用方式及其生命周期管理 |
---
### ✅ 参考答案简要:
1. **输出可能类似:**
```
i: 5, captured: 0
i: 5, captured: 1
i: 5, captured: 2
i: 5, captured: 3
i: 5, captured: 4
```
- 因为 `i` 是在闭包中被捕获的,而不是在每次迭代中复制。当委托执行时,`i` 已经变成 5。
- `captured` 是每次迭代定义的新变量,因此正确保存了当时的值。
2. **`var captured = i;` 不影响结果。**
因为 `var` 只是类型推断,底层仍是 `int captured = i;`。
3. **修复方法:**
```csharp
for (int i = 0; i < 5; i++)
{
int captured = i;
actions.Add(() => Console.WriteLine($"captured: {captured}"));
}
```
或者使用局部函数/创建新作用域。
4. **使用 `Task.Run` 的问题:**
- 多个任务并行执行时,`Console.WriteLine` 是线程安全的,但输出可能会交错。
- 更严重的是,如果在 WinForm/WPF 中未捕获异常或未等待任务完成,可能导致程序提前退出。
---
如果你需要更偏向“设计模式”、“反射”或“性能优化”的专家级题目,也可以告诉我,我可以继续出一道 😄
除特别声明,本站所有文章均为原创,如需转载请以超级链接形式注明出处:SmartCat's Blog
标签:AI写作
上一篇:无
精华推荐