25

After looking on MSDN, it's still unclear to me how I should form a proper predicate to use the Find() method in List using a member variable of T (where T is a class)

For example:

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

What should my "byYear" predicate look like?

(The MSDN example only talks about a List of dinosaurs and only searches for an unchanging value "saurus" -- It doesn't show how to pass a value into the predicate...)

EDIT: I'm using VS2005/.NET2.0, so I don't think Lambda notation is available to me...

EDIT2: Removed "1999" in the example because I may want to "Find" programatically based on different values. Example changed to range of cars from 1980 to 2000 using for-do loop.

Pretzel
  • 8,141
  • 16
  • 59
  • 84
  • 1
    I asked a similar [question](http://stackoverflow.com/questions/200151/search-for-object-in-generic-list) and got some really excellent answers! – Saif Khan Oct 28 '08 at 05:35

6 Answers6

32

You can use a lambda expression as follows:

myCar = carList.Find(car => car.Year == 1999);
Dan Finucane
  • 1,547
  • 2
  • 18
  • 27
30

Ok, in .NET 2.0 you can use delegates, like 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);
}
Matt Hamilton
  • 200,371
  • 61
  • 386
  • 320
  • *laughs at the C# 3.0 code* I'm jealous. Guess I should upgrade to VS2008, huh? Thanks for the help! – Pretzel Oct 28 '08 at 02:20
  • The var in "var car99 = "... makes me a little uncomfortable. In this case I'd be more likely to use "Car car99 = "... Probably best discussed else where - http://stackoverflow.com/questions/41479/use-of-var-keyword-in-c – Daniel Ballinger Mar 17 '09 at 22:36
  • What can I say? I'm a var nutcase. – Matt Hamilton Mar 17 '09 at 23:42
  • Best example of Predicate I've seen yet, especially when you need to pass a value to search and not be expected to hardcode a value to compare inside the predicate method – Fandango68 May 24 '17 at 23:47
15

Or you can use an anonymous delegate:

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);
}
Todd
  • 5,017
  • 1
  • 25
  • 16
  • Oooh, anonymous delegate. This could be good in a pinch. Thanks! (oh, and welcome to StackOverflow.) – Pretzel Oct 28 '08 at 02:35
7

Since you can't use lambda you can just replace it with an anonymous delegate.

myCar = carList.Find(delegate(Car car) { return car.Year == i; });
Ajaxx
  • 2,500
  • 4
  • 27
  • 38
2

Hmm. Thinking more about it, you could use currying to return a predicate.

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

Now you can pass the result of this function (which is a predicate) to your Find method:

my99Car = cars.Find(byYear(1999));
my65Car = cars.Find(byYear(1965));
Matt Hamilton
  • 200,371
  • 61
  • 386
  • 320
1

You can use this too:

var existData =
    cars.Find(
     c => c.Year== 1999);
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
phclummia
  • 11
  • 1