C# LINQ - Part 1: Enumerables - The Foundation of LINQ

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
[Music] [Applause] [Music] so let's get started welcome to a new week to a new topic last week we mainly focused on asynchronous programming and i hope you can remember what we did last week because we are going to need it once we come to the topic of entity framework and data access and so on today we are going to talk about the second very important base technology that is super important when it comes to querying databases we heard a lightning talk about the topic today so you have already a little bit of background knowledge that's very good because i can build on that but we will dive in deep into link and take a look how it works try to understand what the basic technologies behind link are and then we are going to practice a little bit so we will take um one of the homeworks that you did and we will implement it together based on link and if there is still time you can start working on the homework which is due to next week okay but first we'll talk about the basic technologies behind link if you would like to follow along then please create a new project and as always we are going to use a console app in net core i'm going to call it hello ling let me start my zooming tool so i can zoom in a little bit here is hello link nothing special just a plain old console app should be done immediately here it is and then please remember go to properties or in the cs proj file as we do it always and switch to net5 i also ask you in the project file you can remember it from last week and the week before go to lang version preview in order to get the latest c-sharp features enabled in our program and with that we are good if you get annoyed with this whole namespace class main and so on i think by now you should be familiar with that in c sharp 9 and dot net 5 you can remove all the main stuff and with that you have a nice clean little field for experiments and this is exactly what we need good the first thing that i would like to describe and discuss with you is the concept of i innumerable who knows what the what the members of i innumerable are i enumerables is an interface so it has some members which ones okay that's a tricky one it only contains one member get enumerator so let's talk about the enumerator what are the members of an enumerator guess any idea yeah list no yeah i think it's just an id just an id no yeah current correct with current i get the current element so i have a pointer in any kind of collection and with current i get the current item what else if i have current and i have an enumerator of c long to enumerate is alphan what do i need reset no not possible yeah exactly current and move next that is what you have there is a good idea with the reset thing but it's not there so you have a forward only read only cursor through a collection you can ask for what is the current element and you can say go to the next one if you go to the next one and there is no next one then you will get false as the return value of move next got it that's i innumerable read only forward only you cannot manipulate an i enumerable not possible you cannot go back you cannot reset you cannot jump you cannot access with an index that's not possible just move next and current good good let's implement a very simple i enumerable generator um the first code that we are going to write is not very good so we are working our way through to understanding what i innumerable really is so let's create a function which will return i innumerable of let's make it very simple at the beginning just an integer value i enumerable of int generate numbers and it will get an int max value so we should generate all numbers between let's say zero and the max value a naive implementation of this method could look like this var result equals new list of int for var i equals 0 i lower than max value oh i said oh it doesn't matter lower lower equals not relevant for this example i will say lower equals result dot add i return result now why can i return a list because if we take a look into list of t scroll up a little bit then you will see that list of t see it here implements i enumerable you mentioned that in your lightning talk i like that any class that implements i enumerable can be used as a basis for link good so we just returned the list very very simple now remember the lightning talk that we just heard about link let's build a very very simple query let's start by calling generate numbers this one give it a max value let's say of 10 something like this and then if we do a look using system dot link we now have a method you mentioned it in your lightning talk which is called where and here we can specify a so-called predicate a thunk of int and pool and my question to you is that's a repetition you should already know that by now funk of int and pool gets which parameters yeah correct and what is the return type bool correct that's exactly the case so let's give it the name n you can choose any variable here it's just a variable name and in this case let's say only even numbers got it very very simple let's store the result in a variable and then let's iterate over this variable for each var item in result console.writeline item got it difficult no i don't think so you should understand what this where is all about just by taking a look at it i mean can you remember what i told you i think did we discuss the whole ashen puttle cinderella stuff where i told you did we discuss that no yeah okay it doesn't matter just this function is applied to each number and it is only returned if this condition is true so let's give it a try let's run this method or this program the return is all even numbers zero two four six eight ten yep that looks good can i assume that we don't have any severe questions to this code you can read it you can understand it not big of a problem right good now we are going to dive a little bit deeper we are going to think about how i enumerable really works and to do that the first thing that i would like to do together with you is i would like to refactor this method i would like to get rid of the list here so please delete the var result equals to new list i want to get rid of that one then we don't have a result anymore we cannot add it to any kind of result we can't return the result there is no result so which c-sharp keyword comes in handy in this situation correct yield so what we can do is we can say yield return i and remove the return here yield return is a really interesting guy yield return will return the value without us having to create a list or an array or something like this yield is called anten in german okay if we run our application now it should still work properly nice we will debug that in a second okay just accept what we have written here you can remember instead of creating a list or any kind of collection that stores our value we can just write yield return and it magically happens we'll take a look at how c-sharp does that now let's restructure our program a little bit let's please put this one in a block of code so it should look like this i'm just putting in some brackets see it's exactly the same code as before the only difference is that i now have a block of code that makes it easier to debug this stuff and to set a breakpoint it would be possible with the other syntax too but it's easier like that just to make it a little bit more interesting we are also going to select to project the values we heard it in the lightning talk thank you for the good preparation we can say here select and here we just say oops this is the right one return and multiplied by two no multiplied by three sorry if i write it's good looks good so i give you a second so that you can change your code accordingly this is what i want you to change this is what i want you to add and this is where we have the yield and then we are going to discuss what's the point of all this does anybody need additional time to write down the code you're fine good now let's set a breakpoint here in line 24. you can do that by pressing f9 or by clicking in the gray bar here let's please select set a breakpoint here inside of the select set a breakpoint here inside of the return and set a break inside of the where sorry and set a breakpoint here inside the for each so we should have four break points in the where in the select in the console write line of the four each and in the yield return good good and then run the program in the debugger so press f5 not ctrl f5 but f5 this runs the program in the debugger and we are going to stop inside the generate numbers yield return now how did we come here there is a tool in visual studio i'm not sure if you are familiar with it it's called the call stack no here's the call stack i hope you can find it can you find it call stack yes good and if you take a look we see in the call stack how we came to this generate numbers we came from the main method line 15 so if we click on that double click on that it will show us where we came from and this is pretty astonishing what we see here the call to generate number now look at the screen that's important did not happen here generate numbers was was not called when we seemingly call generate numbers it didn't happen the call of generate numbers happened inside the for each loop you see that one how can that be what what's going on here i mean we have learned for months and years and that when we write a syntax like that we are calling a method right but we don't i can prove that to you let me show you uh please stay in the debugger okay just for me i go through if i press f11 it will walk through the code you see here i'm now standing at the call of generate numbers and i press step into so i would like to see what's going on and it jumps over the entire statement it ignores the method call what's going on and now we are here in the for each statement and only when we are here in the in statement it really jumps into generate numbers you see that it jumps in to generate numbers and it would yield the first return value this concept is crucially important for you to understand i enumerable it is super important if you want to successfully use entity framework the whole idea that you see here in action is that ienumerable is a pull-based system that means if we call a so-called generator method a method that generates an i-innumerable the method is not really called it is not it's just sitting there idle doing nothing until somebody is really interested in the result so the generator method is completely inactive until somebody says and now i need the first value the for each loop is the guy who really says now i need the first value and what happens behind the scenes when for each starts running the move next method of the i enumerable is called for the first time and only when i enumerable move next is called the generator method is called get the idea not before so what we can do is we can build queries step by step by step you will see that in a second and only at the very end when we start getting values then our generator method really becomes active what would be the opposite of a pull-based approach a push-based approach right do you know any design pattern where this is flipped around where we don't have this pull thing where the values are generated when we pull the first results with the for each loop for instance but the difference is that the values are pushed as soon as they become available what is the name of this design pattern it starts with o yeah yeah exactly the observer pattern the observer pattern is the difference is the opposite of the enumerable observer means that you have an observable you have a subscriber and the observable pushes its value to the subscriber by i innumerable it's different the generator is inactive until somebody is interested in the result okay it's like with your homework i give your i give you the homework and you don't start immediately working on the homework only when i say i want to see the result then you start working on the homework get the idea ah yeah you don't know what i mean now let's go one step further please press f11 and let's see what's going to happen if we press f11 the next step is now the where clause you see that so we are we are returning from here we are really leaving the generate method please please please watch that closely and try to understand what i'm telling you here the generate method does not generate the entire numbers array it generates only the first value and then the value runs through the entire pipeline of filters select classes and so on please give me just two or three more minutes then we're going to make the break okay so if we press f11 again and f11 again so we run through the where clause and now see what's going to happen next next we are going to run through the select course so we finish the processing of the first value you can continue to press f11 now we are printing in on the screen you see it here so we finish dealing with the first value zero in our case and now watch what's going to happen once we reach the in clause again in the for each loop guess what it jumps again back to the generator method you see it but it doesn't jump into the beginning of the get enumerators i get numbers but it continues after the yield so what we see here is that a generator method with yield yields antenna the first value returns it then it runs through all the different link operators then it is processed until the very end of the query in our case the for each loop and then c-sharp automatically jumps back into the generator and says now i need the next value understand it that means give me a second that means that if you generate a large number of items for instance numbers you don't have a memory problem you never have the situation that all the numbers are in an array or a list because they are generated one by one by one by one they are processed each element from the very beginning until the very end and then the next value is generated you have a question when you use a normal return statement with the list then the list implementation is doing the yield for you you just don't see it but it's sub-optimal because you are taking in our case 10 integer values which is 40 bytes plus the overhead that you need for the list data type so you have a lot of bytes in memory but you don't need these bytes in memory you can process one integer after each other and that's a big advantage of link got it that's one of the fundamental principles on which ling is built and after a short break we are going to continue our experiments so we are going to think about how this is all done and what the operators do and so on so we we are a little bit over time two minutes um let's continue yeah it's easier let's continue at nine okay that's eight minutes break so you have the possibility to fetch your coffee or whatever good nine minutes
Info
Channel: Rainer Stropek
Views: 7,078
Rating: undefined out of 5
Keywords: C#, CSharp, .NET, .NET Core, .NET 5, HTL Leonding, LINQ, Enumerables
Id: TeGwezv1z20
Channel Id: undefined
Length: 22min 59sec (1379 seconds)
Published: Sat Oct 17 2020
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.