2008-10-28 22 views
21

Po patrząc na MSDN, to wciąż dla mnie jasne, w jaki sposób należy tworzyć prawidłowe orzeczenie korzystania z metody find() w wykazie stosując zmienną składową o T (gdzie T jest klasa)Jak utworzyć dobrego delegata predykatów na Znajdź() coś na mojej liście <T>?

Na przykład:

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

Jak powinien wyglądać mój predykat "byYear"?

(przykład MSDN mówi jedynie o listę dinozaurów i tylko wyszukiwań dla wartości niezmienne „Saurus” - nie pokazuje, jak przekazać wartość do orzecznika ...)

EDIT: Używam VS2005/.NET2.0, więc nie sądzę, że notacja Lambda jest dostępna dla mnie ...

EDIT2: Usunięto "1999" w tym przykładzie, ponieważ mogę chcieć "Znajdź" programowo na podstawie różne wartości. Przykład zmieniono na zakres samochodów od 1980 do 2000 za pomocą pętli for-do.

+0

Poprosiłem podobny [Pytanie] (http://stackoverflow.com/questions/200151/search-for-object-in-generic-list) i uzyskał kilka naprawdę doskonałych odpowiedzi! –

Odpowiedz

29

Ok, w .NET 2.0 możesz używać delegatów, tak jak:

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

* śmieje się z kodu C# 3.0 * Jestem zazdrosny. Chyba powinienem uaktualnić do VS2008, co? Dzięki za pomoc! – Pretzel

+0

Zmienna w "var car99 =" ... sprawia, że ​​czuję się trochę nieswojo. W tym przypadku bardziej prawdopodobne jest użycie "Car car99 =" ... Prawdopodobnie najlepiej jest omówić jeszcze gdzie - http://stackoverflow.com/questions/41479/use-of-var-keyword-in-c –

+0

Co czy mogę powiedzieć? Jestem wariatką. –

2

Hmm. Myśląc o tym więcej, możesz użyć currying, aby zwrócić predykat.

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

Teraz można przekazać wynik tej funkcji (co jest orzecznikiem) do metody znajdują się:

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

Myślę, że Find() chce predykatu , a nie Func . Próbowałem to nie będzie kompilacji na liście w 3.0 ...? – Codewerks

+0

Ten kod używa predykatu . Kompiluje się dobrze. "byYear" zwraca predykat , który jest następnie przekazywany do cars.Find(). –

27

Można użyć wyrażenia lambda w następujący sposób:

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

Albo można użyć anonimowego delegata:

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, anonimowy delegat. To może być dobre w szczypie. Dzięki! (no i witamy w StackOverflow.) – Pretzel

+0

Przerywa edycję + kontynuuj, chociaż niestety ... –

7

Ponieważ nie można użyć lambda można po prostu zastąpić go anonimowego delegata.

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

Można to wykorzystać też:

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