If you're just learning C# you've probably come across something like this and wondered what the weird x=>x
is all about...
things.SingleOrDefault(x=>x.Name == "Bob");
To understand what's going on, let's explore a specific example.
Let's say you have a collection of People.
Here's a class to represent a Person...
public class Person
{
public string Name { get; set; }
public int Age { get; set; }
}
Then somewhere in your application, a list of people like this...
private List<Person> People = new List<Person>
{
new Person { Name = "Bob", Age = 37 },
new Person { Name = "Brian", Age = 21 },
new Person { Name = "Amy", Age = 58 }
};
Three people in a list. Each object in the list is an instance of our
Person
class.
Now say you want to find the record for "Amy" and display her age.
You could do this manually by looping through each person until you find
the relevant one...
public void Exists()
{
Person result = null;
foreach (var person in People)
{
if (person.Name == "Amy")
{
result = person;
break;
}
}
if (result != null)
Console.WriteLine("we found Amy!, she's " + result.Age);
}
Result will be the instance of "Person" for Amy and we can write her age to
the console.
Alternatively, rather than typing out endless loops yourself, you can use
some methods built in to C# lists to save yourself a few keystrokes.
public void Exists()
{
var amy = People.SingleOrDefault(IsAmy);
}
Under the covers, this will loop through the "People" list, and for each
one it will call IsAmy
to determine whether this is the person we want.
What does IsAmy
look like I hear you ask.
private bool IsAmy(Person arg)
{
return arg.Name == "Amy";
}
SingleOrDefault
expects a function, which takes a Person
and returns a bool
.
In here we can put whatever logic we want.
If IsAmy
returns true
, then we're saying this instance of Person
is the
one we want. If we return false
we're saying it isn't.
We can "inline" our IsAmy
function (to save declaring it separately) like
so...
public void Exists()
{
var amy = People.SingleOrDefault((Person person) =>
{ return person.Name == "Amy" });
}
This is exactly the same as the last example, except instead of declaring a
separate function we're declaring it "inline".
You can see we're still taking in a Person
argument, then returning a
true
or false
(true if "Amy", false if not).
Finally, to make this more concise, we can simplify to this...
public void Exists()
{
var amy = People.SingleOrDefault(person => person.Name == "Amy");
}
This is another way of declaring the same thing.
Here, we are still taking the Person
, applying our condition to it and
returning the result (true or false) but with less keystrokes!
So the left side of the => is the argument (Person
), the right side is the
expression which returns a boolean.
Essentially lambdas are really just syntactic sugar and a shorthand way of
declaring a function.
You'll see them used a lot with lists/other collections and therefore in
relation to database queries etc.
Top comments (7)
If anyone's coming from "JavaScript" background, you will find that it works very similar to the JavaScript's lambda.
To show the similarity (using the examples in this article)
1 - You can leave out
()
if you have only one argument passed.2 - You can pass the method name
Both lambda syntax are the same in C# & JavaScript.
You can go one step further:
things.SingleOrDefault(({name}) => name === "Bob");
I wasn't able to replicate the object desconstruction in C# as you could do in JavaScript (even after implementing Deconstruct)
dotnetfiddle.net/Wbx3ac
And Roslyn 2.0 compiler complains...
Sorry, I was talking explicitly on JS terms
No worries, mate~ 😉
I think it's worth pointing out that a lambda is not simply a shorthand for function declaration.
IsAmy
is a function. The other two variants are both lambdas and they differ from functions in that they capture all the locals and globals that are visible in the scope where the lambda is defined.IsAmy
has no access to those.Thanks for this, an important clarification and I appreciate you taking the time to outline it here :-)