Young87

SmartCat's Blog

So happy to code my life!

游戏开发交流QQ群号60398951

当前位置:首页 >AI写作

c#题例-2025-07-02 10:58:29

当然可以!以下是一道**专家级别**的 C# 逻辑面试题,它结合了语言特性、面向对象设计、泛型编程和一些巧妙的陷阱,适合考察候选人对 C# 的深度理解以及逻辑分析能力。

---

### 🧠 面试题:泛型委托与闭包陷阱

#### 题目描述:

下面是一个使用 `Func` 和闭包的 C# 程序,请你预测并解释其输出结果,并说明为什么会出现这样的结果。

```csharp
using System;
using System.Collections.Generic;

class Program
{
static void Main()
{
var actions = new List>();

for (int i = 0; i < 5; i++)
{
actions.Add(() => i);
}

foreach (var action in actions)
{
Console.Write(action() + " ");
}
}
}
```

---

#### 进阶问题(可选):

1. 如果将循环体改为:
```csharp
int copy = i;
actions.Add(() => copy);
```
输出会有什么不同?为什么?

2. 如何修改原始代码,使每个 lambda 表达式捕获的是当前迭代的值而不是变量本身?请提供至少两种解决方案。

---

### 💡 考察点解析:

- **闭包与变量捕获机制**:C# 中 lambda 表达式捕获的是变量本身,而非值。
- **延迟执行与副作用**:lambda 在添加到列表时不会立即执行,而是在调用时才执行。
- **值类型 vs 引用类型行为差异**
- **泛型委托的使用场景**
- **性能与内存管理意识**

---

### ✅ 标准答案:

#### 原始代码输出:

```
5 5 5 5 5
```

**原因解释:**

- 所有 lambda 表达式都捕获的是同一个变量 `i`,而不是每次迭代的副本。
- 循环结束后,`i` 的值为 5,此时所有 lambda 表达式引用的都是这个最终值。
- 所以在遍历执行时,它们读取的 `i` 都是 5。

---

#### 修改后的版本:

```csharp
int copy = i;
actions.Add(() => copy);
```

此时输出为:

```
0 1 2 3 4
```

**原因:**

- 每次迭代定义了一个新的局部变量 `copy`,它被分配一个新的存储位置。
- 每个 lambda 表达式捕获的是不同的 `copy` 变量,因此保留了当时的值。

---

### 🔁 解决方案汇总:

#### 方法一:引入中间变量复制值(如上所示)

#### 方法二:使用 `foreach` 替代 `for`(配合数组或集合)

```csharp
var values = new int[] { 0, 1, 2, 3, 4 };
var actions = new List>();

foreach (var v in values)
{
actions.Add(() => v);
}

// 输出: 0 1 2 3 4
```

> 注意:在 C# 5.0 及以后版本中,`foreach` 循环变量每次迭代都会创建一个新变量,避免了闭包陷阱。

---

如果你需要更多类似难度的问题(比如涉及协变逆变、反射、表达式树、async/await陷阱等),我可以继续提供。是否要再来一道?😊

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

上一篇: c#题例-2025-07-02 16:31:47

下一篇: c#题例-2025-07-02 05:25:01

精华推荐