2008-10-28 12 views
21

Nach einem Blick auf MSDN, dann ist es mir noch nicht klar, wie ich ein richtiges Prädikat bilden sollte die Find() -Methode in List mit einer Membervariable von T (wobei T eine Klasse)Wie formiere ich einen guten Prädikatdelegaten zu Find() etwas in meiner Liste <T>?

Zum Beispiel zu verwenden:

public class Car 
{ 
    public string Make; 
    public string Model; 
    public int Year; 
} 

{ // somewhere in my code 
    List<Car> carList = new List<Car>(); 
    // ... code to add Cars ... 

    Car myCar = new Car(); 

    // Find the first of each car made between 1980 and 2000 
    for (int x = 1980; x < 2000; x++) 
    { 
     myCar = carList.Find(byYear(x)); 
     Console.Writeline(myCar.Make + myCar.Model); 
    } 
} 

Wie soll mein Prädikat "byYear" aussehen?

(MSDN Beispiel nur Gespräche über eine Liste der Dinosaurier und nur sucht nach einem unveränderlichen Wert „Saurus“ - Es zeigt nicht, wie ein Wert in das Prädikat passieren ...)

EDIT: ich verwende VS2005/.NET2.0, so dass ich glaube nicht, Lambda-Notation mir zur Verfügung steht ...

EDIT2: entfernt „1999“ in dem Beispiel, weil ich „Suche“ programmatisch kann wollen, basierend auf verschiedene Werte. Das Beispiel wurde von 1980 bis 2000 unter Verwendung der For-do-Schleife in eine Reihe von Autos geändert.

+0

ich ein ähnliches [Frage] Fragen (http://stackoverflow.com/questions/200151/search-for-object-in-generic-list) und bekam einige wirklich gute Antworten! –

Antwort

29

ok, in .NET 2.0 können Sie Delegaten verwenden, etwa so:

static Predicate<Car> ByYear(int year) 
{ 
    return delegate(Car car) 
    { 
     return car.Year == year; 
    }; 
} 

static void Main(string[] args) 
{ 
    // yeah, this bit is C# 3.0, but ignore it - it's just setting up the list. 
    List<Car> list = new List<Car> 
    { 
     new Car { Year = 1940 }, 
     new Car { Year = 1965 }, 
     new Car { Year = 1973 }, 
     new Car { Year = 1999 } 
    }; 
    var car99 = list.Find(ByYear(1999)); 
    var car65 = list.Find(ByYear(1965)); 

    Console.WriteLine(car99.Year); 
    Console.WriteLine(car65.Year); 
} 
+0

* lacht über den C# 3.0-Code * Ich bin eifersüchtig. Ich denke, ich sollte auf VS2008 upgraden, oder? Danke für die Hilfe! – Pretzel

+0

Die Var in "var car99 =" ... macht mich ein bisschen unwohl. In diesem Fall würde ich eher "Auto car99 =" verwenden ... Wahrscheinlich am besten wo sonst diskutiert - http://StackOverflow.com/questions/41479/use-of-var-keyword-in-c –

+0

Was? Kann ich sagen? Ich bin ein var-Verrückter. –

2

Hmm. Wenn Sie mehr darüber nachdenken, können Sie Curry verwenden, um ein Prädikat zurückzugeben.

Func<int, Predicate<Car>> byYear = i => (c => c.Year == i); 

Jetzt können Sie das Ergebnis dieser Funktion übergeben (das ist ein Prädikat), um Ihre Methode Suchen:

my99Car = cars.Find(byYear(1999)); 
my65Car = cars.Find(byYear(1965)); 
+0

Ich denke Find() will ein Prädikat , kein Func . Versucht dies, wird es nicht auf einer Liste in 3.0 kompilieren ...? – Codewerks

+0

Dieser Code verwendet Prädikat . Es kompiliert einfach gut. "byYear" gibt ein Prädikat zurück, das dann an cars.Find() übergeben wird. –

27

Sie einen Lambda-Ausdruck verwenden können, wie folgt:

myCar = carList.Find(car => car.Year == 1999); 
14

Oder Sie können einen anonymen Delegaten verwenden:

Car myCar = cars.Find(delegate(Car c) { return c.Year == x; }); 

// If not found myCar will be null 
if (myCar != null) 
{ 
    Console.Writeline(myCar.Make + myCar.Model); 
} 
+0

Oooh, anonymer Delegierter. Dies könnte im Notfall gut sein. Vielen Dank! (oh, und willkommen zu StackOverflow.) – Pretzel

+0

Es bricht Edit + Continue obwohl leider ... –

7

Da Sie nicht Lambda verwenden, können Sie es mit einem anonymen Delegierten nur ersetzen kann.

myCar = carList.Find(delegate(Car car) { return car.Year == i; }); 
1

Sie können dies auch nutzen:

var existData = 
    cars.Find(
    c => c.Year== 1999);