Метод C # принимает предикат - это выглядит нормально? - PullRequest
8 голосов
/ 05 февраля 2010

Мне нужен метод, который имеет следующий API:

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

Будет ли что-то подобное работать?

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

Если это так, я смогу указать более сложные предикаты, такие как ( псевдокод ):

myRepository.GetUsers(u => u.CreatedDate is upto 14 days old);

Ответы [ 3 ]

19 голосов
/ 05 февраля 2010

Это выглядит абсолютно нормально. Однако, если вы хотите использовать предикат с чем-то вроде LINQ to SQL, вы должны использовать:

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

Это означает, что лямбда-выражение будет преобразовано в дерево выражений вместо делегата - и это дерево выражений затем можно будет преобразовать в SQL.

3 голосов
/ 05 февраля 2010

Да, это будет работать.

То, что вы говорите компилятору, - это то, что вы собираетесь передать функцию, которая работает с User объектом и возвращает bool - как выглядит функция, полностью зависит от вас. Вы можете получить довольно сложные вложенные объекты, используя ors (||) и ands (&&), но если вам становится слишком трудно увидеть, что делает предикат, вам, вероятно, следует рассмотреть возможность рефакторинга.

Но в основном любая лямбда, которая принимает, например, u в качестве User объекта и превращает его в выражение, возвращающее bool, будет работать.

2 голосов
/ 05 февраля 2010

Один совет: вы можете использовать Predicate вместо Func , что немного понятнее (Predicate встроен в .net 3.5, систему пространств имен).

...