如何编写谓词函数

时间:2018-10-31 08:16:37

标签: c# delegates

我有一个这样的班级:

    public class A
    {
        public string Username { get; set; }
        public bool IsOK { get; set}
    }

    public class B:A
    {
        public string test { get; set; }
    }
    public class C:B
    {
        public string test2 { get; set; }
    }

在我的主班上:

    static void main()
    {
        var a = new B() { Username = "User1", IsOK = false };
        var b = new B() { Username = "user2", IsOK = false };
        var c = new C() { Username = "admin", IsOK = true };
        List<B> bclasses = new List<B>() { a, b, c };
        // I want to filter out username is user2 or IsOK is true
        var username = "user2";
        var select = bclasses.Where(b => b.IsOK || b.Username == username).ToList();
    }

但是我不想每次都写代码“ b => b.IsOk || b.UserName ==用户名”。 我如何在Where中写一个谓词,以便简洁? 谢谢。

3 个答案:

答案 0 :(得分:1)

在这种情况下,我认为您可能需要实现功能(Func),而不是谓词。

感谢@Fildor向我指出未使用的委托,以便将其封装为以下形式:

 Func<List<A>, string, List<A>> selectValidUser = (users, filterName) =>
 {
    return users.Where(u => u.IsOK || u.Username == filterName).ToList();
 };

 var selectedUsers = selectValidUser(bclasses, username);

答案 1 :(得分:1)

您需要一个接受B或C并返回布尔值的函数,该布尔值指示是否将其包括在列表中。换句话说,是Func<B,bool>。您可以这样定义它:

Func<B,bool> predicate = x => x.IsOK || x.Username == username;

要使用它,只需将其传递给Where

var selection = bclasses.Where( predicate ).ToList();

答案 2 :(得分:1)

您可以将谓词声明为Func<A, bool>

Func<A, bool> predicate = x => x.IsOK || x.Username == username;

或者您可以将其声明为局部函数:

bool predicate(A x) => x.IsOK || x.Username == username;

(很遗憾,您不能使用Predicate<A>,因为它不是IEnumerable.Where()接受的类型。)

无论哪种情况,如果在方法内部定义它,它就可以捕获本地username,因此不需要为此设置参数。

这是一个正确且可编译的示例:

using System.Collections.Generic;
using System.Linq;

namespace Demo
{
    public class A
    {
        public string Username { get; set; }
        public bool   IsOK     { get; set; }
    }

    public class B: A
    {
        public string test { get; set; }
    }

    public class C: B
    {
        public string test2 { get; set; }
    }

    static class Program
    {
        public static void Main()
        {
            var     a        = new B() { Username = "User1", IsOK = false };
            var     b        = new B() { Username = "user2", IsOK = false };
            var     c        = new C() { Username = "admin", IsOK = true };
            List<B> bclasses = new List<B>() { a, b, c };

            // I want to filter out username is user2 or IsOK is true
            var username = "user2";

            bool predicate(A x) => x.IsOK || x.Username == username; // <=== Here is the predicate.

            var select = bclasses.Where(predicate).ToList();
        }
    }
}

现在,假设您实际上想将username参数传递给谓词而不是捕获它,您可以像这样向谓词添加一个参数:

bool predicate(A x, string name) => x.IsOK || x.Username == name;

然后您将username传递给Where()内部的谓词,如下所示:

var select = bclasses.Where(item => predicate(item, username)).ToList();