Когда вы используете + = или - = при типах делегата, это просто вызывает Delegate.Combine
и Delegate.Remove
.
Важная вещь о многоадресных делегатах заключается в том, что возвращаемое значение для всех, кроме последнего выполненного делегата , игнорируется. Все они выполняются (если не генерируется исключение), но используется только последнее возвращаемое значение.
Для предикатов вы можете сделать что-то вроде:
public static Func<T, bool> And<T>(params Func<T, bool>[] predicates)
{
return t => predicates.All(predicate => predicate(t));
}
public static Func<T, bool> Or<T>(params Func<T, bool>[] predicates)
{
return t => predicates.Any(predicate => predicate(t));
}
Вы бы тогда сделали:
Func<string, bool> predicate = And<string>(
t => t.Length > 10,
t => t.Length < 20);
РЕДАКТИРОВАТЬ: Вот более общее решение, которое довольно забавно, если немного странно ...
public static Func<TInput, TOuput> Combine<TInput, TOutput>
(Func<TOutput, TOutput, TOutput> aggregator,
params Func<TInput, TOuput>[] delegates) {
// delegates[0] provides the initial value
return t => delegates.Skip(1).Aggregate(delegates[0](t), aggregator);
}
Так вы могли бы затем реализовать А как:
public static Func<T, bool> And<T>(params Func<T, bool>[] predicates) {
return Combine<T, bool>((x, y) => x && y, predicates);
}
(лично я предпочитаю это использовать GetInvocationList()
, потому что в итоге вы получите предикат, который вы можете передать другим битам LINQ и т. Д.)