Is there a built-in way to convert IEnumerator<T>
to IEnumerable<T>
?

- 128,308
- 78
- 326
- 506
-
The only question on StackOverflow that Jon Skeet has not answered. – BenKoshy Jan 05 '23 at 00:38
9 Answers
The easiest way of converting I can think of is via the yield statement
public static IEnumerable<T> ToIEnumerable<T>(this IEnumerator<T> enumerator) {
while ( enumerator.MoveNext() ) {
yield return enumerator.Current;
}
}
compared to the list version this has the advantage of not enumerating the entire list before returning an IEnumerable. using the yield statement you'd only iterate over the items you need, whereas using the list version, you'd first iterate over all items in the list and then all the items you need.
for a little more fun you could change it to
public static IEnumerable<K> Select<K,T>(this IEnumerator<T> e,
Func<K,T> selector) {
while ( e.MoveNext() ) {
yield return selector(e.Current);
}
}
you'd then be able to use linq on your enumerator like:
IEnumerator<T> enumerator;
var someList = from item in enumerator
select new classThatTakesTInConstructor(item);

- 19
- 1
- 5

- 21,497
- 7
- 62
- 96
-
6-1: This doesn't cater for the fact that an IEnumerable should be able to be iterated over multiple times; here it will only be able to be done once as the source IEnumerator will have been used up. You need to cache the items from the IEnumerator for the second time round. – Greg Beech Jul 15 '09 at 07:56
-
10Well you are stating a requirement not stated (at least explicitly) in the question. If multiple iterations is not required caching will be a performance hit and Sam states that performance is very much a concern hence no caching included – Rune FS Jul 22 '09 at 08:27
-
This is wrongheaded and pointlessly inefficient. See my answer. user says *+1 For not needing to define a class* -- but this doesn't just define a class, it defines *two* classes. An `IEnumerable
` method that does `yield return` is converted by the compiler into a class that implements `IEnumerator – Jim Balter Nov 29 '18 at 08:33`, and a class that implements `IEnumerable ` that returns an instance of the former class. The method in turn returns an instance of the second class. -
2*You need to cache the items from the IEnumerator for the second time round. * -- um, no. It's up to the caller to Reset the Enumerator if that's what they want: `foreach(var x in fooEnumerator.ToIEnumerable
()) { ... }; fooEnumerator.Reset(); foreach(var x in fooEnumerator.ToIEnumerable – Jim Balter Nov 29 '18 at 08:36()) { ... };` -
1@JimBalter technically it doesn't define any classes. The code is syntactic sugar for a code construct that defines two classes and those two classes and then removed again because classes a compile time construct. So I guess the comment is aimed at the fact that the code doesn't require any additional classes (aside from the class that holds the method) – Rune FS Nov 29 '18 at 18:50
-
Sorry, but the above comment is completely false (to the degree that it's even comprehendible). It does define two classes, as it must, since the method using `yield return` must return an instance of IEnumerable, and the GetEnumerator method of instance must in turn return an instance of IEnumerator. If you want to debate it, take it up with the language spec ... I won't comment further. – Jim Balter Nov 29 '18 at 23:16
-
1@JimBalter there's absolutely nothing in the specs that requires any classes to be defined in the above code. It would be perfectly legal to compile the above to IL without emitting any additional classes and simply reusing existing classes – Rune FS Dec 07 '18 at 16:26
You could use the following which will kinda work.
public class FakeEnumerable<T> : IEnumerable<T> {
private IEnumerator<T> m_enumerator;
public FakeEnumerable(IEnumerator<T> e) {
m_enumerator = e;
}
public IEnumerator<T> GetEnumerator() {
return m_enumerator;
}
// Rest omitted
}
This will get you into trouble though when people expect successive calls to GetEnumerator to return different enumerators vs. the same one. But if it's a one time only use in a very constrained scenario, this could unblock you.
I do suggest though you try and not do this because I think eventually it will come back to haunt you.
A safer option is along the lines Jonathan suggested. You can expend the enumerator and create a List<T>
of the remaining items.
public static List<T> SaveRest<T>(this IEnumerator<T> e) {
var list = new List<T>();
while ( e.MoveNext() ) {
list.Add(e.Current);
}
return list;
}
-
This will work so long as you only call GetEnumerator() once -- most things that call that expect to get their own copy. Ie. once you've moved through the whole thing, you can't start over again. – Jonathan Rupp Jun 22 '09 at 22:03
-
@Jonathan, yes entirely true (noted in the answer). Precisely why I said "kinda" – JaredPar Jun 22 '09 at 22:04
-
1Yeah I did something like this ... another problem with this is that when you get an enumerator its in position -1 so wrapping it in this way causes a skip – Sam Saffron Jun 22 '09 at 22:05
-
@Jared, you mean SaveRest(this IEnumerator
enumerable) no... thats one dangerous function, as a side effect it enumerates AND it returns a list.... I ended up coding around this see: http://stackoverflow.com/questions/1018407/what-is-the-most-elegant-way-to-get-a-set-of-items-by-index-from-a-collection/1025137#1025137 but the problem is I lost elegance there – Sam Saffron Jun 22 '09 at 22:19 -
@Sam, What would you return besides an IList
? I chose a List – JaredPar Jun 22 '09 at 22:48over an iterator because it removes the issue of dealing with IEnumerater being disposable. Theres' no dispose question if you create the List immediately. If you choose the iterator path, you must deal with lifetime of the IEnumerator -
I don't think I have any good solution. I guess the general guildeline of always avoiding any method that takes in a Enumerator as a param should followed. – Sam Saffron Jun 22 '09 at 23:01
-
Another option would be to write an `AsForEachable` method which returns a struct that does not implement from `IEnumerable
` but includes a `GetEnumerator` method which returns the underlying enumerator. Such a struct may be used in a `foreach` statement to read things out of the enumerator, but code which expects an `IEnumerable – supercat Dec 11 '13 at 18:17` wouldn't accept it. -
*when people expect successive calls to GetEnumerator to return different enumerators vs. the same one* -- since the constructor of FakeEnumerable takes a single IEnumerator as an argument, how could anyone expect such a thing? *A safer option is along the lines Jonathan suggested* -- no, that's deeply confused. If you want to rerun the IEnumerator, then call Reset on it ... that's what that method is for. But the fact is that this isn't how .NET enumerators are used ... IEnumerable is the public-facing object and IEnumerator is normally a private class that enumerates it. – Jim Balter Nov 29 '18 at 08:54
EnumeratorEnumerable<T>
A threadsafe, resettable adaptor from IEnumerator<T>
to IEnumerable<T>
I use Enumerator parameters like in C++ forward_iterator concept.
I agree that this can lead to confusion as too many people will indeed assume Enumerators are /like/ Enumerables, but they are not.
However, the confusion is fed by the fact that IEnumerator contains the Reset method. Here is my idea of the most correct implementation. It leverages the implementation of IEnumerator.Reset()
A major difference between an Enumerable and and Enumerator is, that an Enumerable might be able to create several Enumerators simultaneously. This implementation puts a whole lot of work into making sure that this never happens for the EnumeratorEnumerable<T>
type. There are two EnumeratorEnumerableMode
s:
Blocking
(meaning that a second caller will simply wait till the first enumeration is completed)NonBlocking
(meaning that a second (concurrent) request for an enumerator simply throws an exception)
Note 1: 74 lines are implementation, 79 lines are testing code :)
Note 2: I didn't refer to any unit testing framework for SO convenience
using System;
using System.Diagnostics;
using System.Linq;
using System.Collections;
using System.Collections.Generic;
using System.Threading;
namespace EnumeratorTests
{
public enum EnumeratorEnumerableMode
{
NonBlocking,
Blocking,
}
public sealed class EnumeratorEnumerable<T> : IEnumerable<T>
{
#region LockingEnumWrapper
public sealed class LockingEnumWrapper : IEnumerator<T>
{
private static readonly HashSet<IEnumerator<T>> BusyTable = new HashSet<IEnumerator<T>>();
private readonly IEnumerator<T> _wrap;
internal LockingEnumWrapper(IEnumerator<T> wrap, EnumeratorEnumerableMode allowBlocking)
{
_wrap = wrap;
if (allowBlocking == EnumeratorEnumerableMode.Blocking)
Monitor.Enter(_wrap);
else if (!Monitor.TryEnter(_wrap))
throw new InvalidOperationException("Thread conflict accessing busy Enumerator") {Source = "LockingEnumWrapper"};
lock (BusyTable)
{
if (BusyTable.Contains(_wrap))
throw new LockRecursionException("Self lock (deadlock) conflict accessing busy Enumerator") { Source = "LockingEnumWrapper" };
BusyTable.Add(_wrap);
}
// always implicit Reset
_wrap.Reset();
}
#region Implementation of IDisposable and IEnumerator
public void Dispose()
{
lock (BusyTable)
BusyTable.Remove(_wrap);
Monitor.Exit(_wrap);
}
public bool MoveNext() { return _wrap.MoveNext(); }
public void Reset() { _wrap.Reset(); }
public T Current { get { return _wrap.Current; } }
object IEnumerator.Current { get { return Current; } }
#endregion
}
#endregion
private readonly IEnumerator<T> _enumerator;
private readonly EnumeratorEnumerableMode _allowBlocking;
public EnumeratorEnumerable(IEnumerator<T> e, EnumeratorEnumerableMode allowBlocking)
{
_enumerator = e;
_allowBlocking = allowBlocking;
}
private LockRecursionPolicy a;
public IEnumerator<T> GetEnumerator()
{
return new LockingEnumWrapper(_enumerator, _allowBlocking);
}
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
}
class TestClass
{
private static readonly string World = "hello world\n";
public static void Main(string[] args)
{
var master = World.GetEnumerator();
var nonblocking = new EnumeratorEnumerable<char>(master, EnumeratorEnumerableMode.NonBlocking);
var blocking = new EnumeratorEnumerable<char>(master, EnumeratorEnumerableMode.Blocking);
foreach (var c in nonblocking) Console.Write(c); // OK (implicit Reset())
foreach (var c in blocking) Console.Write(c); // OK (implicit Reset())
foreach (var c in nonblocking) Console.Write(c); // OK (implicit Reset())
foreach (var c in blocking) Console.Write(c); // OK (implicit Reset())
try
{
var willRaiseException = from c1 in nonblocking from c2 in nonblocking select new {c1, c2};
Console.WriteLine("Cartesian product: {0}", willRaiseException.Count()); // RAISE
}
catch (Exception e) { Console.WriteLine(e); }
foreach (var c in nonblocking) Console.Write(c); // OK (implicit Reset())
foreach (var c in blocking) Console.Write(c); // OK (implicit Reset())
try
{
var willSelfLock = from c1 in blocking from c2 in blocking select new { c1, c2 };
Console.WriteLine("Cartesian product: {0}", willSelfLock.Count()); // LOCK
}
catch (Exception e) { Console.WriteLine(e); }
// should not externally throw (exceptions on other threads reported to console)
if (ThreadConflictCombinations(blocking, nonblocking))
throw new InvalidOperationException("Should have thrown an exception on background thread");
if (ThreadConflictCombinations(nonblocking, nonblocking))
throw new InvalidOperationException("Should have thrown an exception on background thread");
if (ThreadConflictCombinations(nonblocking, blocking))
Console.WriteLine("Background thread timed out");
if (ThreadConflictCombinations(blocking, blocking))
Console.WriteLine("Background thread timed out");
Debug.Assert(true); // Must be reached
}
private static bool ThreadConflictCombinations(IEnumerable<char> main, IEnumerable<char> other)
{
try
{
using (main.GetEnumerator())
{
var bg = new Thread(o =>
{
try { other.GetEnumerator(); }
catch (Exception e) { Report(e); }
}) { Name = "background" };
bg.Start();
bool timedOut = !bg.Join(1000); // observe the thread waiting a full second for a lock (or throw the exception for nonblocking)
if (timedOut)
bg.Abort();
return timedOut;
}
} catch
{
throw new InvalidProgramException("Cannot be reached");
}
}
static private readonly object ConsoleSynch = new Object();
private static void Report(Exception e)
{
lock (ConsoleSynch)
Console.WriteLine("Thread:{0}\tException:{1}", Thread.CurrentThread.Name, e);
}
}
}
Note 3: I think the implementation of the thread locking (especially around BusyTable
) is quite ugly; However, I didn't want to resort to ReaderWriterLock(LockRecursionPolicy.NoRecursion)
and didn't want to assume .Net 4.0 for SpinLock

- 374,641
- 47
- 450
- 633
-
I like the idea. I agree that this is the only 'correct' implementation. But I think the Blocking mode is a bit overkill. Throwing on a concurrent enumeration should be good for most use cases. – Saintali May 09 '14 at 18:03
-
As Jason Watts said -- no, not directly.
If you really want to, you could loop through the IEnumerator<T>, putting the items into a List<T>, and return that, but I'm guessing that's not what you're looking to do.
The basic reason you can't go that direction (IEnumerator<T> to a IEnumerable<T>) is that IEnumerable<T> represents a set that can be enumerated, but IEnumerator<T> is a specific enumeratation over a set of items -- you can't turn the specific instance back into the thing that created it.

- 15,522
- 5
- 45
- 61
-
I was looking to do something like this in a Skip implementation, the built in Linq Skip is a complete Dog – Sam Saffron Jun 22 '09 at 22:07
-
See: http://stackoverflow.com/questions/1018407/what-is-the-most-elegant-way-to-get-a-set-of-items-by-index-from-a-collection/1025137#1025137 ... I was looking for a cleaner way to implement Skip (so its not called on IEnumerator), but it involved IEnumerable wrapping – Sam Saffron Jun 22 '09 at 22:12
Solution with use of Factory along with fixing cached IEnumerator
issue in JaredPar's answer allows to change the way of enumeration.
Consider a simple example: we want custom List<T>
wrapper that allow to enumerate in reverse order along with default enumeration. List<T>
already implements IEnumerator
for default enumeration, we only need to create IEnumerator
that enumerates in reverse order. (We won't use List<T>.AsEnumerable().Reverse()
because it enumerates the list twice)
public enum EnumerationType {
Default = 0,
Reverse
}
public class CustomList<T> : IEnumerable<T> {
private readonly List<T> list;
public CustomList(IEnumerable<T> list) => this.list = new List<T>(list);
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
//Default IEnumerable method will return default enumerator factory
public IEnumerator<T> GetEnumerator()
=> GetEnumerable(EnumerationType.Default).GetEnumerator();
public IEnumerable<T> GetEnumerable(EnumerationType enumerationType)
=> enumerationType switch {
EnumerationType.Default => new DefaultEnumeratorFactory(list),
EnumerationType.Reverse => new ReverseEnumeratorFactory(list)
};
//Simple implementation of reverse list enumerator
private class ReverseEnumerator : IEnumerator<T> {
private readonly List<T> list;
private int index;
internal ReverseEnumerator(List<T> list) {
this.list = list;
index = list.Count-1;
Current = default;
}
public void Dispose() { }
public bool MoveNext() {
if(index >= 0) {
Current = list[index];
index--;
return true;
}
Current = default;
return false;
}
public T Current { get; private set; }
object IEnumerator.Current => Current;
void IEnumerator.Reset() {
index = list.Count - 1;
Current = default;
}
}
private abstract class EnumeratorFactory : IEnumerable<T> {
protected readonly List<T> List;
protected EnumeratorFactory(List<T> list) => List = list;
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
public abstract IEnumerator<T> GetEnumerator();
}
private class DefaultEnumeratorFactory : EnumeratorFactory {
public DefaultEnumeratorFactory(List<T> list) : base(list) { }
//Default enumerator is already implemented in List<T>
public override IEnumerator<T> GetEnumerator() => List.GetEnumerator();
}
private class ReverseEnumeratorFactory : EnumeratorFactory {
public ReverseEnumeratorFactory(List<T> list) : base(list) { }
public override IEnumerator<T> GetEnumerator() => new ReverseEnumerator(List);
}
}

- 113
- 3
- 6
static class Helper
{
public static List<T> SaveRest<T>(this IEnumerator<T> enumerator)
{
var list = new List<T>();
while (enumerator.MoveNext())
{
list.Add(enumerator.Current);
}
return list;
}
public static ArrayList SaveRest(this IEnumerator enumerator)
{
var list = new ArrayList();
while (enumerator.MoveNext())
{
list.Add(enumerator.Current);
}
return list;
}
}

- 13,322
- 16
- 71
- 114
Nope, IEnumerator<> and IEnumerable<> are different beasts entirely.

- 1,086
- 5
- 13
-
1
-
10
-
7This not a useful answer and is misleading. The sole purpose of an IEnumerable is to provide an IEnumerator via the GetEnumerator method. So they are tightly related and the names are not "counterintuitive". An IEnumerable is something that can be enumerated, and so it must provide an enumerator to enumerate it. An enumerator is something that enumerates something. People have trouble understanding that because they let their eyes glaze over instead of focusing. – Jim Balter Nov 29 '18 at 08:16
This is a variant I have written... The specific is a little different. I wanted to do a MoveNext()
on an IEnumerable<T>
, check the result, and then roll everything in a new IEnumerator<T>
that was "complete" (so that included even the element of the IEnumerable<T>
I had already extracted)
// Simple IEnumerable<T> that "uses" an IEnumerator<T> that has
// already received a MoveNext(). "eats" the first MoveNext()
// received, then continues normally. For shortness, both IEnumerable<T>
// and IEnumerator<T> are implemented by the same class. Note that if a
// second call to GetEnumerator() is done, the "real" IEnumerator<T> will
// be returned, not this proxy implementation.
public class EnumerableFromStartedEnumerator<T> : IEnumerable<T>, IEnumerator<T>
{
public readonly IEnumerator<T> Enumerator;
public readonly IEnumerable<T> Enumerable;
// Received by creator. Return value of MoveNext() done by caller
protected bool FirstMoveNextSuccessful { get; set; }
// The Enumerator can be "used" only once, then a new enumerator
// can be requested by Enumerable.GetEnumerator()
// (default = false)
protected bool Used { get; set; }
// The first MoveNext() has been already done (default = false)
protected bool DoneMoveNext { get; set; }
public EnumerableFromStartedEnumerator(IEnumerator<T> enumerator, bool firstMoveNextSuccessful, IEnumerable<T> enumerable)
{
Enumerator = enumerator;
FirstMoveNextSuccessful = firstMoveNextSuccessful;
Enumerable = enumerable;
}
public IEnumerator<T> GetEnumerator()
{
if (Used)
{
return Enumerable.GetEnumerator();
}
Used = true;
return this;
}
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
public T Current
{
get
{
// There are various school of though on what should
// happens if called before the first MoveNext() or
// after a MoveNext() returns false. We follow the
// "return default(TInner)" school of thought for the
// before first MoveNext() and the "whatever the
// Enumerator wants" for the after a MoveNext() returns
// false
if (!DoneMoveNext)
{
return default(T);
}
return Enumerator.Current;
}
}
public void Dispose()
{
Enumerator.Dispose();
}
object IEnumerator.Current
{
get
{
return Current;
}
}
public bool MoveNext()
{
if (!DoneMoveNext)
{
DoneMoveNext = true;
return FirstMoveNextSuccessful;
}
return Enumerator.MoveNext();
}
public void Reset()
{
// This will 99% throw :-) Not our problem.
Enumerator.Reset();
// So it is improbable we will arrive here
DoneMoveNext = true;
}
}
Use:
var enumerable = someCollection<T>;
var enumerator = enumerable.GetEnumerator();
bool res = enumerator.MoveNext();
// do whatever you want with res/enumerator.Current
var enumerable2 = new EnumerableFromStartedEnumerator<T>(enumerator, res, enumerable);
Now, the first GetEnumerator()
that will be requested to enumerable2
will be given through the enumerator enumerator
. From the second onward the enumerable.GetEnumerator()
will be used.

- 109,618
- 12
- 197
- 280
The other answers here are ... strange. IEnumerable<T>
has just one method, GetEnumerator()
. And an IEnumerable<T>
must implement IEnumerable
, which also has just one method, GetEnumerator()
(the difference being that one is generic on T
and the other is not). So it should be clear how to turn an IEnumerator<T>
into an IEnumerable<T>
:
// using modern expression-body syntax
public class IEnumeratorToIEnumerable<T> : IEnumerable<T>
{
private readonly IEnumerator<T> Enumerator;
public IEnumeratorToIEnumerable(IEnumerator<T> enumerator) =>
Enumerator = enumerator;
public IEnumerator<T> GetEnumerator() => Enumerator;
IEnumerator IEnumerable.GetEnumerator() => Enumerator;
}
foreach (var foo in new IEnumeratorToIEnumerable<Foo>(fooEnumerator))
DoSomethingWith(foo);
// and you can also do:
var fooEnumerable = new IEnumeratorToIEnumerable<Foo>(fooEnumerator);
foreach (var foo in fooEnumerable)
DoSomethingWith(foo);
// Some IEnumerators automatically repeat after MoveNext() returns false,
// in which case this is a no-op, but generally it's required.
fooEnumerator.Reset();
foreach (var foo in fooEnumerable)
DoSomethingElseWith(foo);
However, none of this should be needed because it's unusual to have an IEnumerator<T>
that doesn't come with an IEnumerable<T>
that returns an instance of it from its GetEnumerator
method. If you're writing your own IEnumerator<T>
, you should certainly provide the IEnumerable<T>
. And really it's the other way around ... an IEnumerator<T>
is intended to be a private class that iterates over instances of a public class that implements IEnumerable<T>
.

- 16,163
- 3
- 43
- 66
-
@sehe I actually didn't initially recognize the accepted answer as the same because it was couched in "Fake" and a lot of other nonsense like copying the result of the enumerator into a List instead of simply using Reset. And I'm not at all "enthusiastic about this approach" ... as my final paragraph makes clear, it's generally wrongheaded to take an arbitrary IEnumerator and wrap it in an IEnumerable ... one almost always has an IEnumerable that provides its own (private) IEnumerator. – Jim Balter Nov 29 '18 at 09:19
-
The thing is, few people seem to understand the relationship between the two interfaces ... even now in 2018, let alone back in 2009. So I'm hoping that this helps. – Jim Balter Nov 29 '18 at 09:21
-
*not even a yield statement in sight* -- `yield return` is certainly convenient, but it obscures people's understanding. When you write an `IEnumerable` method that uses `yield return`, the compiler actually generates *two* anonymous classes for you ... an IEnumerator, and an IEnumerable that returns an instance of the former. Then your method simply returns an instance of the IEnumerable class. So the people writing these `yield return` loops in their answers seem to have no idea how much overhead they've added. – Jim Balter Nov 29 '18 at 09:23
-
1@JimBalter Sometimes overhead can be deceiving. If I run your solution and my solution simply count from 1 to 100000. You solution uses 80% of the time mine uses. If I on the other hand runs the accepted answer here https://stackoverflow.com/questions/13001578/i-need-a-slow-c-sharp-function then at some point my solution runs faster than your solution. The cross over is in the area of an input value of 2000 on my machine – Rune FS Nov 29 '18 at 19:21
-
My enthusiasm was based on the missing bits of style (e.g. if you want to point out the relation between these interfaces, you cleverly avoided the idiomatic explicit interface implementation). – sehe Nov 29 '18 at 22:25
-
I have no idea what code is being run in the above mentioned test, but the results are implausible (and the link is completely irrelevant). And the other comment is obscure ... I do have an explicit interface implementation: `IEnumerator IEnumerable.GetEnumerator() => Enumerator;` – Jim Balter Nov 29 '18 at 23:20
-
@JimBalter it's actually pretty straight forward to verify your claim that "the results are implausible" you have a link to the actual code I ran and you can simply redo the test. Of course with different hardware, the cutover point will be different but use 2000 as a starting point and work your way up – Rune FS Aug 26 '19 at 18:59