Как сформировать хороший делегат-предикат для Find() чего-либо в моем List‹T›?

После просмотра MSDN мне все еще неясно, как мне сформировать правильный предикат для использования метода Find() в списке с использованием переменной-члена T (где T - класс)

Например:

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

Как должен выглядеть мой предикат byYear?

(Пример MSDN говорит только о списке динозавров и ищет только неизменное значение «заурус» - он не показывает, как передать значение в предикат...)

РЕДАКТИРОВАТЬ: я использую VS2005/.NET2.0, поэтому я не думаю, что нотация Lambda мне доступна...

EDIT2: в примере удалено «1999», потому что я могу захотеть «найти» программно на основе разных значений. Пример изменен на диапазон автомобилей с 1980 по 2000 год с использованием цикла for-do.


person Pretzel    schedule 28.10.2008    source источник
comment
Я задал аналогичный вопрос и получил отличные ответы!   -  person Saif Khan    schedule 28.10.2008


Ответы (6)


Хорошо, в .NET 2.0 вы можете использовать делегатов, например:

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);
}
person Matt Hamilton    schedule 28.10.2008
comment
смеется над кодом C# 3.0 Я завидую. Думаю, мне стоит перейти на VS2008, а? Спасибо за помощь! - person Pretzel; 28.10.2008
comment
Вар в var car99 = ... меня немного смущает. В этом случае я бы с большей вероятностью использовал Car car99 = ... Вероятно, лучше всего обсудить это в другом месте - stackoverflow.com/questions/41479/use-of-var-keyword-in-c - person Daniel Ballinger; 18.03.2009
comment
Что я могу сказать? Я вар псих. - person Matt Hamilton; 18.03.2009
comment
Лучший пример предиката, который я когда-либо видел, особенно когда вам нужно передать значение для поиска и не ожидать, что значение будет жестко закодировано для сравнения внутри метода предиката. - person Fandango68; 25.05.2017

Вы можете использовать лямбда-выражение следующим образом:

myCar = carList.Find(car => car.Year == 1999);
person Dan Finucane    schedule 28.10.2008
comment
Не подходит для VS2005/.NET2.0, но самое элегантное решение. - person Tom; 19.04.2018

Или вы можете использовать анонимного делегата:

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);
}
person Todd    schedule 28.10.2008
comment
Ооо, анонимный делегат. Это может быть хорошо в крайнем случае. Спасибо! (о, и добро пожаловать в StackOverflow.) - person Pretzel; 28.10.2008

Поскольку вы не можете использовать лямбду, вы можете просто заменить ее анонимным делегатом.

myCar = carList.Find(delegate(Car car) { return car.Year == i; });
person Ajaxx    schedule 28.10.2008

Хм. Если подумать, вы можете использовать каррирование для возврата предиката.

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

Теперь вы можете передать результат этой функции (которая является предикатом) вашему методу Find:

my99Car = cars.Find(byYear(1999));
my65Car = cars.Find(byYear(1965));
person Matt Hamilton    schedule 28.10.2008
comment
Я думаю, что Find() хочет Predicate‹T›, а не Func‹T,T›. Пробовал это, он не будет компилироваться в списке в 3.0...? - person Codewerks; 28.10.2008
comment
Этот код использует Predicate‹T›. Он компилируется просто отлично. byYear возвращает предикат Car›, который затем передается в cars.Find(). - person Matt Hamilton; 28.10.2008

Вы также можете использовать это:

var existData =
    cars.Find(
     c => c.Year== 1999);
person phclummia    schedule 07.05.2014