score:3

The IQueryable most likely does have a reference to the underlying collection (possibly through a number of layers of indirection), but it won't be publicly exposed, so you won't be able to access it, at least not in any way that I would consider reasonable and not a very, very messy hack.

score:0

No, each query is executed independently, and all you're left with is the result set of the query itself. There is nothing within the memory object that contains the original collection nor any accessible reference to the original collection. Considering that the original collection may now be null or out of scope, this would be dangerous to allow even. If you need to the original collection, you will need to keep it in scope until you're completely finished with it.

score:0

This is cheating, but maybe it makes sense in your context:

interface IReferencedQueryable<T> : IQueryable<T>
{
    IEnumerable<T> Source { get; }
}

static class IReferencedQueryableExtensions
{
    public static IReferencedQueryable<T> AsReferencedQueryable<T>(
        this IEnumerable<T> source)
    {
        return ReferencedQueryable.From(source);
    }

    class ReferencedQueryable<T> : IReferencedQueryable<T>
    {
        public IEnumerable<T> Source { get; private set; }

        ReferencedQueryable(IEnumerable<T> source)
        {
            Source = source;
        }

        static IReferencedQueryable<T> From(IEnumerable<T> source)
        {
            return new ReferencedQueryable(source);
        }

        // all the IQueryable members would be 
        // implemented through AsQueryable()
        // ...
    }

    public static IReferencedQueryable<T> Where<T>(
        this IReferencedQueryable<T> source, 
        Expression<Func<T, bool>> predicate)
    {
        return ReferencedQueryable.From(
            ((IQueryable<T>)source).Where(predicate));
    }

    // do the same for all the Linq extension methos you want to support
}

You would use it like this:

T[] itemArray = // initialized values
var itemQuery = itemArray.AsReferencedQueryable()
                         .Where(*/some query*/)
                         .Skip(5)
                         .Etc() ...

When you need your source sequence you can access it through the Source member, possibly through an as cast.

var s = itemQuery.Source;

Related Articles