7

実行時に渡す値の使用に基づいて、リストで「検索」を行う方法がわかりません。以下のコードが表示されている場合は、Path パラメーターが X に等しい List 内の 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

ラムダを使用します。

 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

完全を期すために、ラムダを使用したくない場合は次のようにします。

// 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くださいMatch()

このスレッドも確認してください: Predicate Delegates in C#

于 2009-10-07T07:44:30.753 に答える
0

匿名デリゲートを使用した.NET2.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

検索に匿名メソッドを使用してみて、その中で必要なローカル変数を使用してください。それでも不十分な場合は、通常定義されているデリゲートメソッドを呼び出します。

于 2009-10-07T07:09:10.077 に答える
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
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

これが私が使用した解決策です。いくつかの引数を渡す必要があり、実行時にメソッドを編集するのを妨げるものは何も使用したくなかったので、これを思いつきました。

明らかに、必要に応じて、型引数を使用してジェネリック メソッド (正しい用語ですか?) に変更できます。これにより、メソッド内のラムダの問題も回避されます。それが匿名メソッドにも当てはまるかどうかはわかりませんが、すでに分離されているので大したことではありません。

リフレクションがパフォーマンスに影響を与えるかどうかはわかりません。

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 に答える