0

我有以下方法:

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

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

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

我想做类似的事情:

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

4 回答 4

3

From the signature and usage, following code is what I inferred for you. It compiles, however, it's incorrect for use.

  • Classes

    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;
    }
    
  • Test

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

Here're something I'd like to tell:

  1. You might misunderstood of generic.

    As you see the class MyGeneric and those two method, all have constraints. From the usage of your code, almost cannot go without these constraints, but this is just unnecessarily complicated.

  2. You might misunderstood of Predicate<T> and also lambda expressions

    The definition of Predicate<T> is

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

    That is, it's a delegate. obj is the argument pass to the delegate. Therefore you cannot get obj with a different context. However, you can do something like

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

    Here x references to o, but with your Find method, it's not possibly to do. So the object pass to the Predicate<T>, must already be somewhere you can access it, otherwise you can never.

I post with the code that demonstrates what the compilable syntax of statement that you can do, and even possibly works. But I STRONGLY suggest that DON'T do something like this.

于 2013-03-06T22:25:28.190 回答
0

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

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

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

于 2013-03-06T20:31:29.213 回答
0

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

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

Func<T, bool>只有当您想从 IEnumerable 中过滤项目并且您的问题中没有任何 IEnumerable 时,您才需要传递谓词 ( )。如果你有 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(...) 之前,它不包含任何值。

于 2013-03-06T21:28:23.553 回答
0

尝试这个

public virtual List<T> Find<T>(Func<T,bool> match)
{
   return lst.Where(match).ToList();
}
于 2013-03-06T20:47:54.543 回答