我无法弄清楚如何根据我在运行时传入的值使用List上的“查找”。如果您看到我的下面的代码,我希望能够在List中找到它的Path参数等于X的CustomClass,其中X将在运行时定义。
如何在列表上进行此类查找?或者,如果不编写迭代器并手动执行查找,这是不可能的?在这种情况下,也许我应该使用一个关键的集合来代替?
private List<CustomClass> files;
public void someMethod()
{
Uri u= new Uri(www.test.com);
CustomClass cc = this.files.find( matchesUri(u) ); // WON'T LET ME DO THIS
}
private static bool matchesUri(List<CustomClass> cc, Uri _u)
{
return cc.Path == _u; }
public class CustomClass
{
private Uri path;
public Uri Path
{
get { return this.path; }
set { this.path = value; }
}
}
PS。我必须承认,我并没有完全按照http://msdn.microsoft.com/en-us/library/x0b5b5bc.aspx
中的doco中的谓词答案 0 :(得分:12)
使用lambda:
Uri u = new Uri("www.test.com");
CustomClass cc = this.files.Find(cc => cc.Path == u);
或者如果你还想要一个命名方法:
static bool matchesUri(CustomClass cc, Uri _u)
{
return cc.Path == _u;
}
Uri u = new Uri("www.test.com");
CustomClass cc = this.files.Find(cc => matchesUri(cc, u));
答案 1 :(得分:1)
你可以写
CustomClass cc = this.files.Find( p=> p.Path == u );
如果未找到与谓词匹配的元素,则Find()方法返回null。
答案 2 :(得分:1)
仅为了完整起见,如果您不想使用lambda,那么您将会采取以下措施:
// Predicate must be a method with a single parameter,
// so we must pass the other parameter in constructor
public class UriMatcher
{
private readonly Uri _u;
public UriMatcher(Uri u)
{
_u = u;
}
// Match is Predicate<CustomClass>
public bool Match(CustomClass cc)
{
return cc.Path == _u;
}
}
然后将其用作:
public void someMethod()
{
Uri u = new Uri("www.test.com");
UriMatcher matcher = new UriMatcher(u);
CustomClass cc = this.files.Find(matcher.Match);
}
请注意,您传递的引用方法,而不是方法的结果 - Match
vs Match()
。
另请检查此主题:Predicate Delegates in C#。
答案 3 :(得分:0)
public void someMethod()
{
Uri u= new Uri("www.test.com");
CustomClass cc = this.files.find( p => { return p.Path == u; } );
}
答案 4 :(得分:0)
尝试使用匿名方法进行搜索,并使用您希望在其中使用的任何局部变量。如果不满意,请调出您通常定义的委托方法。
答案 5 :(得分:0)
.NET 2.0使用匿名委托回答(请注意,这仅适用于C#,VB.NET没有匿名委托)。
public void someMethod()
{
Uri u= new Uri("www.test.com");
CustomClass cc = this.files.find(delegate(CustomClass oTemp) { return oTemp.Path == u;});
}
答案 6 :(得分:0)
在Pavel的标记为答案的帖子中,我认为该行:
CustomClass cc = this.files.Find(cc => cc.Path == u);
应该是:
CustomClass cc = this.files.Find(cc2 => cc2.Path == u);
这是因为=>左边的表达式是一个变量定义(从表达式推断出类型) - 编译器会给出重定义错误。
此表达式也可以使用明确的定义编写:
CustomClass cc = this.files.Find((CustomClass cc2) => cc2.Path == u);
答案 7 :(得分:0)
这是我使用的解决方案。我需要传递几个参数,并且不想使用任何阻止我在运行时编辑方法的东西,所以我想出了这个。
显然,如果你想,你可以使用类型参数将其更改为通用方法(右项?)。这也解决了方法中lambdas的问题。不确定这是否也适用于匿名方法,但它已经分开,所以没什么大不了的。
我不知道反射会不会影响性能。
private Predicate<ItemData> FindItemData(string search, string fieldName)
{
var field = typeof(ItemData).GetField(fieldName);
return delegate(ItemData item) { return (string)field.GetValue(item) == search; };
}
//in another method...
itemlist.Find(FindItemData(e.Row[2].ToString(), "ItemName"));