Возможности использования Func <> для улучшения удобочитаемости кода
Сегодня я наконец "получил" Func<>
делегат и увидел, как я могу использовать его, чтобы сделать некоторые из моих менее читаемых запросов LINQ (надеюсь) более читаемый.
Здесь простой пример кода, иллюстрирующий выше, в (очень) тривиальном примере
List<int> numbers = new List<int> { 1, 5, 6, 3, 8, 7, 9, 2, 3, 4, 5, 6, };
// To get the count of those that are less than four we might write:
int lessThanFourCount = numbers.Where(n => n < 4).Count();
// But this can also be written as:
Func<int, bool> lessThanFour = n => n < 4;
int lessThanFourCount = numbers.Where(lessThanFour).Count();
Может ли кто-нибудь еще приводить примеры сценариев, в которых они используют Func<>
?
(Обратите внимание, что я не буду защищать использование Func<>
в сценарии так же просто, как показано выше, это просто пример, который, надеюсь, делает функциональность Func<>
ясной.)
Ответы
Ответ 1
Я предполагаю, что в этом будет только точка, если вы собираетесь повторно использовать рассматриваемый Func в нескольких местах (и это связано с более чем тривиальной логикой). В противном случае использование стандартного способа кажется намного лучше и прекрасно читаемым.
Ответ 2
Это только более читаемо/полезно, когда/если вы повторно используете его.
Более интересная Lambda для прохождения и futz с, будет Expression<Func<int,bool>>
, поскольку вы все равно можете вызвать ее, когда захотите, но вы также можете полностью ее разобрать и поработать с ней.
Его... ну... мертвый сексуальный.
Ответ 3
Я использую делегаты Func и Action для общей обработки исключений. Я часто нахожу, что я строю один и тот же блок try-catch снова и снова, потому что я держу их как можно короче. Делегирование и действие могут уменьшить дублирование кода try-catch.
Действительно простой пример:
...
DoSomethingPotentiallyBad((x) => x * 2, 0); // both delegates do
DoSomethingPotentiallyBad((x) => 2 / x, 0); // something different ...
...
static int DoSomethingPotentiallyBad(Func<int, int> function, int input)
{
// ... but get exception handled all the same way
try
{
return function.Invoke(input);
}
catch
{
Console.WriteLine("Evaluation failed! Return 0.");
return 0;
}
}
Этот пример очень искусственный и не показывает его силу. Но предположил, что у вас есть что-то вроде операций с базами данных, и вы хотите повторить каждую операцию сбойной базы данных 5 раз (что связано с использованием флагов, цикла finally-block и while) и хотите, чтобы один и тот же журнал приложений использовался, тогда у вас есть только один место для размещения блока try-catch: это метод, который принимает аргумент Func или Action в качестве аргумента. Код, который обрабатывает бизнес-логику, почти свободен от этих блоков try-catch и, следовательно, более читабельен.
Для более подробного примера и более подробного описания смотрите:
Политика действий
Ответ 4
Обычно я делаю это только тогда, когда хочу повторно использовать делегат. В противном случае, не часто.
Ответ 5
Как насчет принятия параметра Func<>
в ваших собственных методах, когда это необходимо, чтобы сделать их более гибкими и расширяемыми? Например:
public static string ToDelimitedString<T>(
this IEnumerable<T> source, Func<T, string> converter, string separator)
{
// error checking removed for readability
StringBuilder sb = new StringBuilder();
foreach (T item in source)
{
sb.Append(converter(item));
sb.Append(separator);
}
return (sb.Length > 0) ?
sb.ToString(0, sb.Length - separator.Length) : string.Empty;
}
// ...
List<int> e1 = new List<int> { 1, 2, 3 };
// convert to "2|4|6"
string s1 = e1.ToDelimitedString(x => (x * 2).ToString(), "|");
DateTime[] e2 = new DateTime[]
{ DateTime.Now.AddDays(-100), DateTime.Now, DateTime.Now.AddDays(100) };
// convert to "Tuesday, Thursday, Saturday"
string s2 = e2.ToDelimitedString(x => x.DayOfWeek.ToString(), ", ");
List<MyCustomType> e3 = new List<MyCustomType>
{ new MyCustomType("x"), new MyCustomType("y"), new MyCustomType("z") };
// convert to "X and Y and Z"
string s3 = e3.ToDelimitedString(x => x.Name.ToUpper(), " and ");
Ответ 6
В большинстве случаев НЕ.