简体   繁体   中英

Cannot cast from generic to get LINQ where clause

OK so I've written the following function:

private IQueryable<LogEntry> SelectAll<T>(IEnumerable<LogEntry> logEntries, List<Expression<Func<LogEntry, bool>>> whereClause)
{
    var selectAllQuery = from l in logEntries select l;
    if (whereClause != null)
    {
        foreach (Expression<Func<LogEntry, bool>> whereStatement in whereClause)
        {
            selectAllQuery = selectAllQuery.Where(whereClause);
        }
    }
}

But it won't compile. It throws an error when it tries to return something at "selectAllQuery" as follows:

System.Collections.Generic.IEnumerable' does not contain a definition for 'Where' and the best extension method overload System.Linq.Enumerable.Where(System.Collections.Generic.IEnumerable, System.Func)' has some invalid arguments

I've tried casting this every which way I can think of to no avail. In the above code, running the initial select statement returns selectAllQuery of type System.Linq.Enumerable.WhereSelectEnumerableIterator<LogEntry,LogEntry>

Clearly I'm missing something fundamental about LINQ. But what?

Cheers.

The problem is that selectAllQuery is an IEnumerable<LogEntry> and you need it to be an IQueryable<LogEntry> in order to use expression trees. Try just changing the first line of the method:

var selectAllQuery = logEntries.AsQueryable();

Alternatively, compile the predicates as you go to get them into delegate form:

foreach (Expression<Func<LogEntry, bool>> whereStatement in whereClause)
{
    selectAllQuery = selectAllQuery.Where(whereStatement.Compile());
}

EDIT: Okay, the problems weren't just because of Queryable , but because of your naming. Let's look at this foreach statement:

foreach (Expression<Func<LogEntry, bool>> whereStatement in whereClause)
{
    selectAllQuery = selectAllQuery.Where(whereClause);
}

You're not using whereStatement anywhere in the body of the loop. You're trying to call Where with the entire list of clauses on each iteration. This is where better naming would help. Try this, for example:

private IQueryable<LogEntry> SelectAll<T>(IEnumerable<LogEntry> logEntries,
    List<Expression<Func<LogEntry, bool>>> filters)
{
    var selectAllQuery = logEntries.AsQueryable();
    if (filters != null)
    {
        foreach (var filter in filters)
        {
            selectAllQuery = selectAllQuery.Where(filter);
        }
    }
    return selectAllQuery;
}

Because the parameter is now pluralized, it would look obviously wrong as the argument to the Where method - whereas the difference between whereStatement and whereClause isn't at all obvious as the former being singular and the latter being plural.

Some times these kind of errors would get away with simple solution like adding System.Linq to the project...and referring it in the class file. Very sad that VS IDE does not help us to resolve as part of the refactor menu...

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM