IEnumerable

在C#中,`IEnumerable<T>` 是一个定义于 `System.Collections.Generic` 命名空间中的接口,它表示可以枚举的一系列元素的集合。`IEnumerable<T>` 接口是许多集合类(如 `List<T>`, `Dictionary<TKey, TValue>`, `Array` 等)的基础,并且它是实现迭代器模式的关键接口之一。

 

### 主要特性

 

- **GetEnumerator()**:这是 `IEnumerable<T>` 接口中唯一的方法。它返回一个实现了 `IEnumerator<T>` 接口的对象,该对象用于遍历集合。每次调用 `GetEnumerator()` 都会返回一个新的枚举器,这意味着你可以同时拥有多个独立的枚举器来遍历同一个集合。

 

  ```csharp

  public IEnumerator<T> GetEnumerator();

  ```

 

- **非泛型版本**:还有一个非泛型版本的 `IEnumerable` 接口,它存在于 `System.Collections` 命名空间中。这个接口也只有一个 `GetEnumerator` 方法,但它返回的是 `IEnumerator`,而不是 `IEnumerator<T>`。当处理的对象类型不是已知的时候,或者你需要与旧版代码兼容时,可能会用到非泛型版本。

 

  ```csharp

  public IEnumerator GetEnumerator();

  ```

 

### 使用场景

 

`IEnumerable<T>` 的主要用途是在 foreach 循环中遍历集合,因为 C# 编译器会在编译期间将 foreach 循环转换为对 `GetEnumerator()`、`MoveNext()` 和 `Current` 属性的调用。

 

```csharp

var numbers = new List<int> { 1, 2, 3, 4, 5 };

 

foreach (int number in numbers)

{

    Console.WriteLine(number);

}

```

 

上述代码实际上会被编译器转换成类似下面的形式:

 

```csharp

var enumerator = numbers.GetEnumerator();

while (enumerator.MoveNext())

{

    int number = enumerator.Current;

    Console.WriteLine(number);

}

```

 

### 惰性求值和延迟执行

 

当一个方法返回 `IEnumerable<T>` 类型的结果时,通常意味着该方法支持惰性求值(Lazy Evaluation)。这意味着实际的数据获取或计算只会在你开始遍历序列时发生,而且只会为当前访问的元素进行。这对于处理大数据集或流式数据非常有用,因为它可以节省内存并提高性能。

 

例如,LINQ 查询表达式经常返回 `IEnumerable<T>`,并且只有当你开始枚举结果时才会执行查询。

 

```csharp

var query = from n in numbers

            where n > 3

            select n;

 

// 此时,query 还没有执行任何操作

// 只有当我们遍历 query 时,查询才会被执行

foreach (var item in query)

{

    Console.WriteLine(item); // 输出: 4, 5

}

```

 

### 注意事项

 

- 如果你在遍历 `IEnumerable<T>` 时修改了底层集合,可能会抛出 `InvalidOperationException` 异常。这是因为大多数集合在检测到其结构被改变时会禁止继续枚举。

- `IEnumerable<T>` 不保证线程安全。如果你需要在多线程环境中使用,你可能需要额外的同步逻辑。

- 枚举器是一次性的,一旦完成遍历后,就不能再次使用同一个枚举器来重新遍历集合。如果需要多次遍历,必须通过 `GetEnumerator()` 获取新的枚举器。

 

### 实现自己的 IEnumerable<T>

 

如果你想创建一个自定义的集合类,并使其能够支持 `foreach` 循环,那么你需要实现 `IEnumerable<T>` 接口,并提供一个合适的枚举器。这通常涉及到定义一个内部类来实现 `IEnumerator<T>` 接口,或者利用 C# 的迭代器语法(yield return/yield break),它可以大大简化实现过程。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值