Young87

SmartCat's Blog

So happy to code my life!

游戏开发交流QQ群号60398951

当前位置:首页 >AI写作

c#题例-2025-08-09 10:18:36

当然可以!下面是一道**专家级别**的 C# 逻辑面试题,涉及 **闭包、捕获变量、异步编程、委托、泛型、线程安全**等多个高级概念,适合考察资深 C# 开发者的综合理解能力。

---

### 🧠 面试题:闭包陷阱与异步编程中的变量捕获

**题目:**

考虑以下 C# 代码片段:

```csharp
using System;
using System.Threading.Tasks;

class Program
{
static async Task Main(string[] args)
{
var tasks = new Task[10];

for (var i = 0; i < 10; i++)
{
int temp = i;

tasks[i] = Task.Run(async () =>
{
await Task.Delay(100); // 模拟异步工作
Console.WriteLine($"i = {i}, temp = {temp}");
});
}

await Task.WhenAll(tasks);
}
}
```

#### 问题:

1. **输出结果会是什么?为什么?**
2. 如果将 `int temp = i;` 改为 `var temp = i;`,结果是否变化?为什么?
3. 如何修改代码,确保每个任务打印出 `i = 0, temp = 0` 到 `i = 9, temp = 9` 的预期结果?
4. 如果你将 `for` 循环改为 `for (int i = 0; i < 10; i++)`,结果是否会变化?请解释原因。

---

### ✅ 考察点解析:

1. **变量捕获(Closure)陷阱**:
- `i` 是在循环外部定义的(使用 `var i = 0`),因此在所有任务中捕获的是同一个变量 `i`。
- 当循环结束后,`i == 10`,所以所有任务在执行时看到的 `i` 都是 `10`。
- `temp` 是每次循环中定义的局部变量,每次循环都会创建一个新的变量,因此捕获的是不同的变量。

2. **异步与线程安全**:
- 任务异步执行,打印时 `i` 的值已经改变。
- 强调了闭包变量在异步/多线程环境下的行为。

3. **泛型、委托、Task 的使用**:
- 使用了 `Task.Run` 和 `async/await`,考察对异步编程模型的理解。

4. **语言版本细节**:
- 在 C# 5 及以上,`for (int i = 0; i < 10; i++)` 中的循环变量 `i` 每次循环都会创建一个新的变量实例,避免了闭包陷阱;而 `var i = 0` 则是外部变量,不会重新创建。

---

### 🧪 示例输出(当前代码):

```
i = 10, temp = 0
i = 10, temp = 1
i = 10, temp = 2
...
i = 10, temp = 9
```

---

### ✅ 正确做法(确保输出为 0~9):

```csharp
for (var i = 0; i < 10; i++)
{
int temp = i;
int copy = i; // 或者直接使用 temp

tasks[i] = Task.Run(async () =>
{
await Task.Delay(100);
Console.WriteLine($"i = {temp}, temp = {temp}");
});
}
```

或者使用 `for (int i = 0; i < 10; i++)`,这样每次循环的 `i` 是独立的。

---

这道题非常适合考察一个 C# 开发者对语言细节、闭包、异步编程模型和线程安全的理解,是一个典型的“看似简单,实则深奥”的题目。需要有扎实的底层知识才能完整回答。

除特别声明,本站所有文章均为原创,如需转载请以超级链接形式注明出处:SmartCat's Blog

上一篇: c#题例-2025-08-09 15:51:56

下一篇: c#题例-2025-08-09 03:31:45

精华推荐