You can't move backward or refer to a random index in IEnumerable<> object - the collection can be created in various ways including randomness and there's no magic way of getting n-th element without iterating over all previous elements.
The common usage of IEnumerable<>
is:
foreach (var value in GetValues())
{
Console.WriteLine(value);
}
which translates to something like:
using (var enumerator = GetValues().GetEnumerator())
{
while(enumerator.MoveNext())
{
var value = enumerator.Current;
Console.WriteLine(value);
}
}
If you want to refer to the specific index, you need to have an IList<> object - you can create one by calling
.ToList()
The .ToArray()
mentioned in another response is actually a little bit slower and calls .ToList()
internally before making it into an array (because array need to have fixed size and we don't know the number of elements in IEnumerable until we enumerate to the end)
You can create your own proxy, lazy class which will enumerate the enumerator only when needed
public static IEnumerable<int> GetValues()
{
for (int i = 0; i < 10; i++)
{
Console.WriteLine("yielding " + i);
yield return i;
}
}
class LazyList<T>
{
IEnumerator<T> enumerator;
IList<T> list;
public LazyList(IEnumerable<T> enumerable)
{
enumerator = enumerable.GetEnumerator();
list = new List<T>();
}
public T this[int index]
{
get
{
while (list.Count <= index && enumerator.MoveNext())
{
list.Add(enumerator.Current);
}
return list[index];
}
}
}
static void Main(string[] args)
{
var lazy = new LazyList<int>(GetValues());
Console.WriteLine(lazy[0]);
Console.WriteLine(lazy[4]);
Console.WriteLine(lazy[2]);
Console.WriteLine(lazy[1]);
Console.WriteLine(lazy[7]);
Console.WriteLine(lazy[9]);
Console.WriteLine(lazy[6]);
Console.Read();
}
will produce:
yielding 0
0
yielding 1
yielding 2
yielding 3
yielding 4
4
2
1
yielding 5
yielding 6
yielding 7
7
yielding 8
yielding 9
9
6