C# method accepting a predicate - does this look ok?
Asked Answered
J

3

9

I'd like a method that has the following API:

//get all users with a role of admin
var users = myRepository.GetUsers(u => u.Role == Role.Admin);

Will something like this work?

IList<User> GetUsers(Func<User, bool> predicate)
{            
  var users = GetAllUsers();
  return users.Where(predicate).ToList();                                                          
} 

If so, wil I be able to specify more complex predicates such as (pseudocode):

myRepository.GetUsers(u => u.CreatedDate is upto 14 days old);
Joost answered 5/2, 2010 at 11:43 Comment(3)
Why don't you want to return an IEnumerable of users?Burglarious
Is an IEnumerable preferable because it is more flexible?Joost
An IList is an IEnumerable, so an IEnumerable is going to be less flexible. I think the comment may have been directed toward the possible unneeded call to ToList()?Boabdil
C
20

That looks absolutely fine. However, if you want to use the predicate with something like LINQ to SQL, you'd want to use:

IList<User> GetUsers(Expression<Func<User, bool>> predicate)

That means the lambda expression will be converted into an expression tree instead of a delegate - and that expression tree can then be converted into SQL.

Cerda answered 5/2, 2010 at 11:46 Comment(3)
Really appreciate your response. ThanksJoost
+1 That explanation clarified my understanding of LINQ by a couple percent. Much obliged. :)Reni
Thanks much for this answer. I'm using LINQ to SQL, and using just Func<User,bool> throws an OutOfMemory exception. This works perfect.Disjoint
T
3

Yes, this will work.

What you're telling the compiler is that you're going to pass a function that works on a User object, and returns a bool - what the function looks like is entirely up to you. You can get pretty complex nesting stuff using ors (||) and ands (&&) too, but if it gets too hard to see what the predicate is doing, you should probably consider refactoring.

But basically any lambda that takes for example u as a User object, and turns it into an expression that returns bool will work.

Typhogenic answered 5/2, 2010 at 11:44 Comment(0)
T
2

One tip: you can use Predicate<T> instead of Func<T, bool>, which is a little clearer (Predicate<T> is built in to .net 3.5, namespace System).

Triecious answered 5/2, 2010 at 11:47 Comment(2)
Predicate<T> was actually in .NET 2.0, but Func<T,bool> tends to be used in LINQ - partly because some methods have Func<T,int,bool>.Cerda
Ah I forgot that it was in 2.0; could you give me a few examples of methods using Func<T, int, bool>? ThanksTriecious

© 2022 - 2024 — McMap. All rights reserved.