C#迭代器

本文详细介绍了C#2.0中迭代器的概念、语法、实现方式及其在不同场景下的应用,包括非泛型和泛型迭代器的实现、使用yield关键字的特性、迭代器机制以及如何在类中实现多个迭代器。此外,文章还讨论了迭代器的机制、适用性和总结了其在C#编程中的优势。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

迭代器概述

迭代器是可以返回相同类型的值的有序序列的一段代码。

迭代器可用作方法、运算符或 get 访问器的代码体。

迭代器代码使用 yield return 语句依次返回每个元素。yield break 将终止迭代。有关更多信息,请参见 yield。

可以在类中实现多个迭代器。每个迭代器都必须像任何类成员一样有唯一的名称,并且可以在 foreach 语句中被客户端代码调用,如下所示:foreach(int x in SampleClass.Iterator2){}

迭代器的返回类型必须为 IEnumerable、IEnumerator、IEnumerable<T> 或 IEnumerator<T>。

迭代器是使用在foreach中的集合。在C#2.0中使用迭代器创建一个用于foreach的集合,实现上比较简单:继承于IEumnerable,并实现GetEnumerator()。

首先这个集合要基于IEnumerable(可以使用泛型),下面先来实现一个非泛型版的迭代器。代码如下(非泛型代码示例来源于MSDN):

 

 public class DaysOfTheWeek : System.Collections.IEnumerable
    {
      string[] m_Days = { "Sun", "Mon", "Tue", "Wed", "Thr", "Fri", "Sat" };

      public System.Collections.IEnumerator GetEnumerator()
      {
        for (int i = 0; i < m_Days.Length; i++)
        {
          yield return m_Days[i];
        }
      }
    }

    class TestDaysOfTheWeek
    {
      static void Main()
      {
        DaysOfTheWeek week = new DaysOfTheWeek();
        foreach (string day in week)
        {
          System.Console.Write(day + " ");
        }
        Console.Read();
      }
   }

 

操作结果是:

Sun Mon Tue Wed Thr Fri Sat

其中yied return关键字产生枚举元素

泛型版迭代器的实现代码如下:

 

static void Main(string[] args)
    { 

      Stack<int> stack = new Stack<int>();
      stack.items = new int[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
      foreach (int i in stack)
      {
        Console.WriteLine(i);
      }
      Console.Read();
   }

public class Stack<T> : IEnumerable<T>
  {
    public T[] items;

    public IEnumerator<T> GetEnumerator()
    {
      for (int i = 0; i < items.Length; i++)
      {
        yield return items[i];
      }
    }

    IEnumerator IEnumerable.GetEnumerator()
    {
      return GetEnumerator();
    }
}

 

运行结果如下:

1
2
3
4
5
6
7
8
9
10

其中G在实现泛型迭代器时我一直没有写IEnumerator IEnumerable.GetEnumerator()这个方法,所以编译器一直在给我报错,(猜想)这个方法应该IEnumerator<T>接口中的一个抽象方法。而这个方法中调用的GetEnumerator(),通过集成环境中的提示发现,实际上是上面写到的IEnumerator<T> GetEnumerator()这个泛型方法。

在自定义迭代器时,我们可以利用yield break关键字跳出循环。如上面的例子中,我们想只输出小于等于5的项,调整上面代码,如:

 

public class Stack<T> : IEnumerable<T>
  {
    public T[] items;

    public IEnumerator<T> GetEnumerator()
    {

      for (int i = 0; i < items.Length; i++)
      {        

        if ((Convert.ToInt32(items[i]) > 5))
          yield break;

        yield return items[i];
      }
    }

    IEnumerator IEnumerable.GetEnumerator()
    {
      return GetEnumerator();
    }
  }

 

 

操作结果:

 

1
2
3
4
5

 

迭代器的机制:

 

  实际上迭代器只是在C#2.0中通过编译器一层额外处理的,用来简化创建可用于foreach的枚举集合的工作,从性能上没有什么变化。对于其生成的中间语言没有太多的变化。

实例:定义和使用命名迭代器

 

   class Class1
  {
    public IEnumerator GetEnumerator()
    {
      for (int i = 0; i < 10; i++)
      {
        yield return i;
      }
    }

 

    // 定义一个命名的迭代器,并可以提供参数
    public IEnumerable MaxToMin(int min, int max)
    {
      for (int i = max; i >= min; i--)
      {
        yield return i;
      }
    }

 

    // 定义一个迭代器类型的属性,
    public IEnumerable MinToMax
    {
      // this表示该类实例,因为该类实现了GetEnumerator(),它是可枚举的
      get { yield return this; }
    }

 

    public IEnumerable GetDescriptions()
    {
      yield return "this is my test";
      yield return "class name is class1";
      yield return "ktgu";
    }
  }

 

  static void Main(string[] args)
  {
    
    Class1 c = new Class1();

 

    foreach (int i in c)
    {
      Console.WriteLine(i);
    }

 

    foreach (int i in c.MaxToMin(1, 10))
    {
      Console.WriteLine(i);
    }

 

    foreach (int i in c.MinToMax)
    {
      Console.WriteLine(i);
    }

 

    foreach (string s in c.GetDescriptions())
    {
      Console.WriteLine(s);
    }
   }

 


迭代效果及实现要点

 

1.迭代抽象:访问一个聚合对象的内容而无需暴露它的内部表示。

 

2.迭代多态:为遍历不同的集合结构提供一个统一的接口,从而支持同样的算法在不同的集合结构上进行操作。

 

3.迭代器的健壮性考虑:遍历的同时更改迭代器所在的集合结构,会导致问题。

 

适用性

 

1.访问一个聚合对象的内容而无需暴露它的内部表示。

 

2.支持对聚合对象的多种遍历。

 

3.为遍历不同的聚合结构提供一个统一的接口(即, 支持多态迭代)。

 

总结

 

Iterator模式就是分离了集合对象的遍历行为,抽象出一个迭代器类来负责,这样既可以做到不暴露集合的内部结构,又可让外部代码透明的访问集合内部的数据

参考:
C#2.0-迭代器应用 http://cs.alienwave.cn/Topic/1347.aspx
迭代器(C# 编程指南) http://msdn2.microsoft.com/zh-cn/library/dscyy5s0(VS.80).aspx

 

转载于:https://www.cnblogs.com/eagle1986/archive/2011/12/05/2276293.html

<think>好的,用户想了解C#迭代器的用法和相关编程问题。首先,我需要回忆C#迭代器的基本概念,并确保信息的准确性。迭代器C#中是通过yield return和yield break语句实现的,用于简化集合的遍历。需要解释什么是迭代器,以及它们如何工作。 接下来,我应该涵盖如何创建迭代器方法。可能需要举一个简单的例子,比如生成数字序列。同时,用户可能想知道如何实现自定义集合的迭代器,比如一个自定义类实现IEnumerable接口,使用迭代器块来返回元素。 然后,考虑用户可能遇到的常见问题,比如延迟执行特性。需要说明迭代器方法在调用时不会立即执行,而是在遍历时才会执行。这可能会导致一些意想不到的结果,比如在迭代过程中修改集合的影响。此外,异常处理也是需要注意的地方,在迭代器内部如何处理异常,以及finally块的行为。 另外,用户可能对实际应用场景感兴趣,比如分页处理大数据集,或者生成无限序列。这时候需要举出具体的例子,说明如何利用迭代器的延迟加载特性来优化性能。 还要记得引用提供的资料,比如引用[2]中提到foreach循环在不同语言中的应用,可以联系到C#中foreach如何与迭代器配合使用。引用[4]提到的MayExtensions和MayUtilities类可能涉及IEnumerable<T>的扩展方法,可以提到使用LINQ方法如Where、Select等与迭代器的结合。 需要检查是否有相关优化技巧,比如避免在迭代器中修改集合,或者使用yield break提前终止迭代。同时,性能方面的考虑,比如迭代器的内存效率和执行效率,尤其是在处理大规模数据时的优势。 最后,确保回答结构清晰,分点说明,并提供代码示例。可能的问题包括如何实现自定义迭代器、处理异常、性能优化等。生成的相关问题需要覆盖这些方面,帮助用户进一步学习。</think>### C#迭代器使用指南 迭代器C#中实现集合遍历的核心机制,通过`yield return`和`yield break`语句实现延迟执行特性[^2]。以下是具体用法和示例: #### 一、基础迭代器实现 1. **简单数字生成器** ```csharp public static IEnumerable<int> GenerateNumbers(int max) { for(int i=0; i<max; i++){ yield return i; // 每次迭代返回当前值 if(i > 5) yield break; // 提前终止迭代 } } // 使用示例 foreach(var num in GenerateNumbers(10)){ Console.WriteLine(num); // 输出0-6 } ``` 2. **自定义集合迭代** ```csharp public class ColorCollection : IEnumerable<string> { private string[] _colors = {"Red","Green","Blue"}; public IEnumerator<string> GetEnumerator() { foreach(var color in _colors){ yield return color; } } } ``` #### 二、高级应用场景 1. **分页处理大数据集** ```csharp public static IEnumerable<DataChunk> ReadLargeFile(string path) { using var reader = new StreamReader(path); while(!reader.EndOfStream){ var buffer = new char[1024]; reader.ReadBlock(buffer, 0, 1024); yield return new DataChunk(buffer); } } ``` 2. **无限序列生成** ```csharp public static IEnumerable<int> Fibonacci() { int a=0, b=1; while(true){ yield return a; (a, b) = (b, a+b); } } ``` #### 三、核心特性说明 1. **延迟执行机制**:迭代器方法在调用时仅返回枚举器对象,实际代码在`MoveNext()`时执行[^4] 2. **状态保持**:每次`yield return`会保留当前执行上下文状态 3. **异常处理**: ```csharp public static IEnumerable<string> SafeIteration() { try{ yield return "Start"; throw new Exception("Test"); } finally{ Console.WriteLine("Cleanup"); // 仍会执行 } } ``` #### 四、最佳实践建议 1. 避免在迭代过程中修改被遍历的集合 2. 复杂逻辑建议分离到单独方法 3. 结合LINQ使用提升效率: ```csharp var filtered = GenerateNumbers(100).Where(n => n%2 == 0); ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值