http://www.developer.com/net/cplus/article.php/3402241/Managed-Extensions-Versioning-Collection-Classes.htm
Welcome to this week's installment of .NET Tips & Techniques! Each week, award-winning Architect and Lead Programmer Tom Archer demonstrates how to perform a practical .NET programming task using either C# or Managed C++ Extensions.
In the previous two articles, I've illustrated how to make your C++ classes enumerable and how to add sorting capabilities to those classes. This article discusses the issue of versioning. Put simply, versioning your collections becomes important if the data held by the collection can be modified while a client is enumerating that data. Here's an example of the problem using the same Article class example I've been using throughout this series on programming collection classes with Managed Extensions:
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.
Managed Extensions: Versioning Collection Classes
September 1, 2004
The following steps demonstrate a technique that a member of the Microsoft .NET Common Language Runtime (CLR) team showed me—a technique that he told me they use internally.
__gc class ArticleCollection : public IEnumerable
{
...
static int version = 0;
__gc class ArticleCollection : public IEnumerable
{
...
public:
void Add()
{
// If data is changed, update version so that any
// outstanding enumerators are now out of data!
version++;
// perform add
}
__gc class ArticleCollection : public IEnumerable
{
...
public:
IEnumerator* GetEnumerator()
{
return dynamic_cast<IEnumerator*>(new ArticleEnumerator(this, version));
}
__gc class ArticleEnumerator : public IEnumerator
{
...
public:
ArticleEnumerator(ArticleCollection* collection, int version)
{
this->collection = collection;
this->version = version;
position = -1;
}
protected:
int version;
__gc class ArticleEnumerator : public IEnumerator
{
protected:
void VerifyVersion()
{
if (version != collection->version)
throw new InvalidOperationException(S"Data out of sync. "
S"Need to reacquire enumerator");
}
__gc class ArticleEnumerator : public IEnumerator
{
public:
bool MoveNext()
{
VerifyVersion();
...
}
__property Object* get_Current()
{
VerifyVersion();
...
}
void Reset()
{
VerifyVersion();
...
}
};
Maintaining a Boolean Member to Indicate a "Dirty" Collection
I used a numeric field to track the version number associated with a given enumerator object. I did this to handle scenarios in which the client might retrieve multiple enumerator objects from a single collection object. As a result, each time the data is changed the client code needs to reacquire each enumerator object that is made obsolete. Depending on the complexity of your needs, you could use a simple boolean member to indicate whether or not the collection is "dirty" or changed. The main difference being that if you use such a technique you would be marking the collection dirty for all clients of a particular instance of the collection. So it really comes down to the needs of your applications.
Looking Ahead
The past three (3) articles have illustrated the technique of creating two additional classes to the class that you're enumerating—a collection class (IEnumerable-derived) and an enumerator class (IEnumerable-derived). The next article will show how you can combine these two interfaces into a single class and explains when you would want to do that and when it would not be a good idea.
About the Author