shamp00
shamp00

Reputation: 11326

How can I tell if an IEnumerable has been evaluated?

Can I know whether the deferred evaluation of an IEnumerable (or IQueryable) has already happened? That is, whether GetEnumerator().MoveNext() has ever been called. Is there a way?

How would I code HasBeenEvaluated() in the following example?

private void Example()
{
    IEnumerable<Thing> things = _Repository.GetObjects<Thing>();

    bool x = HasBeenEvaluated(things); // returns false

    foreach (var thing in things)
    {
         x = HasBeenEvaluated(things); // returns true
    }
}

Upvotes: 0

Views: 391

Answers (3)

Scott Nimrod
Scott Nimrod

Reputation: 11570

Perhaps you can inherit from the type and add a method to it to return the state.

In this case you would add a property to this class that would reflect the state of an operation being called.

public class StatefulThings : IEnumerable<Thing>
{
  bool _moveNextExecuted = false;

  public override bool MoveNext()
   {
      // Perform next pointer

      // Set state of hasBeenEnumerated in here...
      _moveNextExecuted  = true;
   }
}

Upvotes: 1

Servy
Servy

Reputation: 203847

You can create a wrapper for an IEnumerable that, when iterated, flips a boolean to indicate that it has been iterated:

//TODO come up with a better name
public class Foo<T> : IEnumerable<T>
{
    private IEnumerable<T> wrapped;
    public Foo(IEnumerable<T> wrapped)
    {
        this.wrapped = wrapped;
    }
    public bool HasBeenIterated { get; private set; }
    public IEnumerator<T> GetEnumerator()
    {
        HasBeenIterated = true;
        foreach (var item in wrapped)
            yield return item;
    }

    IEnumerator IEnumerable.GetEnumerator()
    {
        return GetEnumerator();
    }
}

Your method can now become:

private void Example()
{
    var things = new Foo<Thing>(_Repository.GetObjects<Thing>());

    bool x = things.HasBeenIterated;//is false

    foreach (var thing in things)
    {
        x = things.HasBeenIterated;//is true
    }
}

Upvotes: 1

Jeppe Stig Nielsen
Jeppe Stig Nielsen

Reputation: 62002

In general, no. The interface IEnumerable<> does not support that.

Also, if you have an IEnumerator<>, you cannot tell in general if MoveNext() was ever called.

Sometimes an IEnumerator<> will support the Reset() method, but this is not what you ask. Many enumerators will just throw an exception when you try to Reset().

Upvotes: 1

Related Questions