今天我终于“得到了”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<>
功能的示例。)
答案 0 :(得分:6)
我想如果你要在很多地方重用有问题的Func(并且它涉及的不仅仅是简单的逻辑),那么这样做只会有一点。否则使用标准方式似乎更好,更完全可读。
答案 1 :(得分:4)
当你重复使用它时,它才真正更具可读性/实用性。
一个更有趣的Lambda传递和futz,将是Expression<Func<int,bool>>
因为你仍然可以在你想要的时候调用它,但是你也可以将它完全分开并修补它。
它......好......死了性感。
答案 2 :(得分:2)
我正在使用Func和Action委托来处理异常。我经常发现自己一遍又一遍地构建相同的try-catch块,因为我保持它们尽可能短。 Delegate和Action可以减少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块和while循环)并希望相同应用程序范围内记录,然后你只有一个地方放置try-catch块:它是方法,它将Func或Action委托作为参数。处理业务逻辑的代码几乎没有那些try-catch-blocks,因此更具可读性。
对于一些更高级的示例和更长的描述,请查看: Action Policy
答案 3 :(得分:1)
我通常只在我想重用委托时才这样做。否则,不经常。
答案 4 :(得分:1)
如何在适当的时候在自己的方法中接受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 ");
答案 5 :(得分:0)
大部分时间都不是。