Academic Integrity: tutoring, explanations, and feedback — we don’t complete graded work or submit on a student’s behalf.

Let\'s say I\'m designing a custom data structure like a stack or a queue (for e

ID: 642213 • Letter: L

Question

Let's say I'm designing a custom data structure like a stack or a queue (for example - could be some other arbitrary ordered collection that has the logical equivalent of push and pop methods - ie destructive accessor methods).

If you were implementing an iterator (in .NET, specifically IEnumerable<T>) over this collection that popped on each iteration, would that be breaking IEnumerable<T>'s implied contract?

Does IEnumerable<T> have this implied contract?

eg:

public IEnumerator<T> GetEnumerator()
{
    if (this.list.Count > 0)
        yield return this.Pop();
    else
        yield break;
}

Explanation / Answer

I believe a destructive Enumerator violates the Principle of Least Astonishment. As a contrived example, imagine a business object library that offers generic convenience functions. I innocently write a function that updates a collection of business objects:

static void UpdateStatus<T>(IEnumerable<T> collection) where T : IBusinessObject
{
foreach (var item in collection)
{
item.Status = BusinessObjectStatus.Foo;
}
}
Another developer who knows nothing about my implementation or your implementation innocently decides to use both. It's likely they'll be surprised by the result:

//developer uses your type without thinking about the details
var collection = GetYourEnumerableType<SomeBusinessObject>();

//developer uses my function without thinking about the details
UpdateStatus<SomeBusinessObject>(collection);
Even if the developer is aware of the destructive enumeration, they may not think about the repercussions when handing the collection to a black-box function. As the author of UpdateStatus, I'm probably not going to consider destructive enumeration in my design.

However, it is only an implied contract. .NET collections, including Stack<T>, enforce an explicit contract with their InvalidOperationException - "Collection was modified after the enumerator was instantiated". You could argue that a true professional has a caveat emptor attitude toward any code that is not their own. The surprise of a destructive enumerator would be discovered with minimal testing.