将多个参数传递给Predicate,Functional Programming

时间:2018-03-11 17:14:05

标签: c# functional-programming

我正在努力更好地理解函数式编程。提供了以下示例,此示例创建谓词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告诉它长度使一个函数成长字,即不硬编码&#39; 10&#39;。

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();

1 个答案:

答案 0 :(得分:2)

我做:

public Func<string, int, bool> longWords = (str, number) => str.Length > number;

而不是:

public Predicate<Tuple<string, int>> longWords = (x) => x.Item1.Length > x.Item2;

这只是因为我认为使用stringint然后返回bool而不是带谓词的函数更容易处理stringint的元组,并返回bool。加上这个版本的元组类型很麻烦。如果您正在使用C#7及更高版本,请考虑新的元组类型。

然后从:

更改方法签名
public static int Count<T>(T[] array, Predicate<T> predicate, int counter)

为:

public static int Count<T>(T[] array, Func<T, int, bool> predicate, int counter)

为了适应上述代表类型的变化。

然后需要更改if条件:

if (predicate(new Tuple<string, int>(array[i], 10)))

为:

if (predicate(array[i], 10))

为了适应上述代表类型的变化。

另请注意,在C#中,您需要像这样定义数组:

string[] text = { "This is a really long string", "Not 10" };

而不是[ ]大括号。

现在您的使用代码变为:

BaseFunctions b = new BaseFunctions();
string[] text = { "This is a really long string", "Not 10" };

Console.WriteLine(BaseFunctions.Count(text, b.longWords, 0).ToString());
Console.ReadLine();