简体   繁体   中英

How the Lambda Operator works and how it simplifies the expression in LINQ(c#)?

I am new to C# learning, i couldn't understand clearly about the lambda operator, but what i understood is it simplifies the expressions.

 var testString = Console.ReadLine();
            testString.ToCharArray()
            .OrderBy(i => i).ToLookup(j => j)
            .Select(i => new Program { letter = i.Key, count = i.Count() }).ToList()
            .ForEach(i => Console.WriteLine("letter {0},count {1}", i.letter, i.count,i.sign));

in the above code the i am not getting about 'i' and 'j'. is that a variable or object of anonymous type ?

The issue is that your question itself is wrong, you ask "is that a variable or object or anonymous type" as if those 3 things were uncompatible. An anonymous type has instances, those are objects and the name by which you refer to those objects are variables. I'll try to clarify the syntax however so that it may make more sense to you.

To understand what's happening you have to look at what all those fancy linq operators have as a signature, let's take the example of OrderBy:

public static IOrderedEnumerable<TSource> OrderBy<TSource, TKey>(this IEnumerable<TSource> source, Func<TSource, TKey> keySelector);

The first parameter is the object on which you call orderby (if this is confusing to you, Google up extention methods), the other parameter (the one that corresponds to i=>i in your code) is this:

Func<TSource, TKey> keySelector

Now we need to dig deeper and see what "Func" is, let's look at the definition of Func:

public delegate TResult Func<in T, out TResult>(T arg)

Func is . . . a delegate definition! Something that has existed way before lambdas were introduced, now that we know what i => i is type Wise, we can try to understand what i is, for this we need to dissect the syntax. We know i => i is aa delegate func whose signature looks like this once we infer the type (by knowing the type of your enumerable), both before & after the call to orderby, you're working with an enumerable of char, so i=>i is a Func which is a delegate char Func(char Item), basically a delegate that takes a char, and returns a char.

Lambda functions are a very terse way to express delegates in very specific scenarios, let's look at the old ways you could do this

char MyMethod(char c)
{
    return c;
}

bla.OrderBy(MyMethod); // This is a very verbose version, we defined an external method

Now this way made sense in most cases where you used delegate as you HAD to specify all this information (in non generic cases where you couldn't use type inference). However as i've shown earlier we know (thanks to inference) that you're working on a Func from the start thanks to the type of the object you're calling this on, this means we could strip the redundant information and end up with:

MyMethod(c)
{
   return c;
}

What else can we strip? Well the method's name! Why? because we're only using it once so why name it if it's not going to be reused!

(c){ return c;}

Also you often want to do something very simple that holds in a single statement, so why bother returning it, let's just implicitely return what the statement resolves to and drop the brackets! (c) c

And now we're left with something that is strictly the same as the original code (all the additional code from the original is useless and can be infered from the context as i demonstrated) so we just change the syntax to make it visibly diferent by adding the lambda operator => between the input variables and the code

(c)=>c

Which can be simplified again if you're only passing in a single element by removing the ()

c=>c

So what's the lambda operator? It's the separator between the signature and the code, and the whole expression is declaring a while method without naming it, and by letting the compiler infer as much as it can, inline where you itend to use it in a very terse syntax. And in your case i is a local variable passed in as an input of the delegate you're defining inline.

As for anonymous types you're not using any in your example, they're type that are declared inline and not named, and that are also meant to be used within the scope of a query (just like lambda expressions avoid creating one shot functions for code you don't need to name and won't reuse, anonymous types avoid creating 1 shot classes for data you'll only use once).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM