When you need to create an instance of a delegate which has a single parameter, lambda expressions allow you to create that delegate "inline" in a very concise manner. For instance, here's code to find a particular person in a list, by their name:
List<Person> list = new List<Person>();
// [..] Populate list here
Person jon = list.Find(p => p.Name == "Jon");
In C# 2.0 you could use an anonymous method which was a little bit more longwinded, but not too bad:
List<Person> list = new List<Person>();
// [..] Populate list here
Person jon = list.Find(delegate(Person p) { return p.Name == "Jon"; });
In C# 1.0 you'd have to create a whole extra method. In addition, if you wanted to parameterise it, you'd have to create a different type, whereas anonymous methods and lambda expressions capture their executing environment (local variables etc) so they act like closures:
public Person FindByName(List<Person> list, String name)
{
return list.Find(p => p.Name == name); // The "name" variable is captured
}
There's more about this in my article about closures.
While passing delegates into methods isn't terribly common in C# 2.0 and .NET 2.0, it's a large part of the basis of LINQ - so you tend to use it a lot in C# 3.0 with .NET 3.5.