委托谓词的用处
Delegate Predicates Usefulness
下面的示例显示使用 predicate
来评估硬编码值为 100000 的条件。无法向 FindPoints
方法添加额外的参数,因为它会违反谓词参数约束。
这使使用谓词的价值受到质疑。显然 Lambda 解决了这个问题..但是 none 考虑到这个看似奇怪的约束,谁能详细说明谓词在现实生活场景中的用处。
如果不接受 T 以外的参数,为什么有人会使用谓词?
using System;
using System.Drawing;
public class Example
{
public static void Main()
{
// Create an array of Point structures.
Point[] points = { new Point(100, 200),
new Point(150, 250), new Point(250, 375),
new Point(275, 395), new Point(295, 450) };
// Define the Predicate<T> delegate.
Predicate<Point> predicate = FindPoints;
// Find the first Point structure for which X times Y
// is greater than 100000.
Point first = Array.Find(points, predicate);
// Display the first structure found.
Console.WriteLine("Found: X = {0}, Y = {1}", first.X, first.Y);
}
private static bool FindPoints(Point obj)
{
return obj.X * obj.Y > 100000;
}
}
// The example displays the following output:
// Found: X = 275, Y = 395
编辑:Lambda 用法在下面做同样的事情。
using System;
using System.Drawing;
public class Example
{
public static void Main()
{
// Create an array of Point structures.
Point[] points = { new Point(100, 200),
new Point(150, 250), new Point(250, 375),
new Point(275, 395), new Point(295, 450) };
// Find the first Point structure for which X times Y
// is greater than 100000.
Point first = Array.Find(points, x => x.X * x.Y > 100000 );
// Display the first structure found.
Console.WriteLine("Found: X = {0}, Y = {1}", first.X, first.Y);
}
}
// The example displays the following output:
// Found: X = 275, Y = 395
这是来自 MSDN。
这篇文章给出了很好的例子,但似乎没有解决我的问题。
即使您使用 lambda 表达式声明谓词,提供匿名方法而不是命名方法,lambda 仍然 只接受特定类型。只是编译器推断出所需的类型(但请注意,C# 实际上允许在您明确指定类型的地方对 lambda 语法进行变体)。
所以这两种方法同样有用;如果您理解为什么一个有用(例如 lambda 语法),那么您就会理解为什么另一个有用。
它们都很有用,因为通过传递谓词委托实例,您可以自定义所调用方法的行为。例如。在这种情况下,您使用的是 Array.Find()
方法。谓词委托实例的使用,无论是先存储在局部变量中还是简单地直接传递,无论是使用命名方法还是匿名方法声明,都允许 Array.Find()
方法执行所有无聊的重复性迭代工作通过一个数组,同时允许调用者提供有趣的、特定于场景的逻辑。
明确地说,您的两个示例实际上基本相同,尤其是因为您正在处理谓词的静态方法。声明中存在细微差别,但是一旦优化 JIT 编译器完成了代码,在运行时执行的内容实际上是相同的。即使是从您的 C# 程序编译的 IL 在结构上也是相同的,尽管会有一些命名差异。您可以通过比较编译版本自己验证这一点,例如使用 ildasm.exe 工具或类似 dotPeek 反编译器的工具。
我还要指出,您提供了两个示例——局部变量和命名方法的使用,以及不带局部变量的匿名方法的使用——但至少还有两个其他示例也是同样相同:
具有匿名方法的局部变量:
Predicate<Point> predicate = x => x.X * x.Y > 100000;
Point first = Array.Find(points, predicate);
没有局部变量的命名方法:
Point first = Array.Find(points, FindPoints);
在最后一个示例中,编译器推断委托类型,自动创建委托实例,就像将方法组名称分配给局部变量时所做的那样。
下面的示例显示使用 predicate
来评估硬编码值为 100000 的条件。无法向 FindPoints
方法添加额外的参数,因为它会违反谓词参数约束。
这使使用谓词的价值受到质疑。显然 Lambda 解决了这个问题..但是 none 考虑到这个看似奇怪的约束,谁能详细说明谓词在现实生活场景中的用处。
如果不接受 T 以外的参数,为什么有人会使用谓词?
using System;
using System.Drawing;
public class Example
{
public static void Main()
{
// Create an array of Point structures.
Point[] points = { new Point(100, 200),
new Point(150, 250), new Point(250, 375),
new Point(275, 395), new Point(295, 450) };
// Define the Predicate<T> delegate.
Predicate<Point> predicate = FindPoints;
// Find the first Point structure for which X times Y
// is greater than 100000.
Point first = Array.Find(points, predicate);
// Display the first structure found.
Console.WriteLine("Found: X = {0}, Y = {1}", first.X, first.Y);
}
private static bool FindPoints(Point obj)
{
return obj.X * obj.Y > 100000;
}
}
// The example displays the following output:
// Found: X = 275, Y = 395
编辑:Lambda 用法在下面做同样的事情。
using System;
using System.Drawing;
public class Example
{
public static void Main()
{
// Create an array of Point structures.
Point[] points = { new Point(100, 200),
new Point(150, 250), new Point(250, 375),
new Point(275, 395), new Point(295, 450) };
// Find the first Point structure for which X times Y
// is greater than 100000.
Point first = Array.Find(points, x => x.X * x.Y > 100000 );
// Display the first structure found.
Console.WriteLine("Found: X = {0}, Y = {1}", first.X, first.Y);
}
}
// The example displays the following output:
// Found: X = 275, Y = 395
这是来自 MSDN。 这篇文章给出了很好的例子,但似乎没有解决我的问题。
即使您使用 lambda 表达式声明谓词,提供匿名方法而不是命名方法,lambda 仍然 只接受特定类型。只是编译器推断出所需的类型(但请注意,C# 实际上允许在您明确指定类型的地方对 lambda 语法进行变体)。
所以这两种方法同样有用;如果您理解为什么一个有用(例如 lambda 语法),那么您就会理解为什么另一个有用。
它们都很有用,因为通过传递谓词委托实例,您可以自定义所调用方法的行为。例如。在这种情况下,您使用的是 Array.Find()
方法。谓词委托实例的使用,无论是先存储在局部变量中还是简单地直接传递,无论是使用命名方法还是匿名方法声明,都允许 Array.Find()
方法执行所有无聊的重复性迭代工作通过一个数组,同时允许调用者提供有趣的、特定于场景的逻辑。
明确地说,您的两个示例实际上基本相同,尤其是因为您正在处理谓词的静态方法。声明中存在细微差别,但是一旦优化 JIT 编译器完成了代码,在运行时执行的内容实际上是相同的。即使是从您的 C# 程序编译的 IL 在结构上也是相同的,尽管会有一些命名差异。您可以通过比较编译版本自己验证这一点,例如使用 ildasm.exe 工具或类似 dotPeek 反编译器的工具。
我还要指出,您提供了两个示例——局部变量和命名方法的使用,以及不带局部变量的匿名方法的使用——但至少还有两个其他示例也是同样相同:
具有匿名方法的局部变量:
Predicate<Point> predicate = x => x.X * x.Y > 100000;
Point first = Array.Find(points, predicate);
没有局部变量的命名方法:
Point first = Array.Find(points, FindPoints);
在最后一个示例中,编译器推断委托类型,自动创建委托实例,就像将方法组名称分配给局部变量时所做的那样。