C# equivalent of Lambda
You don't really need your own map
and array
methods. There is already the same functionality available, you just have to add using System.Linq;
at the top of your file and you'll be able to use both Select
, which is a projection method and ToArray
which created an array from your collection. They are both extension methods set on IEnumerable<T>
, so you can use them on almost any collection.
var centers = hexes.Select(x => me.hexToCenter(x)).ToArray();
is an equivalent of you JavaScript code:
var centers = Lambda.array(Lambda.map(this.hexes,function(hex) {
return me.hexToCenter(hex);
}));
What's the actual type of lambda in C#?
A lambda expression doesn't have a type. It cannot, because any type in the .NET world that it could have, would also hard-code the type of the lambda's parameters and result. Now consider:
x => x + 1
What type could x
have? What type will the result be? There isn't any single answer, and the lambda expression can indeed be converted to Func<int, int>
, Func<double, double>
, and many other delegate types with different parameters. Giving a lambda expression a type would disallow such expressions. C# did want to allow such expressions, so was designed not to give such expressions any type.
Lambda for getter and setter of property
First of all, that is not lambda, although syntax is similar.
It is called "expression-bodied members". They are similar to lambdas, but still fundamentally different. Obviously they can't capture local variables like lambdas do. Also, unlike lambdas, they are accessible via their name:) You will probably understand this better if you try to pass an expression-bodied property as a delegate.
There is no such syntax for setters in C# 6.0, but C# 7.0 introduces it.
private int _x;
public int X
{
get => _x;
set => _x = value;
}
Confused by C# lambda expression
The =>
operator has exactly the same meaning in both cases: it creates a function whose parameter is the thing on the left, and whose return value is the thing on the right.
You wrote in a comment that the x
in the first case is not a parameter as you understand it. That's not correct; it is a parameter in both cases here.
Here's your first example, again:
List<int> a = new List<int>(){0,1,2,1,3,4,5,6,7,8,9};
IEnumerable<int> b = a.FindAll(x => x>=5);
foreach (int x in b)
Console.WriteLine(x);
If you wanted to write this without using lambda notation, you would define a function somewhere, like this...
static bool MyCondition(int x)
{
return x >= 5;
}
...and then use that function as the argument to FindAll
:
List<int> a = new List<int>(){0,1,2,1,3,4,5,6,7,8,9};
IEnumerable<int> b = a.FindAll(MyCondition);
foreach (int x in b)
Console.WriteLine(x);
The lambda notation is a shorter notation which allows you to define the function right where you use it.
Likewise, if you wanted to write your second example without using lambda notation, you'd define a function elsewhere, like this...
static int MyOperation(int x)
{
return x * 2;
}
...and pass your function as the argument to Select
, like this:
List<int> a = new List<int>(){0,1,2,1,3,4,5,6,7,8,9};
IEnumerable<int> b1 = a.Select(MyOperation);
foreach (int x in b)
Console.WriteLine(x);
Understanding Lambda expressions and delegates
Delegates are methods that you can use as variables, like strings etc. For example you can declare a delegate method with one argument:
delegate void OneArgumentDelegate(string argument);
It doesn't do anything, much like an interface. If you have a method in any class with one argument like this:
void SomeMethod(string someArgument) {}
It matches the signature of the delegate, and thus can be assigned to a variable of its type:
OneArgumentDelegate ThisIsAVariable = new OneArgumentDelegate(SomeMethod);
OneArgumentDelegate ThisIsAlsoAVariable = SomeMethod; // Shorthand works too
These can then be passed as arguments to methods and invoked, like so:
void Main()
{
DoStuff(PrintString);
}
void PrintString(string text)
{
Console.WriteLine(text);
}
void DoStuff(OneArgumentDelegate action)
{
action("Hello!");
}
This will output Hello!
.
Lambda expressions are a shorthand for the DoStuff(PrintString)
so you don't have to create a method for every delegate variable you're going to use. You 'create' a temporary method that's passed on to the method. It works like this:
DoStuff(string text => Console.WriteLine(text)); // single line
DoStuff(string text => // multi line
{
Console.WriteLine(text);
Console.WriteLine(text);
});
Lambda expressions are just a shorthand, you might as well create a seperate method and pass it on. I hope you understand it better now ;-)
Where does the x come from in this lambda expression?
In simplest terms, x is a variable that you declare.
So it reads "x such that x is"... Whatever expression you are trying to convey based on the input and output parameter of your query.
To give you another example:
var sorted = list.Where(x => x.Name == "Foo").ToList();
This reads as "x such that x is equal to Foo". And this will return all list with Name property that is equal to Foo.
To further explain this, lets look into the one of the overloaded Enumerable method which is "Where". According to MSDN:
The actual syntax is:
Where<TSource>(
this IEnumerable<TSource> source,
Func<TSource, bool> predicate
To give another example lets declare a List of integer. Our goal is to get all even integers:
List<int> numbers = new List<int> { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
Now to query all integers who are even numbers, we will use the one of the overloaded version of Where extension methods, using lambda syntax. It says:
So the source here is the:
numbers.Where();
Since "numbers" variable is the IEnumerable of TSource.
TSource here is any IEnumerable of type "T" or any type of entity.
Now the last part is it accepts a Func. A Func is a predefined delegate type. It provides us a way to store anonymous methods in generalized and simple way. To further understand this, lets read it again. It says that it will accept a source, and will output a boolean result.
Now let's create a Func that accepts TSource, on this case, integer as our example and will output boolean result:
Func<int, bool> fncParameter = x => x % 2 == 0;
Now we can pass that into our:
numbers.Where
Which will be:
List<int> numbers = new List<int> { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
Func<int, bool> fncParameter = x => x % 2 == 0;
IEnumerable<int> result = numbers.Where(fncParameter);
Or in short:
ist<int> numbers = new List<int> { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
IEnumerable<int> result = numbers.Where(x => x % 2 == 0);
How do you read lambda expressions?
Given that LINQ generally only works with IEnumerable objects, you could read s =>
as 'for each s in the IEnumerable'.
Update:
Revisiting this answer over 5 years on, I am deeply unsatisfied with it. Personally, nowadays I find myself considering it as "maps to" or I've seen "such that" which is also pertinent depending on the circumstance.
Difference between lambda and LINQ?
Language-Integrated Query (LINQ) is a set of features introduced in
Visual Studio 2008 that extends powerful query capabilities to the
language syntax of C# and Visual BasicA lambda expression is an anonymous function that you can use to
create delegates or expression tree types. By using lambda
expressions, you can write local functions that can be passed as
arguments or returned as the value of function calls.
Linq uses Lambda expression in order to execute some of its functionalities.
Example:
new [] { "Dan", "Yossi", "Ben" }.Where(item => item.Length == 3);
Lambda expression: item => item.Length == 3
Linq: (from item in (new [] { "Dan", "Yossi", "Ben" }) where item.Length == 3)
C# Lambda expressions with Classes
Since you're using reference to Student
, searching it in list and then retrieving its index
doesn't make sense.
You are using Student
instance anyway, so use LINQ's FirstOrDefault
and retrieve object you are trying to modify (in this case, to change the SubjectScore
).
You'd rather:
foreach(string[] lineItem in storedCSVData)
{
string fullName = lineItem[0] + " " + lineItem[1];
//Get student instance instead of index, since you would use it anyway
Student student = Students.FirstOrDefault(s => s.GetFullName().Contains(fullName));
//If there is no result, FirstOrDefault returns 'null'
if(student != null)
{
//Add using refernce instead of using index
student.SubjectScore.Add(
lineItem[4],
Convert.ToDouble(lineItem[5]));
continue;
}
Student storedStudent = new Student(lineItem[0],
lineItem[1],
lineItem[2] == "Yes" ? true : false,
Convert.ToInt32(lineItem[3]));
Students.Add(storedStudent);
}
Related Topics
How to Get the Computer Name in .Net
Hide Tabcontrol Buttons to Manage Stacked Panel Controls
Better Way to Check If a Path Is a File or a Directory
Difference Between Forward Slash (/) and Backslash (\) in File Path
How to Bind a List<String> to a Datagridview Control
Why Does the Equals Implementation for Anonymous Types Compare Fields
Convert Any Object to a Byte[]
ASP.NET MVC Razor Pass Model to Layout
C# Error: Parent Does Not Contain a Constructor That Takes 0 Arguments
Entity Framework Core 2.0.1 Eager Loading on All Nested Related Entities
Benchmarking Small Code Samples in C#, Can This Implementation Be Improved
Is There a Jquery-Like CSS/HTML Selector That Can Be Used in C#
Unzip Files Programmatically in .Net
Why We Have Both Jagged Array and Multidimensional Array
How to Get the Currently-Logged Username from a Windows Service in .Net
Why Can't a Duplicate Variable Name Be Declared in a Nested Local Scope