我有以下方法:
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的混淆了很多。我以为我可以将它们视为对象,但是表达式和我的问题完全没有理解这些元素的概念。
答案 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");
这是我想说的:
您可能误解了泛型。
当你看到类MyGeneric
和那两个方法时,都有约束。从你的代码的使用,几乎不能没有这些约束,但这只是不必要的复杂。
您可能会误解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}},必须已经在某个地方你可以访问它,否则你永远不会。
我发布的代码演示了您可以执行的语句的可编译语法,甚至可能有效。但我强烈建议不要做类似的事情。
答案 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(...)。