score:54

Accepted answer

The existing Linq extension methods work on objects that implement IEnumerable<T>. I assume your object implements the non-generic IEnumerable interface. In that case you can use the Cast<T> extension method to get a generic IEnumerable<T> wrapper. For instance, if the elements are of type int :

var wrapper = myObject.Cast<int>();

You can now use Linq on the wrapper

score:0

No you can't. All LINQ methods are extensions methods for the IEnumerable<T> interface.

So you'll have to implement IEnumerable<T> to use LINQ with your own collections.

score:0

Use a helper class:

namespace System.Linq {
  public sealed class EnumerableWrapper<T> : IEnumerable<T> {
    readonly IEnumerator<T> Enumerator;
    public EnumerableWrapper(IEnumerator<T> enumerator) => Enumerator = enumerator;
    public IEnumerator<T> GetEnumerator() => Enumerator;
    Collections.IEnumerator Collections.IEnumerable.GetEnumerator() => GetEnumerator();
  }
}

Then use Linq on a new instance of EnumerableWrapper

score:7

Not directly. You could fairly easily write a SingleShotEnumerable<T> though:

 public sealed class SingleShotEnumerable<T> : IEnumerable<T>
 {
     private IEnumerator<T> enumerator;

     public SingleShotEnumerable(IEnumerator<T> enumerator)
     {
         if (enumerator == null)
         {
             throw new ArgumentNullException("enumerator");
         }
         this.enumerator = enumerator;
     }

     public IEnumerator<T> GetEnumerator()
     {
         if (enumerator == null)
         {
             throw new InvalidOperationException
                 ("GetEnumerator can only be called once");
         }
         var ret = enumerator;
         enumerator = null;
         return ret;
     }

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

This is assuming you actually have an IEnumerator<T>. If you just have IEnumerator, you could write something similar only implementing IEnumerable, then use Cast or OfType to get to an IEnumerable<T>.

(Note: this isn't thread-safe. You could make it so with locks if you really wanted.)

You could then do:

 var filtered = from person in new SingleShotEnumerable<Person>(personEnumerator)
                where person.Age > 18
                select person.Name;

... but you couldn't use the query twice.

How have you got into the strange situation of only having an IEnumerator<T> anyway? That's quite rare. See if you can design your way around that to avoid having to do something like the above, which is quite fragile.

(An alternative would be to "drain" the IEnumerator<T> to a List<T> or something similar, but that has problems dealing with large or potentially infinite sequences.)


Related Query

More Query from same tag