Should a GetEnumerator method still be idempotent when the class does not implement IEnumerable?

It's not the type which is idempotent - that doesn't even make much sense; you may mean immutable, but that's not clear. It's the GetEnumerator method itself which is typically idempotent While I'd say that's typically the case, I can envisage special cases where it makes sense to have a non-idempotent GetEnumerator method. For example, it could be that you've got data which can only be read once (because it's streaming from a web server which won't service the same request again, or something like that).

In that case GetEnumerator would have to effectively invalidate the data source, so that future calls would throw an exception Such types and methods should be documented very carefully, of course, but I think they're reasonable.

It's not the type which is idempotent - that doesn't even make much sense; you may mean immutable, but that's not clear. It's the GetEnumerator method itself which is typically idempotent. While I'd say that's typically the case, I can envisage special cases where it makes sense to have a non-idempotent GetEnumerator method.

For example, it could be that you've got data which can only be read once (because it's streaming from a web server which won't service the same request again, or something like that). In that case, GetEnumerator would have to effectively invalidate the data source, so that future calls would throw an exception. Such types and methods should be documented very carefully, of course, but I think they're reasonable.

Thought you might be the one to answer, I saw your response to a similar post and thought you might have an opinion which was not a hard and fast rule. Not sure if you read the other question which was about a blocking queue, I feel this is similar to your stream example. Strictly speaking you should not be able to view the contents of a queue and using the foreach was "a way" of popping all of the items out.

I have clarified what I mean when I said idempotent, thanks. – Bronumski Nov 16 '10 at 14:18 Could you clarify whether you think that implementing IEnumerable is relevant or not? – Bronumski Nov 16 '10 at 14:36.

This discussion is an old one and to my knowledge there's no common consensus. Please do not confuse the concept of (runtime) Duck-Typing with abusing the compiler supported foreach to support your desired semantics. Another concept you seem to confuse is Idempotence vs. Immutability.

According to your wording you try to describe the second, which means the object providing the enumerator gets modified during enumeration. Idempotence on the other hand means your enumerator, when called twice will yield the same results. Now that we're clear on this, you need to carefully decide on the semantics your IEnumerable operation should support.

Certain kind of enumerations are hard to make idempotent (i.e. Involve caching), and do usually fall into one of the following categories: Enumerating over randomly changing data (i.e. A random number generator, sensor streams) Enumerating over shared state (e.g. Files, databases, streams etc. ) On the other hand, this only accounts for "source" operations.

If you are implementing filter or transformation operations using enumerators, you should always try to make them idempotent.

I was trying to remove my scenario from the question to keep the question open. What I was suggesting in my previous question was when iterating over a blocking queue each item was dequeued as it went. Additionally any new objects pushed onto the queue after the call to GetEnumerator would still be iterated over.

– Bronumski Nov 16 '10 at 14:31 Could you clarify whether you think that implementing IEnumerable is relevant or not? – Bronumski Nov 16 '10 at 14:36.

It seems you want a queue class from which you can dequeue all items in a nice one-liner. There's nothing wrong with this idea per se; I'd just question your preference to specifically use GetEnumerator to achieve what you're after. Why not simply write a method that is more explicit in terms of what it does?

For example, DequeueAll, or something of the sort. Example: // Just a simplistic example. Not the way I'd actually write it.

Class CustomQueue : Queue { public IEnumerable DequeueAll() { while (Count > 0) { yield return Dequeue(); } } } (Note that the above could even be an extension method, if it represents literally the only functionality you'd want above and beyond what is already provided by Queue. ) This way you could still get the "clean"-looking code I suspect you're after, without the (potential) confusion of a non-idempotent GetEnumerator: // Pretty clean, right? Foreach (T item in queue.DequeueAll()) { Console.

WriteLine(item); }.

That is pretty much what I came to. In fact someone pointed out that . Net 4 introduced a IProducerConsumerCollection interface and BlockingCollection implementation with a GetConsumingEnumerable method.

This question was more about whether it was bad practice because the class has a GetEnumerator method, because the class implements IEnumerable or neither. – Bronumski Nov 16 '10 at 15:06 BTW I like the idea of the extension method. – Bronumski Nov 16 '10 at 15:35.

I would suggest that using ForEach on a collection shouldn't change it unless the name of the collection type implies that's going to happen. The issue in my mind would be what should be returned if a method is performed to consume a collection into something enumerable (e.g. To allow "For Each Foo in MyThing. DequeueAsEnum").

If DequeueAsEnum returns an iEnumerable, then someone could expect to get away with "Dim myIEnumerable As IEnumerable = MyThing. DequeueAsEnum" and then use MyIEnumerable in two disjoint For-Each loops. If DequeueAsEnum returns a type EnumerableOnlyOnce, then it would be a little clearer that its return should only be enumerated once.

To be sure, the existence of implicit typing in newer C# and VB. Net dialects makes it a bit more likely that someone might assign the function return to a variable when they shouldn't, but I don't know how to prevent that. BTW, there are a number of circumstances where it would be helpful to prevent a class reference from being stored into a variable; is there any way to declare a class in such a way that outside code can use expressions of that class type, but cannot declare variables of it?

Now that we're clear on this, you need to carefully decide on the semantics your IEnumerable operation should support. Certain kind of enumerations are hard to make idempotent (i.e. On the other hand, this only accounts for "source" operations.

If you are implementing filter or transformation operations using enumerators, you should always try to make them idempotent.

I cant really gove you an answer,but what I can give you is a way to a solution, that is you have to find the anglde that you relate to or peaks your interest. A good paper is one that people get drawn into because it reaches them ln some way.As for me WW11 to me, I think of the holocaust and the effect it had on the survivors, their families and those who stood by and did nothing until it was too late.

Related Questions