【问题标题】:When do I use a predicate [duplicate]我什么时候使用谓词[重复]
【发布时间】:2021-05-18 15:02:06
【问题描述】:

我了解谓词是什么以及如何创建一个谓词,但我什么时候使用它?我为什么要使用它?

例如:

Predicate<string> isUpper = s => s.Equals(s.ToUpper());

我为什么要这样做或类似的事情?

【问题讨论】:

  • 谓词(以及其他 lambda 表达式,如 Action 和 Func)在您想将函数传递给方法并让该方法执行时非常有用。许多 linq 方法(如 Where 和 Select)都使用了它们。在您的示例中,如果您有一个字符串集合并想查找大写字符串,则可以执行 myCollection.Where(isUpper) 以仅获取大写字符串。

标签: c# predicate


【解决方案1】:

谓词可以存储为变量。这意味着它们可以作为参数传递或存储为类中的成员变量。如果您熟悉 strategy pattern,则可以这样做,但无需创建整个类来封装您的策略。

例如,假设我们在任意整数列表上使用 LINQ。

然后我们可以这样做:

List<int> evenInts = ints.Where(i => i % 2 == 0).ToList();

谓词允许像Where 这样的方法存在并简洁地使用。

【讨论】:

    【解决方案2】:

    首先,我将总结委托和 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&lt;T&gt; 代表


    Predicate&lt;T&gt; 也只是另一个委托,定义如下:

    delegate bool Predicate<T>(T obj)
    

    这是一个带有通用参数的委托。这允许您将任何类型的参数传递给它,该参数将在稍后创建委托变量时指定,但返回类型始终为bool。谓词本质上只是一个条件,可以是truefalse

    对于您的问题,使用谓词,您可以将这样的条件传递给一个方法,以便该方法可以使用它来检查它是否适用于该类私有的东西。您基本上是在传递稍后将执行的逻辑。

    谓词的一个常见用例是过滤。如果我有一个元素集合,并且我想过滤元素并仅获取条件成立的那些元素,我可以使用Predicate&lt;T&gt; 参数:

    
    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&lt;T&gt;,而是相同(兼容性方面)Func&lt;T, bool&gt;,这是另一个定义如下的委托:

    delegate TResult Func<in T, out TResult>(T arg)
    

    Func&lt;T, bool&gt;Predicate&lt;T&gt; 因此在它们可以引用的方法方面是相同的。此外,您可以创建自己的委托,其签名与谓词相同。该框架定义了许多它们,以使您的生活更轻松。

    【讨论】:

    • 我知道其中的 90%,但这是一个绝妙的解释。感谢您抽出宝贵时间,我会将谓词放在我的后兜里并根据需要使用。 -杰西
    【解决方案3】:

    我使用过 C# 谓词,它们只是返回布尔值的委托。 当您搜索对象集合并想要特定的东西时,它们很有用。 它们通常用于允许您在运行时提供逻辑,可以根据需要简单或复杂。

    我已经将它与第三方控件 Telerik Treeview 一起使用来搜索特定节点。

    【讨论】:

      【解决方案4】:

      谓词委托是一个内置的泛型类型委托。此委托在 System 命名空间下定义。谓词委托通常用于根据一组标准对某些数据执行搜索操作。它适用于那些包含一些标准的方法,并确定传递的参数是否满足给定的标准。

      示例语法:

      public delegate bool Predicate <in P>(P obj);
      

      为什么要使用谓词

      C# Predicate 的一些优点:

      • 当我们必须过滤出值列表时,谓词委托很有用。
      • 谓词委托可以内联用于一次性搜索功能。
      • 当我们必须在泛型集合中搜索项目时,可以使用谓词委托。
      • 通过使用谓词委托,可以缩短代码长度,并返回 true 或 false。
      • 匿名方法、lambda 表达式可以分配给谓词委托。
      • 谓词委托在运行时提供逻辑,可以是简单逻辑,也可以是复杂逻辑

      【讨论】:

        猜你喜欢
        • 2016-12-01
        • 2012-02-15
        • 1970-01-01
        • 2021-06-17
        • 1970-01-01
        • 1970-01-01
        • 2013-10-19
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多