Young87

SmartCat's Blog

So happy to code my life!

游戏开发交流QQ群号60398951

当前位置:首页 >AI写作

c#题例-2025-07-04 20:59:08

当然可以!以下是一道**专家级别**的 C# 程序员逻辑面试题,涉及 **委托、事件、异步编程、闭包捕获和线程安全**等多个高级概念:

---

### 🧠 面试题:异步委托与闭包陷阱

**题目描述:**

请分析下面的 C# 代码,并回答问题。

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

class Program
{
static void Main(string[] args)
{
for (var i = 0; i < 5; i++)
{
Task.Run(() =>
{
Console.WriteLine(i);
});
}

Console.ReadKey();
}
}
```

#### ❓问题1:
这段代码的输出是什么?为什么?

#### ❓问题2(进阶):
如何修改代码以确保每个任务都输出其对应的循环变量值(即 0 到 4)?

#### ❓问题3(扩展):
如果将 `Task.Run` 替换为 `Task.Factory.StartNew`,是否会影响结果?为什么?

#### ❓问题4(挑战):
假设你不能修改循环体内的代码,也不能使用 `let` 变量(如在 `for` 中定义局部变量),你能否通过其他方式(如使用闭包参数传递、冻结变量等)保证输出正确?

---

### ✅ 参考答案概要:

#### 回答1:
输出可能为多个 `5`,因为 `i` 是被闭包捕获的循环变量。当 `Task.Run` 异步执行时,`i` 已经递增完成,最终值是 5。所有任务访问的是同一个变量 `i`,而不是当时的值快照。

#### 回答2:
在每次循环中创建一个副本:

```csharp
for (var i = 0; i < 5; i++)
{
int loopCopy = i;
Task.Run(() => Console.WriteLine(loopCopy));
}
```

或者使用 `foreach` + 局部变量(C# 5.0+ 的行为更直观)。

#### 回答3:
`Task.Factory.StartNew` 和 `Task.Run` 在这种场景下行为相同,仍会受闭包捕获影响,因此不会改变结果。

#### 回答4:
可以通过封装到方法中传参实现:

```csharp
void RunTask(int value)
{
Task.Run(() => Console.WriteLine(value));
}

// 修改主循环:
for (var i = 0; i < 5; i++)
{
RunTask(i);
}
```

此时每次调用 `RunTask(i)` 会将当前 `i` 的值拷贝给形参 `value`,形成独立闭包。

---

### 💡考察点总结:

- 对 **闭包捕获机制** 的理解
- 对 **异步任务调度与线程安全** 的掌握
- **变量生命周期与作用域**
- 是否了解 **C# 循环变量捕获的历史变化(C# 5 vs C# 4)**
- 能否灵活运用 **委托与函数式编程技巧** 解决实际问题

---

如果你需要更多类似级别的题目(例如涉及 LINQ 表达式树、泛型约束、内存泄漏、await/async 控制流、协变逆变等),我可以继续为你出题 😄

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

上一篇: c#题例-2025-07-05 02:32:27

下一篇: c#题例-2025-07-04 15:25:48

精华推荐