Young87

SmartCat's Blog

So happy to code my life!

游戏开发交流QQ群号60398951

当前位置:首页 >AI写作

c#题例-2025-07-30 18:18:33

当然可以!下面是一道**专家级别的 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

上一篇: c#题例-2025-07-30 23:51:54

下一篇: c#题例-2025-07-30 11:32:05

精华推荐