【发布时间】:2018-08-19 17:44:33
【问题描述】:
我正在努力更好地理解函数式编程。提供了以下示例,此示例创建了一个谓词 lambda。然后创建一个静态方法来统计通过谓词条件的项目数。
public Predicate<string> longWords = (x) => x.Length > 10;
public static int Count<T>(T[] array, Predicate<T> predicate, int counter)
{
for (int i = 0; i < array.Length; i++)
{
if (predicate(array[i]))
{
counter++;
}
}
return counter;
}
我想让这个解决方案遵循Referential Transparency 原则,该原则规定您只能通过查看其参数的值来确定应用该函数的结果。
不幸的是,longWords 没有告诉我长字的真正含义,我需要向longWords 传递一个参数,告诉它使函数成为长字的长度,即不硬编码“10”。
Predicates 只接受一个参数,而使longWords 需要Predicate<Tuple<string,int>>,带来了挑战。
以下是我试图找到解决方案的尝试,以及导致的两条错误消息。
public class BaseFunctions
{
public Predicate<Tuple<string, int>> longWords = (x) => x.Item1.Length > x.Item2;
public static int Count<T>(T[] array, Predicate<T> predicate, int counter)
{
for (int i = 0; i < array.Length; i++)
{
/// error below: Cannot convert from 'T' to 'string'
/// in the example provided predicate(array[i]) worked fine when the predicate had only string type
if (predicate(new Tuple<string, int>(array[i], 10)))
{
counter++;
}
}
return counter;
}
}
它的用法
BaseFunctions b = new BaseFunctions();
string[] text = ["This is a really long string", "Not 10"];
/// also error below on BaseFunctions.Count 'The type arguments for method BaseFunctions.Count<T>(T[], Predicate<T>, int) cannot be inferred from the usage. Try specifying the arguments explicitly
Console.WriteLine(BaseFunctions.Count(text, b.longWords, 0).ToString());
Console.ReadLine();
【问题讨论】:
-
不要使用
Predicate<Tuple<string, int>>,最好使用Func<T, int, bool>,然后将Predicate<T> predicate改为Func<T, int, bool> predicate -
查看stackoverflow.com/questions/665494/… 了解为什么
Func优于Predicate -
顺便说一句,在理想的世界中,您不会想重新发明轮子,因为我们可以实现您想要的:
string[] text = { "This is a really long string", "Not 10" }; Console.WriteLine(text.Count(x => x.Length > 10));使用Count扩展方法。虽然,在这种特定情况下,这很好,因为您提到这仅用于练习目的。