c#题例-2025-07-30 18:18:33
日期: 2025-07-30 分类: AI写作 17次阅读
当然可以!下面是一道**专家级别的 C# 程序员逻辑面试题**,它结合了 C# 的高级语言特性、多线程、委托、闭包、内存模型、以及对 `async/await` 深层理解的要求:
---
### 🧠 面试题:深入理解 async/await 与闭包的执行顺序
#### 题目描述:
请仔细阅读以下 C# 控制台程序代码,并回答控制台输出的内容是什么?并解释其执行顺序和原因。
```csharp
using System;
using System.Threading.Tasks;
class Program
{
static async Task Main()
{
int x = 1;
var tasks = new Task[3];
for (var i = 0; i < 3; i++)
{
int loopCopy = i;
tasks[i] = Task.Run(async () =>
{
await Task.Delay(100).ConfigureAwait(false);
x += loopCopy;
Console.WriteLine($"x = {x}");
});
}
await Task.WhenAll(tasks);
Console.WriteLine($"Final x = {x}");
}
}
```
---
### 💡 考察点:
- 对 `async/await` 和线程池任务调度的理解
- 对闭包和变量捕获(尤其是循环变量)的理解
- 对 `Task.Run` 和异步委托执行顺序的理解
- 对 `ConfigureAwait(false)` 在异步上下文切换中的作用的理解
- 多线程环境下变量共享和同步问题
---
### ✅ 正确输出(示例):
```
x = 2
x = 3
x = 4
Final x = 4
```
> 实际顺序可能因线程调度不同略有不同,但最终 `x` 应为 `1 + 0 + 1 + 2 = 4`。
---
### 🧾 解析:
1. **变量捕获**:
- `loopCopy = i` 是为了避免经典的“闭包捕获循环变量”陷阱。每个任务都捕获了当前迭代的 `i` 值。
2. **异步执行顺序**:
- 所有三个任务都通过 `Task.Run` 被调度到线程池中异步执行。
- 每个任务等待 `100ms` 后执行 `x += loopCopy`。
- 因为没有同步机制,三个线程可能以任意顺序修改 `x`,但由于它们都操作不同的 `loopCopy` 值(分别是 0、1、2),最终结果是确定的。
3. **ConfigureAwait(false)**:
- 这里不影响输出顺序,但避免了回到主线程上下文,提高性能,适用于后台任务。
4. **最终输出**:
- `x` 初始为 1;
- 三个任务分别加 0、1、2;
- 所以最终 `x = 1 + 0 + 1 + 2 = 4`。
---
### 🧪 延伸问题(可选追问):
> 如果将 `int loopCopy = i;` 去掉,直接使用 `i`,输出会怎样?
- 答案:可能三个任务都输出 `x = 3`,因为 `i` 被共享并最终变为 3。
---
如果你希望我再出一道类似难度的题目(例如涉及表达式树、泛型约束、反射 emit、或 Roslyn 编译器 API 等),也可以告诉我方向!
除特别声明,本站所有文章均为原创,如需转载请以超级链接形式注明出处:SmartCat's Blog
标签:AI写作
精华推荐