我什么时候使用谓词
When do I use a predicate
我了解谓词是什么以及如何创建谓词,但我什么时候使用它?我为什么要使用它?
例如:
Predicate<string> isUpper = s => s.Equals(s.ToUpper());
我为什么要这样做或类似的事情?
谓词可以存储为变量。这意味着它们可以作为参数传递或作为成员变量存储在 class 中。如果您熟悉 strategy pattern 这可以让您做到这一点,但不需要创建一个完整的 class 来封装您的策略。
例如,假设我们在任意整数列表上使用 LINQ。
然后我们可以这样做:
List<int> evenInts = ints.Where(i => i % 2 == 0).ToList();
谓词允许像Where
这样的方法存在并被简洁地使用。
我使用过 C# 谓词,它们只是 return 布尔值的委托。
当您搜索一组对象并想要特定的东西时,它们很有用。
它们通常用于允许您在运行时提供逻辑,可以根据需要简单或复杂。
我已经将它与第三方控件 Telerik Treeview 一起使用来搜索特定节点。
Predicate 委托是一种内置的泛型类型委托。此委托在系统命名空间下定义。谓词委托通常用于根据一组条件对某些数据执行搜索操作。它与那些包含一些标准集的方法一起工作,并确定传递的参数是否满足给定的标准。
语法示例:
public delegate bool Predicate <in P>(P obj);
为什么要使用谓词
C# Predicate 的一些优点:
- 当我们必须过滤掉值列表时,Predicate 委托很有用。
- 可以为一次性搜索功能内嵌谓词委托。
- 当我们必须在通用集合中搜索项目时,可以使用谓词委托。
- 通过使用谓词委托,缩短了代码的长度并返回 true 或 false。
- 匿名方法,lambda 表达式可以赋值给谓词委托。
- 谓词委托提供了运行时的逻辑,可以是简单的逻辑也可以是复杂的逻辑
首先,我将总结委托和 lambda 表达式。
代表
在 C# 中,delegates 允许您创建表示函数的类型。换句话说,委托允许您在变量中保存对方法的引用。一旦我们存储了对该方法的引用,我们就可以使用该变量来调用它所引用的方法。所以你间接调用了这个方法。 C#中的“delegate”一词很符合delegate的字面意思。
要存储对方法的引用,您首先需要创建一个兼容的委托:
delegate int MyDelegate(string parameter)
上面的语句创建了一个委托,它可以保存对 return 类型 int
的任何方法的引用,并采用单个 string
作为参数。例如,我正在创建一个简单的 class 和一个演示方法:
class AClass
{
public int StringLength(string str) { return str.Length; }
}
创建委托后,您可以像使用类型一样使用它:
AClass obj = new AClass()
MyDelegate d = obj.StringLength
注意我跳过了 StringLength
之后的括号。现在我可以这样做了:
int length = d("Hello");
这将间接调用 obj.StringLength()
,它的值 return 将由 d
return 编辑并存储在 length
中。
还有更多像 multicast delegates 这样的代表超出了这个答案的范围。
代表为什么强大?
它们可以帮助您像物品一样轻松地传递 functions/methods。您可以将自己的方法传递给 class,它对您的方法一无所知,但稍后会通过委托调用它。这允许您将自定义逻辑嵌入到您一无所知的代码中。
Lambda 表达式
A lambda expression 只不过是一个函数文字。它有助于在不创建新 class 和新方法的情况下快速创建函数。在前面的示例中,我使用方法 StringLength
创建了一个名为 AClass
的 class。您可以看到所有方法主体都由一行组成。使用 lambdas,可以跳过创建 class 和方法,直接指定方法体:
MyDelegate d = str => str.Length;
Predicate<T>
代表
Predicate<T>
也是一个代表,定义如下:
delegate bool Predicate<T>(T obj)
这是一个带有泛型参数的委托。这允许您向它传递任何类型的参数,该参数将在稍后创建委托变量时指定,但 return 类型始终为 bool
。谓词本质上只是一个条件,可以是 true
或 false
.
关于您的问题,使用谓词,您可以将这样的条件传递给方法,以便该方法可以使用它来检查它是否适用于 class 的私有内容。您基本上是在传递稍后将执行的逻辑。
谓词的一个常见用例是过滤。如果我有一个元素集合,并且我想过滤元素并仅获取条件成立的那些元素,我可以使用 Predicate<T>
参数:
public List<int> Filter(List<int> list, Predicate<int> filter)
{
public var filteredList = new List<int>();
foreach (int element in list)
{
if (filter(element))
{
filteredList.Add(element); //Add to list only if condition holds true for the element
}
}
}
现在,假设我有一个列表,我只想要偶数和大于 5 的数字,那么我可以简单地这样做:
var numbers = new List<int>() { 1, 2, 3, 4, 5, 6, 7, 8, 9 }
var evenNumbers = Filter(numbers, element => element % 2 == 0); // 2, 4, 6, 8
var numbersGreaterThan5 = Filter(numbers, element => element > 5); // 6, 7, 8, 9
实际上,您几乎不必创建自定义 Filter()
方法,因为 System.Linq
已经有一个名为 Where()
的 method/LINQ 运算符可以为您执行此操作。此 Where()
方法的参数不是 Predicate<T>
,而是相同的(兼容性方面)Func<T, bool>
,它是另一个定义如下的委托:
delegate TResult Func<in T, out TResult>(T arg)
Func<T, bool>
和 Predicate<T>
因此在它们可以引用的方法方面是相同的。此外,您可以使用与谓词相同的签名创建自己的委托。该框架定义了其中的一堆,以使您的生活更轻松。
我了解谓词是什么以及如何创建谓词,但我什么时候使用它?我为什么要使用它?
例如:
Predicate<string> isUpper = s => s.Equals(s.ToUpper());
我为什么要这样做或类似的事情?
谓词可以存储为变量。这意味着它们可以作为参数传递或作为成员变量存储在 class 中。如果您熟悉 strategy pattern 这可以让您做到这一点,但不需要创建一个完整的 class 来封装您的策略。
例如,假设我们在任意整数列表上使用 LINQ。
然后我们可以这样做:
List<int> evenInts = ints.Where(i => i % 2 == 0).ToList();
谓词允许像Where
这样的方法存在并被简洁地使用。
我使用过 C# 谓词,它们只是 return 布尔值的委托。 当您搜索一组对象并想要特定的东西时,它们很有用。 它们通常用于允许您在运行时提供逻辑,可以根据需要简单或复杂。
我已经将它与第三方控件 Telerik Treeview 一起使用来搜索特定节点。
Predicate 委托是一种内置的泛型类型委托。此委托在系统命名空间下定义。谓词委托通常用于根据一组条件对某些数据执行搜索操作。它与那些包含一些标准集的方法一起工作,并确定传递的参数是否满足给定的标准。
语法示例:
public delegate bool Predicate <in P>(P obj);
为什么要使用谓词
C# Predicate 的一些优点:
- 当我们必须过滤掉值列表时,Predicate 委托很有用。
- 可以为一次性搜索功能内嵌谓词委托。
- 当我们必须在通用集合中搜索项目时,可以使用谓词委托。
- 通过使用谓词委托,缩短了代码的长度并返回 true 或 false。
- 匿名方法,lambda 表达式可以赋值给谓词委托。
- 谓词委托提供了运行时的逻辑,可以是简单的逻辑也可以是复杂的逻辑
首先,我将总结委托和 lambda 表达式。
代表
在 C# 中,delegates 允许您创建表示函数的类型。换句话说,委托允许您在变量中保存对方法的引用。一旦我们存储了对该方法的引用,我们就可以使用该变量来调用它所引用的方法。所以你间接调用了这个方法。 C#中的“delegate”一词很符合delegate的字面意思。
要存储对方法的引用,您首先需要创建一个兼容的委托:
delegate int MyDelegate(string parameter)
上面的语句创建了一个委托,它可以保存对 return 类型 int
的任何方法的引用,并采用单个 string
作为参数。例如,我正在创建一个简单的 class 和一个演示方法:
class AClass
{
public int StringLength(string str) { return str.Length; }
}
创建委托后,您可以像使用类型一样使用它:
AClass obj = new AClass()
MyDelegate d = obj.StringLength
注意我跳过了 StringLength
之后的括号。现在我可以这样做了:
int length = d("Hello");
这将间接调用 obj.StringLength()
,它的值 return 将由 d
return 编辑并存储在 length
中。
还有更多像 multicast delegates 这样的代表超出了这个答案的范围。
代表为什么强大?
它们可以帮助您像物品一样轻松地传递 functions/methods。您可以将自己的方法传递给 class,它对您的方法一无所知,但稍后会通过委托调用它。这允许您将自定义逻辑嵌入到您一无所知的代码中。
Lambda 表达式
A lambda expression 只不过是一个函数文字。它有助于在不创建新 class 和新方法的情况下快速创建函数。在前面的示例中,我使用方法 StringLength
创建了一个名为 AClass
的 class。您可以看到所有方法主体都由一行组成。使用 lambdas,可以跳过创建 class 和方法,直接指定方法体:
MyDelegate d = str => str.Length;
Predicate<T>
代表
Predicate<T>
也是一个代表,定义如下:
delegate bool Predicate<T>(T obj)
这是一个带有泛型参数的委托。这允许您向它传递任何类型的参数,该参数将在稍后创建委托变量时指定,但 return 类型始终为 bool
。谓词本质上只是一个条件,可以是 true
或 false
.
关于您的问题,使用谓词,您可以将这样的条件传递给方法,以便该方法可以使用它来检查它是否适用于 class 的私有内容。您基本上是在传递稍后将执行的逻辑。
谓词的一个常见用例是过滤。如果我有一个元素集合,并且我想过滤元素并仅获取条件成立的那些元素,我可以使用 Predicate<T>
参数:
public List<int> Filter(List<int> list, Predicate<int> filter)
{
public var filteredList = new List<int>();
foreach (int element in list)
{
if (filter(element))
{
filteredList.Add(element); //Add to list only if condition holds true for the element
}
}
}
现在,假设我有一个列表,我只想要偶数和大于 5 的数字,那么我可以简单地这样做:
var numbers = new List<int>() { 1, 2, 3, 4, 5, 6, 7, 8, 9 }
var evenNumbers = Filter(numbers, element => element % 2 == 0); // 2, 4, 6, 8
var numbersGreaterThan5 = Filter(numbers, element => element > 5); // 6, 7, 8, 9
实际上,您几乎不必创建自定义 Filter()
方法,因为 System.Linq
已经有一个名为 Where()
的 method/LINQ 运算符可以为您执行此操作。此 Where()
方法的参数不是 Predicate<T>
,而是相同的(兼容性方面)Func<T, bool>
,它是另一个定义如下的委托:
delegate TResult Func<in T, out TResult>(T arg)
Func<T, bool>
和 Predicate<T>
因此在它们可以引用的方法方面是相同的。此外,您可以使用与谓词相同的签名创建自己的委托。该框架定义了其中的一堆,以使您的生活更轻松。