2009-10-07 14 views
7

私は、実行時に渡す値の使用に基づいて、リスト上で「検索」を実行する方法を試すことができません。下のコードが表示されている場合は、そのパスのパラメータがXであるList内のCustomClassを検索できるようにしたいと考えています(Xは実行時に定義されます)。C#List.Findメソッド - どのようにして述語に値を渡すことができますか?

リストにそのような検索を行う方法はありますか?または、イテレータを作成せずに手動で検索を行うことはできませんか?どのような場合には、代わりにキーを使用するコレクションがありますか?

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。私は、私は非常にあなたは何の要素が述語に一致する見つからなかった場合、検索()メソッドはnullを返します

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

を書くことができますhttp://msdn.microsoft.com/en-us/library/x0b5b5bc.aspx

答えて

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)); 
+0

ドコのメソッドの構文を調べるだけで、私はもっと上手くいけばいいのですか?パラメータ: 種類:System .. ::。Predicate <(Of <(T>)>)、 The述語<(Of <(T>)>)委任先。検索する要素の条件を定義します。 – Greg

+0

パラメータの種類によって、デリゲートをメソッドに渡すことができます。したがって、そのデリゲートを作成するために使用するメソッドまたはラムダのシグネチャです。他のデリゲート型よりもラムダの使用を意味するものではありません。 lambdaのドキュメントは次のとおりです。http://msdn.microsoft.com/en-us/library/bb397687.aspx –

+1

代理人は、関数ポインタに似ています。署名( 'delegate bool Predicate (T obj)')を見ると、述語はT **型の**単一パラメータをとり、** bool **を返す関数(メソッド)であることがわかります。 – Groo

1

でDOCOに述語のものに従わない認めなければなりません。

0
public void someMethod() 
{ 
    Uri u= new Uri("www.test.com"); 
    CustomClass cc = this.files.find(p => { return p.Path == u; }); 
} 
+0

なぜ文のラムダですか? –

+0

PEBCAK。脳のおなら。好きなのを選びな。 –

0

が検索に匿名メソッドを使用してみてください、あなたはそれの内側に望む任意のローカル変数を使用します。それが満足できない場合は、通常定義されているデリゲートメソッドを呼び出してください。その後、

// 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; 
    } 
} 

としてそれを使用します:完全性期すため

1

だけ、ここにあなたがラムダを使いたくなかった場合はどうなるのかであるあなたがあることを

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

注意の参照をメソッドに渡します。メソッドの結果ではありません。Matchとです。

このスレッドもチェック:Predicate Delegates in C#

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

、私はライン思う:=の左側にexpresion>があるためです

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

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

が代わりにようにする必要があります変数の定義(型は式から推論されます) - コンパイラはそれ以外の場合は再定義エラーを返します。

この式はまた、明示的な定義を書くことができます。ここでは

CustomClass cc = this.files.Find((CustomClass cc2) => cc2.Path == u); 
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")); 
+0

私はそれが私が編集をさせてくれることを二重チェックしていないと言いますが、そうでなければそれはとてもうまくいきます。 –

関連する問題