2009-10-07 5 views
7

Ich kann nicht herausfinden, wie man eine "Suche" in einer Liste durchführt, die auf der Verwendung eines Werts basiert, den ich zur Laufzeit übergebe. Wenn Sie meinen unteren Code sehen, möchte ich die CustomClass in der Liste finden können, für die der Path-Parameter gleich X ist, wobei X zur Laufzeit definiert wird.C# List.Find-Methode - wie kann ich einen Wert in das Prädikat übergeben?

Irgendwelche Ideen wie man so einen Fund auf einer Liste macht? Oder ist das nicht möglich, ohne einen Iterator zu schreiben und die Suche manuell durchzuführen? In diesem Fall gibt es vielleicht eine Schlüsselsammlung, die ich stattdessen verwenden sollte?

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. Ich muss zugeben, dass ich nicht ganz das Prädikat Sachen in der doco folgen bei http://msdn.microsoft.com/en-us/library/x0b5b5bc.aspx

Antwort

12

Verwenden Sie ein Lambda:

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

oder wenn Sie noch eine benannte Methode wollen:

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

danke Jungs - nebenbei bemerkt - sollte ich in der Lage gewesen sein (wenn ich mehr auf C# hatte), indem ich nur die Syntax für die Methode in der Doco? (z. B. Parameter, match, Typ: System .. ::. Prädikat <(Of <(T>)>), Das Prädikat <(Of <(T>)>) Delegate, definiert die Bedingungen des Elements für die Suche nach ... – Greg

+0

Parametertyp beschränkt den Typ von Delegat, das Sie an die Methode übergeben können, und somit die Signatur der Methode oder des Lambda, die Sie verwenden müssen, um diesen Delegaten zu erstellen. Es bedeutet an und für sich nicht mehr die Verwendung von Lambdas als jeder andere Delegattyp. Dokumentation für Lambdas ist hier: http://msdn.microsoft.com/en-us/library/bb397687.aspx –

+1

Delegate ähnelt einem Funktionszeiger. Durch Betrachten der Signatur ('delegate bool Prädikat (T obj)') können Sie sehen, dass ein Prädikat eine Funktion (Methode) ist, die einen ** einzigen Parameter vom Typ T ** und einen ** bool ** zurückgibt. . – Groo

1

Sie

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

Die Find() Methode gibt null schreiben kann, wenn kein Element gefunden wurde, daß das Prädikat übereinstimmt.

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

Warum Aussage Lambda? –

+0

PEBAK. Gehirnfurz. Treffen Sie Ihre Wahl. –

0

Versuchen anonyme Methode für die Suche und verwenden alle lokalen Variablen, die Sie in der es wünschen . Wenn das nicht zufriedenstellend ist, rufen Sie Ihre normalerweise definierte Delegiertenmethode auf. nur

1

Der Vollständigkeit halber ist hier, was Sie tun würden, wenn Sie kein Lambda verwenden wollen:

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

Beachten Sie, dass Sie sind:

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

und dann als verwenden Passing eine Verweis auf eine Methode, nicht das Ergebnis der Methode - Match vs Match().

Überprüfen Sie diesen Thread auch: Predicate Delegates in C#.

0

.NET 2.0 Antwort mit einem anonymen Delegaten (Beachten Sie, dass dies nur für C# funktioniert, VB.NET hat keine anonymen Delegaten).

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

In Pavel Posten als Antwort markiert, denke ich die Zeile:

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

links von => ist dies, weil die expresion:

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

statt sein sollte eine Variablendefinition (der Typ wird aus dem Ausdruck abgeleitet) - Der Compiler würde andernfalls einen Neudefinitionsfehler ergeben.

Dieser Ausdruck kann auch mit einer expliziten Definition wie folgt geschrieben werden:

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

Hier ist eine Lösung, die ich verwenden.Ich musste mehrere Argumente übergeben und wollte nichts verwenden, was mich daran hindern würde, die Methode zur Laufzeit zu bearbeiten, also kam ich auf diese Idee.

Offensichtlich, wenn Sie wollten, könnten Sie es zu einer generischen Methode (richtiger Begriff?) Mit Typargumenten ändern. Dies löst auch das Problem der Lambdas in einer Methode. Nicht sicher, ob das auch für anonyme Methoden gilt oder nicht, aber es ist schon getrennt, also keine große Sache.

Ich weiß nicht, ob die Reflexion einen Leistungseinbruch haben würde oder nicht.

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

Ich werde sagen, dass ich nicht überprüft habe, dass es mich Änderungen machen lässt, aber ansonsten funktioniert es sehr gut. –