c#题例-2025-07-08 06:25:08
日期: 2025-07-08 分类: AI写作 16次阅读
当然可以!下面是一道**专家级别**的 C# 程序员逻辑面试题,涉及 **闭包、捕获变量、异步编程、委托和线程安全**等多个高级概念:
---
### 🧠 面试题:你真的理解闭包与循环变量吗?
#### 问题描述:
请看以下 C# 代码片段:
```csharp
using System;
using System.Threading.Tasks;
class Program
{
static void Main()
{
var actions = new Action[5];
for (var i = 0; i < 5; i++)
{
Task.Delay(10).ContinueWith(_ =>
{
Console.WriteLine(i);
});
}
Console.ReadLine();
}
}
```
#### 问题一:
这段代码输出的是什么?为什么?
#### 问题二(进阶):
如何修改上面的代码,使得每个 `ContinueWith` 输出的是它在循环中对应的索引值(即 0, 1, 2, 3, 4)?
#### 问题三(扩展):
如果将 `for` 循环改为 `Parallel.For`,会出现什么问题?如何确保线程安全并依然输出正确的索引值?
---
### ✅ 考察点解析:
- **闭包与变量捕获机制(Closure & Variable Capturing)**
- **异步编程模型中的上下文捕获**
- **循环变量生命周期的理解(C# 5.0 后的 for 循环行为变化)**
- **多线程/并行编程中的线程安全与变量共享问题**
---
### 💡 参考答案概要:
#### 回答一:
输出的可能是全部为 `5`(或不确定的值),因为 `i` 是被捕获的循环变量,在异步回调执行时,`i` 已经完成自增到 5。这是经典的“闭包捕获循环变量”陷阱。
#### 回答二:
应该在循环内部创建一个副本变量:
```csharp
for (var i = 0; i < 5; i++)
{
int copy = i;
Task.Delay(10).ContinueWith(_ =>
{
Console.WriteLine(copy);
});
}
```
或者使用 lambda 参数传入:
```csharp
Task.Delay(10).ContinueWith(_ => Console.WriteLine(i));
```
但注意:`ContinueWith` 中的 `_ => Console.WriteLine(i)` 仍会捕获 `i`,所以副本是必须的。
#### 回答三:
在 `Parallel.For` 中,多个线程并发执行,循环变量 `i` 的访问会存在竞争条件。应使用局部循环变量或将变量复制到每个线程的本地存储中,例如:
```csharp
Parallel.For(0, 5, i =>
{
int copy = i;
Task.Delay(10).ContinueWith(_ => Console.WriteLine(copy));
});
```
---
如果你能完整解释清楚这些问题,并写出线程安全且语义清晰的解决方案,说明你已经具备非常扎实的 C# 异步编程和语言机制理解能力!
需要我再出一道类似难度的题目吗?
除特别声明,本站所有文章均为原创,如需转载请以超级链接形式注明出处:SmartCat's Blog
标签:AI写作
精华推荐