Template for using IEnumerator <T> in interfaces
I have a C # class that needs to process a sequence of elements ( IEnumerable<T>) through a bunch of methods, so I can't just foreachinside a method. I call .GetEnumerator()and pass this IEnumerator<T>one and it works great, giving me the necessary flexibility when you loop through one sequence.
Now I want to allow others to add logic to this process. The most natural way to do this is to give them an interface with a method that accepts IEnumerator<T>. Easy, done, and it works.
But I am worried that this is an anti-pattern. They need to know what IEnumerator<T>has already been triggered .MoveNext(), so they can simply access it .Current. Plus, I do not see a precedent for use IEnumerator<T>in the interfaces that will be implemented.
- What mistakes do I not consider?
- Is there another template that will allow me this most efficient mechanism (i.e. I donβt want several copies to be created / destroyed) without exposing myself
IEnumerator<T>?
Update: As I mentioned in the comment below: What I want is a kind of general one Stream<T>. I need to be able to effectively see the next element ( IEnumerator.Currentβ .Peek()) and consume it ( IEnumerator<T>.MoveNext()β .Pop()).
I used IEnumerator<T>because it matched the account interface. I prefer to use generic BCL types when appropriate, but it seemed to me that I was abusing it.
So, question 3) Is there a class that is suitable for this need? Or should I just create my own Stream, which lazily performs IEnumerator<T>internally? Then it will be fully encapsulated. I would not want to use many existing collections as they have internal storage, whereas I would like the storage to be IEnumerable<T>iteslf.
OK, it seems that the consensus is what to do with IEnumerator<T>, often being ValueType, as well as not knowing a priori the state IEnumerator<T>, which is usually a bad idea to convey it.
, , - , . ?
IEnumerator<T>. , . , ?
using System;
using System.Collections.Generic;
class Test
{
static void ShowCurrentAndNext(IEnumerator<int> iterator)
{
Console.WriteLine("ShowCurrentAndNext");
Console.WriteLine(iterator.Current);
iterator.MoveNext(); // Let assume it returns true
Console.WriteLine(iterator.Current);
}
static void Main()
{
List<int> list = new List<int> { 1, 2, 3, 4, 5 };
using (var iterator = list.GetEnumerator())
{
iterator.MoveNext(); // Get things going
ShowCurrentAndNext(iterator);
ShowCurrentAndNext(iterator);
ShowCurrentAndNext(iterator);
}
}
}
:
using (List<int>.Enumerator iterator = list.GetEnumerator())
using (IEnumerator<int> iterator = list.GetEnumerator())
:)
, , , , . "" , .
It sounds to me as if you could use an event so that you can click on notification of items that will be processed by listeners. Regular .NET events are processed in the order in which they are signed, so a clearer approach is required for ordering.
You may also like the Reactive Framework.