7

我不知道如何根据我将在运行时传入的值在我拥有的列表上进行“查找”。如果您看到我下面的代码,我希望能够在 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 中的谓词内容

4

8 回答 8

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));
于 2009-10-07T06:32:22.337 回答
1

你可以写

CustomClass cc = this.files.Find( p=> p.Path == u );

如果没有找到与谓词匹配的元素,则 Find() 方法返回 null。

于 2009-10-07T06:31:32.603 回答
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);
}

请注意,您传递的是对方法的引用,而不是方法的结果 -MatchMatch()

还要检查这个线程:Predicate Delegates in C#

于 2009-10-07T07:44:30.753 回答
0
public void someMethod()
{
    Uri u= new Uri("www.test.com");
    CustomClass cc = this.files.find( p => { return p.Path == u; } );
}
于 2009-10-07T06:32:37.870 回答
0

尝试使用匿名方法进行搜索并使用您希望在其中的任何局部变量。如果这不令人满意,请调用您通常定义的委托方法。

于 2009-10-07T07:09:10.077 回答
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;});
}
于 2009-10-07T12:23:48.043 回答
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);
于 2012-08-01T09:11:37.130 回答
0

这是我使用的解决方案。我需要传递几个参数并且不想使用任何会阻止我在运行时编辑方法的东西,所以我想出了这个。

显然,如果您愿意,可以使用类型参数将其更改为通用方法(正确的术语?)。这也解决了方法中的 lambda 问题。不确定这是否也适用于匿名方法,但它已经是独立的,所以没什么大不了的。

我不知道反射是否会对性能产生影响。

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"));
于 2013-07-02T15:53:16.150 回答