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

发布于 2024-08-07 03:15:25 字数 860 浏览 4 评论 0原文

我无法弄清楚如何根据我将在运行时传入的值的使用来对列表进行“查找”。如果您看到我下面的代码,我希望能够在列表中找到其 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; }
    }
}

附言。我必须承认我不太遵循 doco 中的谓词内容 http:// /msdn.microsoft.com/en-us/library/x0b5b5bc.aspx

I can't work out how to do a "find" on a List I have based on use of a value that I'll pass in at run time. If you see my below code, I want to be able to find the CustomClass in the List for which it's Path parameter is equal to X, where X will be defined at run time.

Any ideas how to do such a find on a List? Or is this not possible without writing an iterator and doing the find manually? In which case perhaps there is a key'ed collection I should look at using instead?

   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. I must admit I don't quite follow the predicate stuff in the doco at http://msdn.microsoft.com/en-us/library/x0b5b5bc.aspx

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(8

爱人如己 2024-08-14 03:15:26
public void someMethod()
{
    Uri u= new Uri("www.test.com");
    CustomClass cc = this.files.find( p => { return p.Path == u; } );
}
public void someMethod()
{
    Uri u= new Uri("www.test.com");
    CustomClass cc = this.files.find( p => { return p.Path == u; } );
}
游魂 2024-08-14 03:15:26

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

Try using anonymous method for search and use any local variable you wish inside of it. If that is not satisfactory, call out your normally defined delegate method.

孤星 2024-08-14 03:15:26

.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;});
}

.NET 2.0 answer using an anonymous delegate (note that this only works for C#, VB.NET does not have anonymous delegates).

public void someMethod()
{
  Uri u= new Uri("www.test.com");
  CustomClass cc = this.files.find(delegate(CustomClass oTemp) { return oTemp.Path == u;});
}
枕花眠 2024-08-14 03:15:26

在 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);

In Pavel's post marked as answer, I think the line:

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

should be instead like:

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

This is because the expresion to the left of => is a variable definition (the type is inferred from the expression) - The compiler would gives a redefinition error otherwise.

This expression can also be written with an explicit definition as:

CustomClass cc = this.files.Find((CustomClass  cc2) => cc2.Path == u);
临走之时 2024-08-14 03:15:26

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

显然,如果您愿意,可以使用类型参数将其更改为通用方法(正确的术语?)。这也解决了方法中 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"));

Here is a solution that I used. I needed to pass several arguments and didn't want to use anything that would prevent me from editing the method during runtime, so I came up with this.

Obviously if you wanted to you could change it to a generic method (right term?) using type arguments. This also gets around the problem of lambdas in a method. Not sure if that applies to anonymous methods as well or not, but it is already separate so no big deal.

I don't know whether the reflection would have a performance hit or not.

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"));
美人骨 2024-08-14 03:15:25

使用 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));

Use a lambda:

 Uri u = new Uri("www.test.com");
 CustomClass cc = this.files.Find(cc => cc.Path == u);

or if you still want a named method:

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));
楠木可依 2024-08-14 03:15:25

您可以编写Find() 方法返回 null。

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

如果没有找到与谓词匹配的元素,

You can write

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

The Find() method returns null if no element was found that matches the predicate.

看春风乍起 2024-08-14 03:15:25

仅出于完整性考虑,如果您不想使用 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()

另请检查此线程:C# 中的谓词委托

For completeness sake only, here is what you would do if you didn't want to use a 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;
    }
}

And then use it as:

public void someMethod()
{
    Uri u = new Uri("www.test.com");
    UriMatcher matcher = new UriMatcher(u);
    CustomClass cc = this.files.Find(matcher.Match);
}

Note that you are passing a reference to a method, not the result of the method -- Match vs Match().

Check this thread also: Predicate Delegates in C#.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文