C
C#15mo ago
Emelie

❔ Help me understand this lambda expression

var myKey = availableProducts.FirstOrDefault(x => x.Value == input).Key; Console.WriteLine("Quantity: left " + myKey); Im trying to understand how this code works (how it gets the key for the input value in a dictionary). Been searching the web but not really getting more clear.. mostly I dont understand the use of "x". Many thanks for any help!
80 Replies
cap5lut
cap5lut15mo ago
the lamba is basically just a function that takes a KeyValuePair<TKey, TValue> and returns a bool x is the parameter name chosen, u could use also any other valid name for that. if u would write the lambda as function manually (lets assume that both the TKey and the TValue are ints for simplicity), it would look like this:
int input; // capured input value

bool MyLambda(KeyValuePair<int, int> x /* the parameter name x */)
{
return x.Value == input; // the lambda method body
}
int input; // capured input value

bool MyLambda(KeyValuePair<int, int> x /* the parameter name x */)
{
return x.Value == input; // the lambda method body
}
FirstOrDefault() is a LINQ extension method on IEnumerable<T> and takes a Func<T, bool> as parameter Dictionary<TKey, TValue> implements this interface as IEnumerable<KeyValuePair<TKey, TVAlue>> so it results in the Func<KeyValuePair<int, int>, bool> from the example
Emelie
EmelieOP15mo ago
Sorry for a probably stupid question, but what is a LINQ extension method?
cap5lut
cap5lut15mo ago
do u know what extension methods are in general?
Angius
Angius15mo ago
An extension method is a method that's added to the class from outside of the class
Emelie
EmelieOP15mo ago
not really :/
Angius
Angius15mo ago
Syntactic sugar over static methods, really LINQ is a collection of such methods that extend the IEnumerable
Emelie
EmelieOP15mo ago
why is it added from outside the class?
Angius
Angius15mo ago
Because you can't always just modify the class itself You can't modify int to add new methods, can you? But you can write an extension method for int
cap5lut
cap5lut15mo ago
yeah u can basically "add methods" to another class
public static void PrintMeUpperCase(this string value)
{
Console.WriteLine(value.ToUpper());
}

"hello world".PrintMeUpperCase();
public static void PrintMeUpperCase(this string value)
{
Console.WriteLine(value.ToUpper());
}

"hello world".PrintMeUpperCase();
this would print HELLO WORLD and it looks like the method is part of the string class
Emelie
EmelieOP15mo ago
what is meant by "modifying int" , in this context? I think Im getting it
Angius
Angius15mo ago
Well, int is a struct That has value, properties, and what not You can't just edit the source code of .NET standard library to add new methods to that int struct
Emelie
EmelieOP15mo ago
I also have a really hard time understanding exactly what a struct is, which probably makes it all even harder
Angius
Angius15mo ago
Funky class For all intents and purposes
cap5lut
cap5lut15mo ago
LINQ is a powerful collection of such extension methods to simplify handling a lot of data the same way
Emelie
EmelieOP15mo ago
so, FirstOrDefault is an extented method
cap5lut
cap5lut15mo ago
yes
Emelie
EmelieOP15mo ago
on the enumerable interface?
cap5lut
cap5lut15mo ago
yep
Emelie
EmelieOP15mo ago
which the dictionary implements?
cap5lut
cap5lut15mo ago
correct
Emelie
EmelieOP15mo ago
but why is it called a lambda function?
Angius
Angius15mo ago
The name "lambda" comes from math, IIRC You can call it an "anonymous function" Both names are correct
Azrael
Azrael15mo ago
I prefer Anonymous functions.
Emelie
EmelieOP15mo ago
okay! but is there any point in making it anonymous? could it also be written non-anonymous?
Angius
Angius15mo ago
Sure
Azrael
Azrael15mo ago
Yes. I prefer not using anonymous functions, I focus on readability.
cap5lut
cap5lut15mo ago
its actually lambda "expression", a lambda on its own isnt a complete function, it always needs a delegate type to be assigned to. no matter if thats a method parameter like in the FirstOrDefault() case or if its a local variable
Angius
Angius15mo ago
You can use not-anon functions, but it will just uselessly bloat your code
Emelie
EmelieOP15mo ago
but if the lambda uses parameters (keyValuePair<TKey, TValue) and returns a bool, is it not a function?
Angius
Angius15mo ago
Why write
public static bool IsCountMoreThanFour(Thing x)
{
return x.Count > 4;
}
public static bool IsCountMoreThanFour(Thing x)
{
return x.Count > 4;
}
and
stuff.Where(IsCountMoreThanFour)
stuff.Where(IsCountMoreThanFour)
when you can write
stuff.Where(x => x.Count > 4)
stuff.Where(x => x.Count > 4)
Why would it not be?
cap5lut
cap5lut15mo ago
the type here defines what the lambda is mapped to
Func<int, int, int> addMethod = (a, b) => a + b;
Func<int, int, int> addMethod = (a, b) => a + b;
its a Func delegate, that takes two ints (first two generic parameters) and returns an int (last one)
Emelie
EmelieOP15mo ago
@ZZZZZZZZZZZZZZZZZZZZZZZZZ what @cap5lut wrote a bit earlier! that it isnt completely a function "its actually lambda "expression", a lambda on its own isnt a complete function, it always needs a delegate type to be assigned to. no matter if thats a method parameter like in the FirstOrDefault() case or if its a local variable"
Azrael
Azrael15mo ago
It’s still a function.
cap5lut
cap5lut15mo ago
its not a function on its own, it only makes sense in combination with a delegate type
Emelie
EmelieOP15mo ago
and what is a delegate type 😅
Angius
Angius15mo ago
A type that describes the function
cap5lut
cap5lut15mo ago
it basically defines a method signature/method type, return type and its parameter list
Angius
Angius15mo ago
Func<int, string, string> for example would be a function that takes two strings and returns an int
Emelie
EmelieOP15mo ago
like the actual function name? would that be the delegate?
Angius
Angius15mo ago
I think we're getting way deeper into it than necessary lol
cap5lut
cap5lut15mo ago
delegate int LengthGetter(string value) would be a delegate declaration which can then be later used: LengthGetter lengthGetter = str => str.Length;
Emelie
EmelieOP15mo ago
ok, I think I need to read up on a few things, haha but this is what Im getting: FirstOrDefault is an extended method from the enumerable interface which the dictionary implements
Angius
Angius15mo ago
*extension *IEnumerable But yes
Emelie
EmelieOP15mo ago
and as a PARAMETER, a lambda expression is used (also called an anonymus function)
Angius
Angius15mo ago
Yep
Emelie
EmelieOP15mo ago
stupid question again, but why must a lambda expression or anonymous function be used?
cap5lut
cap5lut15mo ago
its simply better this way, because the user of the method can write the actual check for it
Emelie
EmelieOP15mo ago
its the x I dont understand :/
Angius
Angius15mo ago
It's "each element of the collection" Think of it as a foreach loop With the check inside of it
cap5lut
cap5lut15mo ago
maybe better to write the code out a bit:
public delegate TResult Func<TParameter, TResult>(TParameter parameter);

public static T FirstOrDefault<T>(this IEnumerable<T> elements, Func<T, bool> predicate)
{
foreach (var element in elements)
{
if (predicate(element)) {
return element;
}
}
return default(T);
}
public delegate TResult Func<TParameter, TResult>(TParameter parameter);

public static T FirstOrDefault<T>(this IEnumerable<T> elements, Func<T, bool> predicate)
{
foreach (var element in elements)
{
if (predicate(element)) {
return element;
}
}
return default(T);
}
this would be an example implementation
Emelie
EmelieOP15mo ago
Thank you! Im getting closer now 😅 buuut, what about it makes it a foreach loop?
cap5lut
cap5lut15mo ago
predicate(element) is basically calling the delegate/ur lambda like any other method as well
Emelie
EmelieOP15mo ago
is it the lambda that works as a loop?
cap5lut
cap5lut15mo ago
and as u can see im passing the element to it
Angius
Angius15mo ago
No, the inside of the method
Emelie
EmelieOP15mo ago
ah now I see!!
Angius
Angius15mo ago
The method itself loops over all elements of the collection, and returns whichever element matches your lambda
Emelie
EmelieOP15mo ago
the FirstOrDefault already contains an actual ForEach and x is = var ?
cap5lut
cap5lut15mo ago
x is the parameter of the lambda/delegate public delegate TResult Func<TParameter, TResult>(TParameter parameter); <--- that parameter
MODiX
MODiX15mo ago
Angius
REPL Result: Success
string? GetMatching(string[] strings, Func<string, bool> func)
{
foreach (var str in strings)
{
if (func(str))
{
return str;
}
}
return null;
}

var arr = new[]{
"cat",
"parrot",
"ox",
"sandworm"
};
GetMatching(arr, str => str.Length == 3)
string? GetMatching(string[] strings, Func<string, bool> func)
{
foreach (var str in strings)
{
if (func(str))
{
return str;
}
}
return null;
}

var arr = new[]{
"cat",
"parrot",
"ox",
"sandworm"
};
GetMatching(arr, str => str.Length == 3)
Result: string
cat
cat
Compile: 663.692ms | Execution: 83.204ms | React with ❌ to remove this embed.
Angius
Angius15mo ago
Here's a way simplified example
Emelie
EmelieOP15mo ago
soo x is the parameter used in the anonymous function/expression.
cap5lut
cap5lut15mo ago
correct
Emelie
EmelieOP15mo ago
and the anonymous function doesnt really do anything else then define the x as parameter. The only thing that does anything is the FirstOrDefault function So you could say that the anonymus function is a parameter to the FirstOrDefault function
Angius
Angius15mo ago
It most certainly is
Emelie
EmelieOP15mo ago
Ok, thank you all very much 😄 I have some things to consider now, but I really appreciate you taking the time 😍
Angius
Angius15mo ago
When in doubt, use the debugger and go through the code step-by-step to see what it does and when
Emelie
EmelieOP15mo ago
yeah I try to, but it gets difficult to follow sometimes 😅
cap5lut
cap5lut15mo ago
a delegate is a data type to pass functions around as variables and to call them. the crucial point here is that they merely define the parameter list (count and type) and the return type itself lambdas are syntax sugar to write anonymous functions, so u do not have to write a whole new method and pass that to the delegate parameter/variable in ZZZZZZZZZ's example, without lambdas it would become quite more verbose instead of just calling GetMatching(arr, str => str.Length == 3) u would have to write a new method and pass that:
bool HasLengthOfThree(string str)
{
return str.Length == 3;
}
GetMatching(arr, HasLengthOfThree);
bool HasLengthOfThree(string str)
{
return str.Length == 3;
}
GetMatching(arr, HasLengthOfThree);
this will quickly become quite bloaty if u would have too write a lot of these methods (imagine u want to use GetMatching() to get the first element with a length of 3, then the first with the length of 4 nd the first with the length of 5, this would mean 2 more functions really similar to HasLengthOfThree()) this is a lot simplier to read:
var str3 = GetMatching(arr, str => str.Length == 3);
var str4 = GetMatching(arr, str => str.Length == 4);
var str5 = GetMatching(arr, str => str.Length == 5);
var str3 = GetMatching(arr, str => str.Length == 3);
var str4 = GetMatching(arr, str => str.Length == 4);
var str5 = GetMatching(arr, str => str.Length == 5);
Emelie
EmelieOP15mo ago
Im copying all of your replies into my notepad! very useful and important topics to cover, I am understanding so delegates are methods used as variables
cap5lut
cap5lut15mo ago
Lambda expressions - Lambda expressions and anonymous functions - C#
C# lambda expressions that are used to create anonymous functions and expression bodied members.
Emelie
EmelieOP15mo ago
therefore, in this context, the lambda IS a delegate?
cap5lut
cap5lut15mo ago
a delegate is a method type, just like int is a number type a lambda is just a short hand version to specify the value of such a type
Emelie
EmelieOP15mo ago
so lambda is an example of a delegate?
cap5lut
cap5lut15mo ago
yep (well in detail its a bit complexer, but this would confuse right now more than it would help)
Emelie
EmelieOP15mo ago
ok, thanks again!! Im going to read through everything again in further detail, but I think its getting clearer
cap5lut
cap5lut15mo ago
oh and since c# 10.0 lambdas have a natural type now, so what i earlier said:
its actually lambda "expression", a lambda on its own isnt a complete function, it always needs a delegate type to be assigned to
is not true anymore
Emelie
EmelieOP15mo ago
okay! thanks for clarifying, don´t think its super important for me at the moment, still trying to understand the very basics
cap5lut
cap5lut15mo ago
this will help u understand more about it and some LINQ as well. https://learn.microsoft.com/en-us/dotnet/csharp/linq/write-linq-queries they describe method syntax and query syntax, ignore the latter for now, i dont think its used that often anymore
Write LINQ queries in C# - C#
Learn how to write LINQ queries in C#.
Accord
Accord15mo ago
Was this issue resolved? If so, run /close - otherwise I will mark this as stale and this post will be archived until there is new activity.
Want results from more Discord servers?
Add your server