Consider it without any of the LINQ/lambda mumbo jumbo:
bool IsAnythingNegative(int[] numbers) { bool result = false; foreach (int x in numbers) { if (x < 0) { result = true; break; } } return result; }Now, let's factor out a method and call it
IsNegative
:
bool IsNegative(int x) { return x < 0; } bool IsAnythingNegative(int[] numbers) { bool result = false; foreach (int x in numbers) { if (IsNegative(x)) { result = true; break; } } return result; }The code above works great. However, there's a lot of it, thus more opportunity for bugs. Not only that, but it is a common algorithm to determine if any element in an array satisfies a certain condition (in this case, whether any element is negative). Surely there's a way to make the code simpler and more readable. There is. This is where LINQ shines! Let's use LINQ, but no Lambdas yet:
bool IsNegative(int x) { return x < 0; } bool IsAnythingNegative(int[] numbers) { bool result = false; result = numbers.Any(IsNegative); return result }We are calling a LINQ method called
Any
. The Any
method takes a single argument which is yet another method (in our case, the IsNegative
method). That method must take a single int
argument (because the array contains only integers) and return a bool
. The functionality of Any
is to return true if any element in the array matches the specified condition (in our case, if the number is negative).
Ok great, we simplified the code and reduced the chance for bugs to sneak in. However, the
IsNegative
method may not need to be used by anyone other than the IsAnythingNegative
method. In this case, it is just overhead to have to define a separate IsNegative
method, and it fragments the code. So, let's accomplish the same thing with an anonymous method defined in-line.
bool IsAnythingNegative(int[] numbers) { bool result = false; result = numbers.Any ( (int x) => // anonymous method takes a single argument { return x < 0; // method body is a single statement } ); return result }Don't freak out yet, this is just syntax. We are defining an anonymous method which takes a single
int
argument named x
. The method body consists of a single statement: return x < 0;
. And thus, the method returns bool
. This anonymous method is just like IsNegative
. Guess what, you just wrote a lambda expression!
Ok,
x
must be int
since numbers
only contains int
, so let's remove that redundancy:
bool IsAnythingNegative(int[] numbers) { bool result = false; result = numbers.Any ( (x) => // int can go away { return x < 0; } ); return result }.NET provides a shortcut for lambdas which take a single argument and return a single result:
bool IsAnythingNegative(int[] numbers) { bool result = false; result = numbers.Any ( x => // () can go away // {} can go away x < 0 // return can go away and ; can go away ); return result }Whitespaces removed:
bool IsAnythingNegative(int[] numbers) { bool result = false; result = numbers.Any(x => x < 0); return result }And now, we finally arrived at the all-too-confusing lambda expression => < ( > % #(*^!^$%$%#@**($ syntax.
Here are some other fun methods to play with:
bool areAllEven = numbers.All(x => x % 2 == 0); int[] justTheNegatives = numbers.Where(x => x < 0).ToArray();Hopefully this helps ease you into the new syntax.