首先,我将总结委托和 lambda 表达式。
代表
在 C# 中,delegates 允许您创建表示函数的类型。换句话说,委托允许您在变量中保存对方法的引用。一旦我们存储了对该方法的引用,我们就可以使用这个变量来调用它所引用的方法。所以你间接调用了该方法。 C# 中的“委托”一词非常符合委托的字面意思。
要存储对方法的引用,首先需要创建一个兼容的委托:
delegate int MyDelegate(string parameter)
上述语句创建了一个委托,该委托可以持有对返回类型为int 的任何方法的引用,并将单个string 作为参数。例如,我在这里创建了一个简单的类和一个用于演示的方法:
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(),它返回的值将由d返回并存储在length中。
像multicast delegates 这样的代表还有更多超出了这个答案的范围。
为什么委托很强大?
它们可以帮助您像对象一样轻松地传递函数/方法。您可以将自己的方法传递给对您的方法一无所知但稍后将通过委托调用它的类。这允许您将自定义逻辑嵌入到您一无所知的代码中。
Lambda 表达式
lambda expression 只不过是一个函数字面量。它有助于在不创建新类和新方法的情况下快速创建函数。在前面的示例中,我创建了一个名为AClass 的类,其方法为StringLength。您可以看到所有方法体都由一行组成。使用 lambdas,你可以跳过创建类和方法,直接指定方法体:
MyDelegate d = str => str.Length;
Predicate<T> 代表
Predicate<T> 也只是另一个委托,定义如下:
delegate bool Predicate<T>(T obj)
这是一个带有通用参数的委托。这允许您将任何类型的参数传递给它,该参数将在稍后创建委托变量时指定,但返回类型始终为bool。谓词本质上只是一个条件,可以是true 或false。
对于您的问题,使用谓词,您可以将这样的条件传递给一个方法,以便该方法可以使用它来检查它是否适用于该类私有的东西。您基本上是在传递稍后将执行的逻辑。
谓词的一个常见用例是过滤。如果我有一个元素集合,并且我想过滤元素并仅获取条件成立的那些元素,我可以使用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() 的方法/LINQ 运算符可以为您执行此操作。此Where() 方法的参数不是Predicate<T>,而是相同(兼容性方面)Func<T, bool>,这是另一个定义如下的委托:
delegate TResult Func<in T, out TResult>(T arg)
Func<T, bool> 和Predicate<T> 因此在它们可以引用的方法方面是相同的。此外,您可以创建自己的委托,其签名与谓词相同。该框架定义了许多它们,以使您的生活更轻松。