August 22, 2014
Hot Topics:
RSS RSS feed Download our iPhone app

Managed Extensions: Combining IEnumerable and IEnumerator

  • September 2, 2004
  • By Tom Archer
  • Send Email »
  • More Articles »

Combining the Two Interfaces

Having two distinct interfaces (IEnumerable and IEnumerator) eases the burden of keeping track of enumerators that represent snapshots of dynamic data. The logical question then is "what if the data is static?" In other words, why define an enumerator class that has its own copy of the original collection data if that data never changes? This is one scenario where combining the two interfaces into a single collection class would be advantageous. (You could also keep the collection and enumerator class definitions separate and simply not copy the data—instead having the enumerator object's Current, MoveNext, and Reset members directly access the collections data. However, why even define a separate enumerator class in situations where it has no benefit?)

Therefore, in the following class definitions, I've taken the Article class used in the past few articles and modified it to include a single class (ArticleCollection) that implements both the IEnumerable and IEnumerator interfaces:

#pragma once

#pragma push_macro("new")
#undef new

__gc class Article
{
public:
  Article(String* title, String* author, String* category)
  {
    this->title = title;
    this->author = author;
    this->category = category;
  }

protected:
  String* title;
  String* author;
  String* category;

public:
  __property String* get_Title() { return this->title; }
  __property String* get_Author() { return this->author; }
  __property String* get_Category() { return this->category; }
};

__gc class ArticleCollection : public IEnumerable, public IEnumerator
{
protected:
  ArrayList* articles;
public:
  ArticleCollection()
  {
    articles = new ArrayList();
    
    // create some sample data
    articles->Add(new Article(S"Article #1", 
                              S"Tom", 
                              S"Managed Extensions"));
    articles->Add(new Article(S"Article #2", 
                              S"Dick", 
                              S"Visual C++/MFC"));
    articles->Add(new Article(S"Article #3", 
                              S"Harry", 
                              S"C#"));
  }
	
public:
  IEnumerator* GetEnumerator()
  {
    Reset();
    return this;
  }

protected:
  int position;

public:
  bool MoveNext() { return (++position < articles->Count); }

  __property Object* get_Current()
  {
    if (0 > position
    || position >= articles->Count)
	    throw new InvalidOperationException();

    return articles->Item[position];
  }

  void Reset() { position = -1; }
};
#pragma pop_macro("new")
Here's a list of the main changes to the technique for enumerating your classes covered in the article, Managed Extensions: Adding Enumeration to Your Classes:
  • Aside from the class you want enumerable, the only class you need to add is a collection class that implements (derives from) both IEnumerable and IEnumerator. In this example, this leaves you with the Article and ArticleCollection classes.
  • Since the collection class implements both interfaces, the GetEnumerator method can now simply return the current object instance instead of instantiating a separate enumerator object, which would involve the unnecessary copying of the collection object's data.
  • The Reset, MoveNext, and get_Current methods are now in the collection class.

About the Author

The founder of the Archer Consulting Group (ACG), Tom Archer has been the project lead on three award-winning applications and is a best-selling author of 10 programming books as well as countless magazine and online articles.





Page 2 of 2



Comment and Contribute

 


(Maximum characters: 1200). You have characters left.

 

 


Sitemap | Contact Us

Rocket Fuel