styfle
styfle

Reputation: 24610

Pass OrderBy lambda function as a parameter

Let's say I have a model name User with a couple properties Name and Age. I would like to know the type of a lambda function that accepts a User and returns one of those properties such that lambda function could be used in the OrderBy method.

using System;
using System.Linq;

public class User {
    public string Name { get; set; }
    public int Age { get; set; }
}

public class MainClass {
    static void Main() {

        var users = new User[] {
            new User { Name = "David", Age = 16 },
            new User { Name = "Charlie", Age = 29 },
            new User { Name = "Alice", Age = 15 },
            new User { Name = "Deanna", Age = 27 },
        }.AsQueryable();

        Write(GetAdultsBy(users, u => u.Name));
        Write(GetAdultsBy(users, u => u.Age));
    }

    private static IQueryable<User> GetAdultsBy(IQueryable<User> users, Func<User, object> order) {
        return users
            .Where(u => u.Age > 18)
            .OrderBy(order); // FAIL in ORDER BY
    }

    private static void Write(IQueryable<User> query) {
        var names = query.Select(u => u.Name);
        Console.WriteLine(string.Join(", ", names));
    }
}

I get the following error when running this code:

/tmp/997240133/main.cs(26,14): error CS0266: Cannot implicitly convert type System.Linq.IOrderedEnumerable<User>' toSystem.Linq.IQueryable'. An explicit conversion exists (are you missing a cast?)

But explicitly ordering works just fine with Write(users.OrderBy(u => u.Age)); as one might expect.

So what should be the type for Func<User, object> order parameter?

Upvotes: 0

Views: 1792

Answers (2)

Dylan Nicholson
Dylan Nicholson

Reputation: 1368

You'll need to define private static IQueryable<User> GetAdultsBy() as a generic function to match how OrderBy< > is defined. Specifically:

private static IOrderedQueryable<User> GetAdultsBy<T>(
    IQueryable<User> source,
    Expression<Func<User, T>> order)

Upvotes: 2

SLaks
SLaks

Reputation: 887453

To work with IQueryable, you need to pass expression trees (Expression<Func<...>>).

The expression tree encodes the content of the lambda at runtime, allowing it to be translated to SQL.

Upvotes: 1

Related Questions