迭代器模式(Iterator Pattern)

本文介绍迭代器模式的概念及其在C#中的应用。迭代器模式通过分离集合对象的存储数据与顺序访问数据的职责,使得开发者可以方便地遍历集合对象而不暴露其内部结构。文中详细解释了.NET框架中迭代器的实现方式,包括IEnumerator接口与IEnumerable接口的作用。

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

面向对象的设计,要求为对象做到好的职责分离,每个对象只包括最少的职责,这样其与其他对象的联系也越少,降低了对象间的耦合度。职责分离需要对对象被分离的职责进行封装,并以抽象的方式建立起彼此之间的关系。在设计中,我们往往将这些可能变化的对象抽象为接口和抽象类,从而将原来的具体依赖改变为抽象依赖。

迭代器模式就是分离集合对象的职责的方法,其将集合对象存储数据(存储数据的类型、存储空间的大小、存储空间的分配等)和顺序访问数据这二种职责进行分离。

 

目的:

提供一种方法顺序访问一个聚合对象中各个元素, 而又不需暴露该对象的内部表示。

 

适用性:

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

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

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

 

C#典型实现:

.Net中,迭代器由IEnumerator接口所定义:

public interface IEnumerator

{

    
bool MoveNext();

    Object Current 
{get; }

    
void Reset();

}


该接口提供了遍历集合元素的方法,其中主要的方法是MoveNext()。它将集合中的元素下标移到下一个元素。如果集合中没有元素,或已经移到了最后一个,则返回false。能够提供元素遍历的集合对象,在.Net中都实现了IEnumerator接口。

.Net中的所有集合类则实现另一个接口IEnumerable,其定义如下:

public interface IEnumerable
{
    IEnumerator GetEnumerator();
}


GetEnumerator()方法是一个生成迭代器的工厂方法,在集合类的内部以内部类的方式定义一个实现了IEnumerator接口的迭代器类,并在GetEnumerator()方法中返回其迭代器类的一个实例。

下面是.Net中的ArrayList的实现示意类图:

其中,类ArrayListEnumeratorSimple的相关实现如下所示:

[Serializable]
private class ArrayListEnumeratorSimple : IEnumerator, ICloneable
{
         
// Methods
         internal ArrayListEnumeratorSimple(ArrayList list)
         
{
               
this.list = list;
               
this.index = -1;
               
this.version = list._version;
               
this.currentElement = list;
         }


         
public virtual bool MoveNext()
         
{
               
if (this.version != this.list._version)
               
{
                    
throw new InvalidOperationException(Environment.GetResourceString(”InvalidOperation_EnumFailedVersion”));
               }

               
if (this.index < (this.list.Count - 1))
               
{
                      
this.index++;
                      
this.currentElement = this.list[this.index];
                      
return true;
               }

               
this.currentElement = this.list;
               
this.index = this.list.Count;
               
return false;
         }

         
public virtual void Reset()
         
{
               
if (this.version != this.list._version)
               
{
                      
throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_EnumFailedVersion"));
               }

               
this.currentElement = this.list;
               
this.index = -1;
         }

         
// Properties
         public virtual object Current
         
{
               
get
               
{
                      
object obj1 = this.currentElement;
                      
if (obj1 != this.list)
                      
{
                         
return obj1;
                      }

                      
if (this.index == -1)
                      
{
                         
throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_EnumNotStarted"));
                      }

                      
throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_EnumEnded"));
               }

         }

         
// Fields
         private object currentElement;
         
private int index;
         
private ArrayList list;
         
private int version;
}


ArrayListEnumeratorSimple实现了IEnumerator接口,实现了MoveNext()CurrentReset ()方法或属性。该类是一个私有类型,其构造函数则被internal修饰符限制。在自定义的构造函数中,传入的参数类型是ArrayList。正是通过 构造函数传递需要遍历的ArrayList对象,来完成MoveNext()CurrentReset()等操作。

ArrayList中,IEnumerable接口的GetEnumerator()方法实现代码如下:

public virtual IEnumerator GetEnumerator()
{
    
return new ArrayListEnumeratorSimple(this);
}

 

.Net2.0的实现:

由于在.Net2.0中对迭代器的实现提供了直接支持,所以其实现更加简单,并且不需要实现IEnumerable

public IEnumerator GetEnumerator()
{
       
for(int i = 0 ; i < Count ; i ++ )
              
yield return this[ i ] ;
}


.Net2.0的编译器最终会将其编译成类似典型实现的代码,只不过我们不需要再去手工实现IEnumerator接口。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值