С реальными примерами и их использования, может кто-то пожалуйста, помогите мне понять:Func против действий против Predicate
- Когда нам нужен Func делегат?
- Когда нам нужно делегировать действия?
- Когда нам нужен делегат Predicates?
С реальными примерами и их использования, может кто-то пожалуйста, помогите мне понять:Func против действий против Predicate
Разница между Func
и Action
, хотите ли Вы просто делегат для возврата значения (используйте Func
) или нет (используйте Action
).
Func
, вероятно, наиболее часто используемых в LINQ - например, в прогнозах:
list.Select(x => x.SomeProperty)
или фильтрации:
list.Where(x => x.SomeValue == someOtherValue)
или клавиша выбора:
list.Join(otherList, x => x.FirstKey, y => y.SecondKey, ...)
Action
чаще используется для таких вещей, как : выполнить n для каждого элемента в списке. Я использую это реже, чем Func
, хотя I do иногда используют версию без параметров для таких вещей, как Control.BeginInvoke
и Dispatcher.BeginInvoke
.
Predicate
- только специальный корпус Func<T, bool>
действительно, представленный перед всеми Func
, и большинство делегатов Action
пришли. Я подозреваю, что если бы мы уже Func
и Action
в их различных формах, Predicate
бы не был введен ... хотя делает придает определенное значение для использования делегата, в то время как Func
и Action
используется для широко разрозненные цели.
Predicate
в основном используется в List<T>
для таких методов, как FindAll
и RemoveAll
.
Мне нравится видеть «Predicate» в сигнатуре функции. Он иллюстрирует, что переданный метод принимает решение, а не просто возвращает код успеха или другой тип 'bool'. –
Есть ли какая-либо директива о том, следует ли предпочитать 'Predicate
@ Ron: Да, это в значительной степени то, о чем я говорил в своем предпоследнем абзаце. –
Func - Если требуется делегат для функции, которая может или не может принимать параметры и возвращает значение. Наиболее распространенный пример будет выбрать из LINQ:
var result = someCollection.Select(x => new { x.Name, x.Address });
Действия - Если вы хотите, делегат функции, которая может или не может принимать параметры и не возвращает значение. Я использую их часто для анонимных обработчиков событий:
button1.Click += (sender, e) => { /* Do Some Work */ }
Predicate - Если вы хотите специализированный вариант Func который берет оценивает значение от набора критериев и возвращает логический результат (правда, на матч, false в противном случае).
Опять же, они используются в LINQ довольно часто для таких вещей, как Где:
var filteredResults =
someCollection.Where(x => x.someCriteriaHolder == someCriteria);
Я просто проверил и получается, что LINQ не использует Предикаты. Не знаю, почему они приняли это решение ... но теоретически это все еще ситуация, в которой будет существовать Предикат.
Я знаю, что это старо, но предикат не использовался LINQ, потому что он предшествует Func и Action, которые мы знаем сегодня, а последние два могут быть использованы для достижения того же результата в гораздо лучшем виде. – gparent
@gparent, почему это лучше? Я считаю, что читаемость лучше, если вместо 'Func' или' Action' используются значащие имена делегатов. – Sam
Это зависит от того, как вы используете делегатов, но иногда это имя не так важно и необходимость создавать функции и переменные только для одного использования для меня уменьшает читаемость. – gparent
Действие является делегатом (указателем) к методу, который принимает ноль, один или несколько входных параметров, но ничего не возвращает.
Func является делегатом (указателем) к методу, который принимает ноль, один или несколько входных параметров и возвращает значение (или ссылку).
Predicate - особый вид Func, который часто используется для сравнения.
Хотя широко используется с Linq, Action и Func, понятия логически независимы от Linq. C++ уже содержал базовую концепцию в виде типизированных указателей функций.
Вот небольшой пример действий и Func без использования Linq:
class Program
{
static void Main(string[] args)
{
Action<int> myAction = new Action<int>(DoSomething);
myAction(123); // Prints out "123"
// can be also called as myAction.Invoke(123);
Func<int, double> myFunc = new Func<int, double>(CalculateSomething);
Console.WriteLine(myFunc(5)); // Prints out "2.5"
}
static void DoSomething(int i)
{
Console.WriteLine(i);
}
static double CalculateSomething(int i)
{
return (double)i/2;
}
}
Даже если это дубликат имеет более тщательный обслуживаемого ответ – reggaeguitar
@reggaeguitar Что интересно, что оба принятого ответа от Jon Skeet – rafid059