IEnumerable <T> representing the "remainder" of the IEnumerable <T> sequence
If I go through IEnumerable<T>, is there a way to get a new IEnumerable<T>one representing the remaining items after the current one.
For example, I would like to write an extension method IEnumerator<T>.Remaining():
IEnumerable<int> sequence = ...
IEnumerator<int> enumerator = sequence.GetEnumerator();
if (enumerator.MoveNext() && enumerator.MoveNext()) {
IEnumerable<int> rest = enumerator.Remaining();
// 'rest' would contain elements in 'sequence' start at the 3rd element
}
I am thinking of a collection of a kind of singly linked list, so there must be a way to present any remaining elements, right? I see no way to make it exposed to IEnumerable<T>or IEnumerator<T>, therefore, perhaps this is incompatible with the concept of a potentially unlimited, non-deterministic sequence of elements.
IEnumerator<T>, IEnumerable<T> ( ), .
( , , , ):
public static IEnumerable<T> Remaining<T>( this IEnumerator<T> value ) {
while( value.MoveNext() ) {
yield return value.Current;
}
}
( , IEnumerable):
public static IEnumerable<T> Remaining<T>( this IEnumerator<T> value ) {
List<T> list = new List<T>();
while( value.MoveNext() ) list.Add( value.Current );
return list;
}
IEnumerator<T> IEnumerable<T>, , , , .
, , , " " .
-, , , , , . , .
... . , , , , .
... , , , Skip Take , , . , , , , .
. IEnumerator<T> , , .
, . , 2 ( 1) , , , , .
, :
var enumerable = enumerator.Remaining();
var enumerator1 = enumerable.GetEnumerator();
var enumerator2 = enumerable.GetEnumerator();
enumerator1.MoveNext();
enumerator2.MoveNext();
<-- at this point, enumerable is no longer used, and the first (head) element
of the enumerable is no longer needed (there no way to get to it)
it can be garbage collected.
, , , , , .
, . :
using System;
using System.Collections.Generic;
using System.Collections;
namespace SO2829956
{
public class EnumeratorEnumerable<T> : IEnumerable<T>
{
private class Node
{
public T Value;
public Node Next;
}
private class Enumerator : IEnumerator<T>
{
private IEnumerator<T> _Enumerator;
private Node _Current;
public Enumerator(IEnumerator<T> enumerator, Node headElement)
{
_Enumerator = enumerator;
_Current = headElement;
}
public T Current
{
get { return _Current.Value; }
}
public void Dispose()
{
_Enumerator.Dispose();
}
object IEnumerator.Current
{
get { return Current; }
}
public bool MoveNext()
{
if (_Current.Next != null)
{
_Current = _Current.Next;
return true;
}
else if (_Enumerator.MoveNext())
{
_Current.Next = new Node
{
Value = _Enumerator.Current
};
_Current = _Current.Next;
return true;
}
else
{
_Enumerator.Dispose();
return false;
}
}
public void Reset()
{
throw new NotImplementedException();
}
}
private IEnumerator<T> _Enumerator;
private Node _FirstElement;
public EnumeratorEnumerable(IEnumerator<T> enumerator)
{
_Enumerator = enumerator;
_FirstElement = new Node
{
Next = null,
Value = enumerator.Current
};
}
public IEnumerator<T> GetEnumerator()
{
return new Enumerator(_Enumerator, _FirstElement);
}
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
}
public static class EnumeratorExtensions
{
public static IEnumerable<T> Remaining<T>(
this IEnumerator<T> enumerator)
{
return new EnumeratorEnumerable<T>(enumerator);
}
}
class Program
{
static void Main(string[] args)
{
List<int> values = new List<int> { 1, 2, 3, 4, 5 };
IEnumerator<int> enumerator = values.GetEnumerator();
enumerator.MoveNext();
enumerator.MoveNext();
var enumerable = enumerator.Remaining();
foreach (var i in enumerable)
Console.Out.WriteLine(i);
foreach (var i in enumerable)
Console.Out.WriteLine(i);
}
}
}
:
3
4
5
3
4
5
- foreach IEnumerator<T> , - :
public struct WrappedEnumerator<T>
{
T myEnumerator;
public T GetEnumerator() { return myEnumerator; }
public WrappedEnumerator(T theEnumerator) { myEnumerator = theEnumerator; }
}
public static class AsForEachHelper
{
static public WrappedEnumerator<IEnumerator<T>> AsForEach<T>(this IEnumerator<T> theEnumerator)
{ return new WrappedEnumerator<IEnumerator<T>>(theEnumerator);}
static public WrappedEnumerator<System.Collections.IEnumerator> AsForEach(this System.Collections.IEnumerator theEnumerator)
{ return new WrappedEnumerator<System.Collections.IEnumerator>(theEnumerator); }
[Obsolete("Structs implementing IEnumerator<T> should be boxed before use", false)]
static public WrappedEnumerator<System.Collections.IEnumerator> AsForEach<T>(this T theEnumerator) where T : struct, System.Collections.IEnumerator
{ return new WrappedEnumerator<System.Collections.IEnumerator>(theEnumerator) ; }
}
foo - IEnumerator, IEnumerator<T> , , foreach (whatever in foo.AsForEach()); , , , . , , myEnumerator Foo=someList.GetEnumerator(), someList List<T>, myEnumerator , WrappedEnumerator<T>. - , Obsolete ( false), AsForEach unboxed , , AsForEach struct-type , .