3

I have the following snippet of code. I have few queries regarding the code snippet which I have mentioned after it.

var salaries = customerList
                    .Where(c => c.Age > 30)
                    .Select(c => c.Salary) // salary is of type long
                    .ToList();
  • In above snippet of code, how does "Where" get access to the customerList and how does it define the type of "c"?
  • Does "Where" return a temporary list of customers after applying the filter on which the Select acts?
  • How exactly does "Select" know that it has to return only the "Salary"?
  • How does the type of the variable "salaries" get set to List< long >?
Corentin Pane
  • 4,794
  • 1
  • 12
  • 29
Sharath
  • 516
  • 1
  • 8
  • 19
  • Please check the `Where` signature. – Renat Dec 06 '19 at 06:50
  • 2
    This should help; https://stackoverflow.com/a/671425/1608418 – Amit Kumar Dec 06 '19 at 06:51
  • 2
    read about lambda expressions [link](https://stackoverflow.com/questions/3832337/interview-what-is-lambda-expression/3844487) – MKasprzyk Dec 06 '19 at 06:52
  • here you have article how linq works, and how it is translated [link](https://stackoverflow.com/questions/671235/how-linq-works-internally) – MKasprzyk Dec 06 '19 at 07:03
  • 1
    I will advice reading Jon Skeet's series about [Reimplementing LinQ](https://codeblog.jonskeet.uk/2011/02/23/reimplementing-linq-to-objects-part-45-conclusion-and-list-of-posts/). The article for that question are : [REIMPLEMENTING LINQ TO OBJECTS: PART 2 – “WHERE”](https://codeblog.jonskeet.uk/2010/09/03/reimplementing-linq-to-objects-part-2-quot-where-quot/) and [REIMPLEMENTING LINQ TO OBJECTS: PART 3 – “SELECT” (AND A RENAME…)](https://codeblog.jonskeet.uk/2010/12/23/reimplementing-linq-to-objects-part-3-quot-select-quot-and-a-rename/) – xdtTransform Dec 06 '19 at 08:05
  • John Skeet's book: "C# in depth" helped me a lot in understanding LINQ and lambdas. There are a lot of examples and good advices – Alexander Groshev Dec 06 '19 at 08:08

5 Answers5

6

Where is probably implemented like this (note that this is a very rough implementation, just do give you an idea of what it is like):

public static IEnumerable<T> Where<T>(this IEnumerable<T> source, Func<T, bool> predicate) {
    foreach (T t in source) {
        if (predicate(t)) {
            yield return t;
        }
    }
}

Note that Where is an extension method. You are essentially calling Where(customerList, c => c.Age > 30). Now you should see where it gets access of the customerList. It also infers what T should be by looking at what kind of IEnumerable customerList is. Since it is a IEnumerable<Customer>, T is Customer, and so it expects a Func<Customer, bool> for the second argument. This is how it knows that c is Customer.

Where does not return a temporary list. A lot of LINQ methods make use of deferred evaluation. Where returns an IEnumerable<Customer> that is filtered. Remember that IEnumerable is just a sequence of things. This sequence returned by Where however, is not evaluated, until you ask for it. Select does the same as well. So a list is not created until you call ToList.

Your third question is kind of like asking "How does Where know how to filter" or "How does Console.WriteLine know how to write to the screen". That's what Select does. You can look at its implementation if you want. Here's a rough sketch:

public static IEnumerable<U> Select<T, U>(this IEnumerable<T> source, Func<T, U> mapping) {
    foreach (T t in source) {
        yield mapping(t);
    }
}

The type of the variable salaries is determined by looking at the method signatures of each of the methods you call. Your Select call returns a IEnumerable<long>, and ToList's signature tells the compiler that, given a IEnumerable<T> it will return List<T>, so in this case, it returns a List<long>.

Sweeper
  • 213,210
  • 22
  • 193
  • 313
2

This will help you understand lambda expressions better. Anatomy of the Lambda Expression

And this is for Linq

Hope this helps.

Thank you.

Noorul
  • 873
  • 2
  • 9
  • 26
1

Where clause exists in Enumerable class which uses for querying in .net framework. it provides as boolean condition and return source. It will convert to respective sql query eventually.

so your linq

var salaries = customerList
                    .Where(c => c.Age > 30)
                    .Select(c => c.Salary) // salary is of type long
                    .ToList();

old school sql command

SELECT [c].[Salary] FROM [CustomerList] WHERE [c].[Age] > '30'
phonemyatt
  • 1,287
  • 17
  • 35
1

how does "Where" get access to the customerList and how does it define the type of "c"?

  • customerList is of type List and Where() is an extension method of type List. So Where() method is accessible to customerList. c => c.Age > 30 is a predicate define inside Where() clause. This predicate help list to filter out data based on condition. Here c indicates individual element present in List.

How exactly does "Select" know that it has to return only the "Salary"?

  • Select is used to project individual element from List, in your case each customer from customerList. As Customer class contains property called Salary of type long, Select predicate will create new form of object which will contain only value of Salary property from Customer class.

How does the type of the variable "salaries" get set to List< long >?

  • Select() will crate new form with only Salary property something like
new {
      public long Salary{get; set;}
    }

.ToList() will convert IEnumerable returned by Select into List. Ultimately you will get List<long>

"Where" return a temporary list of customers after applying the filter on which the Select acts?

  • Yes, Where will return filtered list(Precise IEnumerable) on which you applied Select() method

I would suggest you to read Linq in C#, Where clause, Select method, List.

Prasad Telkikar
  • 15,207
  • 5
  • 21
  • 44
1

The link from @Amit can give a good idea.

Short answer is that LINQ is built on the compiler feature called Expressions. When you write something like Where(c => c.Age > 18) compiler doesn't actually compile the c=> c.Age > 18 all the way like a regular method.

It builds a syntax tree that describes what that code does.

The Where function uses this to build a SQL query that is sent to the SQL server which executes that to get the results.

Suggest you look into the workings of IQueryable and Expression<TDelegate> for more information.

Also helps to understand the difference between IEnumerable and IQueryable.

Another example of Expressions used in other parts of C# like Razor pages that uses functions like LabelFor(...) which uses the property you express to build a HTML label rather than executing the code.

HTH

Madushan
  • 6,977
  • 31
  • 79