如何将lambda表达式传递给where语句进行比较

时间:2017-03-06 11:25:01

标签: c# lambda

我们说我有这个课程

public class Person
{
    public int PhoneNumber { get; set; }
    public string Name { get; set; }
}

我想编写一个方法,可以根据Person和比较字段的属性返回用户列表。

private List<Person> GetResult(Func<Person, object> p, string v)
{
       List<Person> data = GetResultsFromDb();
       return data.Where(p == v);
}

例如,如果我想得到所有被称为迈克的人,我可以说

var result = GetResult(a => a.Name, "Mike");

或者,如果我想根据电话号码得到结果,我可以说

var result = GetResult(a => a.PhoneNumber, 123);

但是我得到了

Operator == cannot be applied to operands of type 'Expression<Func<Person, object>>' and string

2 个答案:

答案 0 :(得分:3)

p的论点是代表。此类型与string不能很好地比较(因此您的错误消息)。您需要调用委托来获取值。但是,返回类型的对象不是比较的最佳选择。所以你应该让你的方法通用。既然您是通用的,则不能使用等于运算符==,但可以使用Equals。最后,您需要调用ToList以匹配方法的返回类型:

private List<Person> GetResult<T>(Func<Person, T> p, T v)
{
       List<Person> data = GetResultsFromDb();
       return data.Where(item => p(item).Equals(v)).ToList();
}

由于参数v的类型为T,因此在调用方法时可以推断出T。这意味着您可以省略类型参数,因此您可以使用GetResult(a => a.Name, "Mike")代替GetResult<string>(a => a.Name, "Mike")

由于在Equals上定义Equals,因此在调用Object时,某些.NET专业人员可能会抱怨您不需要该方法是通用的。您还可以指出,null值的比较不起作用,IEquatable实现没有给出任何特殊考虑。如果您想避开所有这些投诉,可以使用EqualityComparer进行比较:

private List<Person> GetResult<T>(Func<Person, T> p, T v)
{
       List<Person> data = GetResultsFromDb();
       return data.Where(item => EqualityComparer<T>.Default.Equals(p(item), v)).ToList();
}

答案 1 :(得分:-2)

见下面的代码。你将p用于两个不同的目的

    public class Person
    {
        public int PhoneNumber { get; set; }
        public string Name { get; set; }

        private List<Person> GetResult(Func<Person, object> p, string v)
        {
            List<Person> data = GetResultsFromDb();
            return data.Where(x => x.Name == v).ToList();
        }

        private List<Person> GetResultsFromDb()
        {
            return new List<Person>() {
                new Person() { Name = "Mike"},
                new Person() { Name = "John"},
                new Person() { Name = "Mike"}
            };
        }

    }