枚举器模式(Enumerator pattern)

如何使用枚举器模式( Enumerator pattern ):

1、 如果你要实现 ** IEnumerable.GetEnumerator ** ** , ** 你也要实现一个 ** GetEnumerator ** 方法的非虚方法版本。你的枚举器类的 ** IEnumerable.GetEnumerator ** 方法应该调用这个非虚方法。如下所示应该返回一个内嵌的枚举器结构:

·                           class MyClass : IEnumerable


·                           {


·                             // non-virtual implementation for your custom collection


·                             public MyEnumerator GetEnumerator() {


·                               return new MyEnumerator(this); // Return nested public struct


·                             }


·                           // IEnumerator implementation


·                             public IEnumerator.GetEnumerator() {


·                               return GetEnumerator();//call the non-interface method


·                             }


·                           }

如果你的类已经显示地提供了非虚的 ** GetEnumerator ** 方法,那么 ** foreach ** 语句就会调用这个非虚的 ** GetEnumerator ** 方法。否则,它会调用 ** IEnumerable.GetEnumerator ** 方法,如果你的类实现了 ** Ienumerable ** 接口。调用一个非虚方法比通过接口调用一个虚方法要更有效。

2、 在枚举器结构中显示的实现 ** IEnumerator.Current ** 属性。 .NET 的实现类在实现时会使得该属性返回一个 ** System.Object ** 对象,而不是一个强类型的对象。这会存在类型转换开销。通过在你的 Current 属性中返回一个强类型对象或者精确的值类型而不是 ** System.Object ** ** , ** 可以避免类型转换的开销。因为你已经显示地实现了一个非虚地 ** GetEnumerator ** 方法(不是 ** IEnumerable.GetEnumerator ** 方法), CLR 能够直接调用 ** Enumerator.Current ** 属性,而不是调用 ** IEnumerator.Current ** 属性,因此可以直接获取所期待的数据,还能避免类型转换和装箱操作的开销。而减少虚方法调用,可以利用方法的内联了。你的实现应该如下:

// Custom property in your class


//call this property to avoid the boxing or casting overhead


Public MyValueType Current { 


  MyValueType obj = new MyValueType();


  // the obj fields are populated here


  return obj;        


}


// Explicit member implementation


Object IEnumerator.Current {


get { return Current} // Call the non-interface property to avoid casting


}

注:枚举器模式只有当性能是关键时才适用。

下面的示例代码展示了枚举器模式:

public class  ItemTypeCollection: IEnumerable 


{


   public struct MyEnumerator : IEnumerator 


   {


      public ItemType Current { get {… } }


      object IEnumerator.Current { get { return Current; } }


      public bool MoveNext() { … }


      …   }


   public MyEnumerator GetEnumerator() { … }


   IEnumerator IEnumerable.GetEnumerator() { … }


   …}

要利用 JIT 的内联方式,应该避免在你的集合类中使用虚方法,除非你确实需要扩展。同时,在 ** Current ** 属性的实现中返回当前值来允许使用内联,或者使用一个字段。

Published At
Categories with Web编程
Tagged with
comments powered by Disqus