如何在Lambda表达式上获得Predicate <t>值?</t>

时间:2013-03-06 19:57:54

标签: c# .net

我有以下方法:

private List<T> GetEntities<T>(T entity) {
    // ...
}

public virtual List<T> Find<T>(Predicate<T> match) {
    // ...
}

如何在Predicate<T>中获取lambda表达式的值?

我想做点什么:

var result = Find<MyObject>(o => o.Name == "Something")

并且在Find方法中我会:

public virtual List<T> Find<T>(Predicate<T> match) {
    // ...
    string name = myObj.Name  // equals to "Something"        
    return GetEntities<T>(myObj) //Note that here is my object with the parameters passed via lambda
    // ...
}

我该怎么做?

编辑:已经有一个接收MyObject的方法,我只想要一个可以使用lambda表达式的方法,而不需要实例化一个对象来过滤一个实体。不知道我是否使用Func或Predicate

编辑2:根据要求,以下是我将要实现的具体示例:

目前,当我想要检索具有特定过滤器的对象时,我使用:

Person p = new Person() { Name = "John" };
var result = GetEntities<Person>(p);

我喜欢做什么:

var result = Find<Person>(p => p.Name = "John");

然而,内部希望继续使用上一个方法,我只需将表达式转换为对象,然后使用GetEntities<Person>(p)

结论: 我对谓词和Func的混淆了很多。我以为我可以将它们视为对象,但是表达式和​​我的问题完全没有理解这些元素的概念。

4 个答案:

答案 0 :(得分:3)

根据签名和用法,以下代码是我推断的。但是,它编译使用不正确

  • 课程

    public partial class MyObject {
        public String Name;
    }
    
    public partial class MyGeneric<U> where U: MyObject {
        private List<T> GetEntities<T>(T entity) where T: U {
            throw new NotImplementedException(); // not implemented yet
        }
    
        public virtual List<T> Find<T>(Predicate<T> match) where T: U {
            foreach(var myObj in m_List)
                if(match(myObj as T)) {
                    // ...
                    var name=myObj.Name;
                    // ...
                    return this.GetEntities(myObj as T);
                }
    
            return new List<T>();
        }
    
        List<U> m_List;
    }
    
  • 测试

    var myGeneric=new MyGeneric<MyObject>();
    var result=myGeneric.Find<MyObject>(o => o.Name=="Something");
    

这是我想说的:

  1. 您可能误解了泛型。

    当你看到类MyGeneric和那两个方法时,都有约束。从你的代码的使用,几乎不能没有这些约束,但这只是不必要的复杂。

  2. 您可能会误解Predicate<T>以及lambda表达式

    Predicate<T>的定义是

    public delegate bool Predicate<T>(T obj);
    

    也就是说,它是代表。 obj传递给委托的参数。因此,您无法使用不同的上下文获取obj。但是,您可以执行类似

    的操作
    MyObject x;
    var myGeneric=new MyGeneric<MyObject>();
    var result=myGeneric.Find<MyObject>(o => (x=o).Name=="Something");
    

    x o引用Find,但使用Predicate<T>方法时,可能不会这样做。所以对象传递给{{1}},必须已经在某个地方你可以访问它,否则你永远不会。

  3. 我发布的代码演示了您可以执行的语句的可编译语法,甚至可能有效。但我强烈建议不要做类似的事情。

答案 1 :(得分:0)

如果我理解你的问题,你的第二种方法应该是这样的:

public virtual List<T> Find<T>(Expression<Predicate<T>> match)
{
    return _myCollection.Where(match).ToList();
}

然后,您可以将lambda表达式传递给方法并返回匹配列表。

答案 2 :(得分:0)

试试这个

public virtual List<T> Find<T>(Func<T,bool> match)
{
   return lst.Where(match).ToList();
}

答案 3 :(得分:0)

在您的示例中,这是正确的:

public virtual List<T> Find(T myObj)
{
    return GetEntities(myObj);
}

只有在想要从IEnumerable中过滤项目并且在您的问题中没有任何IEnumerable时,才需要传递谓词(Func<T, bool>)。如果你有IEnumerable那么:

private IEnumerable<T> _list;
public virtual List<T> Find(Func<T, bool> predicate)
{
    T myObj = _list.FirstOrDefault(predicate);
    return GetEntities(myObj);
}

要扩展一下,您的o => o.Name == "Something"相当于:

private bool Filter(MyObject enumeratedObject)
{
    return enumeratedObject.Name == "Something";
}

在枚举发生之前它不包含任何值,并开始为列表的每个元素调用Filter(...)。