It's essentially the same thing.
The delegate() { }
syntax was introduced in C# 2.0, while the lambda syntax was introduced in C# 3.0. They were designed with different goals in mind, but serve the same purpose.
Let me quote Eric Lippert (it's #7 on his top 10 worst C# features):
I think all concerned would agree that it's unfortunate to have two inconsistent syntaxes for what is basically the same thing. C# is stuck with it, though, because existing C# 2.0 code still uses the old syntax.
The "heaviness" of the C# 2.0 syntax was seen at the time as a benefit. The thought was that users might be confused by this new feature of nested methods, and the design team wanted a clear keyword in there calling out that a nested method was being converted to a delegate. No one could see into the future to know that a much lighter-weight syntax would be needed in a couple of years.
You won't see the delegate() { }
syntax being used much in new code nowadays, as virtually everyone prefers the lighter lambda =>
syntax.
new Predicate<FindPerson>
just types the delegate explicitly and isn't needed anymore. It used to be mandatory in C# 1 IIRC. It can be inferred in most cases so it can be omitted (see here for an example case when it's needed).
Its existence is due to the fact that a lambda is represented by a class instance under the hood, and in this particular case Predicate<T>
is that class. A "raw" lambda is untyped per se, but it can be implicitly converted to any compatible delegate type.
For instance, Predicate<FindPerson>
is a compatible delegate type in this example, but so is Func<FindPerson, bool>
. The same lambda would also be convertible to Expression<Func<FindPerson, bool>>
, but this is an entirely different matter. This is why you can't write var fn = (int x) => x;
in C#, as
the type of fn
cannot be inferred from this expression alone.
As a recap, these are all equivalents:
// Compact lambda
lst.Find(a => a.Name.Equals("Alex"))
// Explicitly typed parameter
lst.Find((FindPerson a) => a.Name.Equals("Alex"))
// Explicit delegate type
lst.Find(new Predicate<FindPerson>(a => a.Name.Equals("Alex")))
// Combination of the two above
lst.Find(new Predicate<FindPerson>((FindPerson a) => a.Name.Equals("Alex")))
// Explicit delegate type through casting
lst.Find((Predicate<FindPerson>)(a => a.Name.Equals("Alex")))
// Lambda block
lst.Find(a => { return a.Name.Equals("Alex"); })
// Delegate block
lst.Find((Predicate<FindPerson>)(delegate(FindPerson a) { return a.Name.Equals("Alex"); }))
// ... etc