C#List.Find方法 - 如何将值传递给谓词?

时间:2009-10-07 06:28:55

标签: c# list collections find predicate

我无法弄清楚如何根据我在运行时传入的值使用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中的谓词

8 个答案:

答案 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"));