welcome to this Advanced Journey Through the depths of c-sharp this course is designed to elevate your programming proficiency delving into intricate aspects like delegates events generics async await tasks and Link plus you'll learnabout.net with detailed code examples and best practice guidelines you'll explore design patterns user actions queries operators c-sharp attributes and more and you'll learn all this from gavinlan Gavin is an experienced developer and free code Camp team member so let's get started learning Advanced C sharp hi and welcome I'm Gavin long I'm a full stack software engineer with over 20 years of experience some of the more abstract concepts of the c-sharp language or any high-level programming language can seem somewhat esoteric even to many experienced Developers so my goal with this Advanced c-sharp course was to explain these more advanced abstract Concepts in a simple and easy to understand way I hope you enjoyed this course and I hope you benefit from it so what sort of topics do I intend to cover in the c-sharp advanced course here are a few examples delegates events generics extension methods Lambda Expressions link asynchronous programming with async await attributes reflection and more so what makes these kinds of topics more advanced than those discussed in the c-sharp for beginners course where we covered basic concepts like methods classes arrays data types variables enum switch statements if statements Loops Etc if I had to pick one word that sums up the answer to that question that word would be the word abstract I found what I believe to be an appropriate definition for the word abstract that in my view best fits the programming context to consider apart from application or association with a particular instance this definition sort of reminds me of the ancient philosophical Theory or world view attributed to the great ancient Greek philosopher Plato the theory is known as the theory of forms or theory of ideas I'm not going to go into too much detail regarding the theory itself but basically the theory asserts that Ultimate Reality exists outside our temporal and spatial world for example the human form itself exists as a thing independently from the actual humans that exist in plural in our experience of our temporal and spatial Realm an even more simple example is that of the shape of a triangle if I ask you to draw a triangle and I was to also draw a triangle there would be subtle differences in our drawings but essentially we would both be able to recognize the three-sided triangle shape in both of our drawings they are forms that are Universal so in this sense the triangle shape itself can be seen as an abstract concept but instances of this shape can be found and recognized in our real world experiences so for example in terms of programming we have certain abstract Concepts that exist on their own as universally recognizable patterns these patterns can be implemented in our code to solve multiple real world problems it can be hugely advantageous to understand certain Advanced abstract Concepts that can then be appropriately applied in code to achieve better code reuse cleaner code extensibility flexibility of design easier maintenance of code separation of concerns enablement of effective unit testing and the provision for overall better performance and efficiency of our applications if there is one downside to the implementation of certain Advanced code patterns it is that to someone unfamiliar with these advanced concepts the code implementations of these advanced concepts can appear as somewhat esoteric for most people the more abstract a concept is the more time is needed to understand the abstract concept this I would say is the main difference between the concepts discussed and the c-sharp for beginners course and some of the concepts that we will cover in the c-sharp advanced course let's look at a basic code example so this is just a basic example that I'll go through fairly quickly it's not necessary to follow along with the example I will however make the code example available on GitHub please see a link to the appropriate repository Below in the description so let's create a c-sharp Project based on the.net core console application project template let's name the project School HR Administration let's create a class Library project and I'll name this HR Administration API foreign within the class Library project let's first delete the class that is there by default and then add an interface named I employee let's add four property definitions to the I employee interface ID as integer first name is string and this is an interface so we of course don't need these Public Access modifiers preceding our property definitions last name is string and salary as decimal let's add an abstract class and name it employee base let's make this employee base abstract class implement the I employee interface and let's make the salary property a virtual property so now we have the basis in our HR Administration API class Library project for a basic employee record so from within our school HR administration.net core console application let's make a reference to the hi Administration API class Library project let's create a class named teacher and let's make the teacher class inherit from the employee base abstract class let's ensure that our code includes a directive to the hi Administration API namespace let's create three other classes that inherit from the employee Base Class these classes represent some other staff roles within the school so head of Department Deputy Headmaster and Headmaster let's say there is a requirement to sum up the annual salaries including bonuses for these members of staff first let's create a method named seed data so the seed data method accepts a generic list which is strongly typed as I employee as an argument foreign five employee objects and add each of the objects to the employee's collection for the sake of this example I'm going to hard code the property values for these five employee records so let's say that a bonus is paid annually to each of these staff members and the amount is based on seniority so let's override the salary property and add an appropriate bonus for each of these employees let's say the teacher gets two percent the head of Department three percent the deputy Headmaster four percent and the Headmaster gets five percent so let's address the requirements to calculate the sum total of staff salaries including bonuses so to do this we can Implement a for each Loop in the main method that traverses the items in our employees list and sums up the salaries within the for each Loop using the plus equals operator we can then output the sum total of all staff annual salaries including bonuses to the console screen let's run the code great we can use more advanced code to achieve the same thing literally through writing one line of code instead of the multiple lines of code used to create the for each Loop and the mathematical operation performed within the for each Loop so let's include a directive at the top of our code to the system.link namespace by using the linked technology we are able to provide the same solution with one line of code like this let's run the code and we get the same result as before but our code is more concise and much cleaner so let's briefly look at some of the advanced c-sharp concepts that have been applied in this simple example my explanation at this point will be brief because each of these topics will be discussed in detail as the c-sharp advanced course progresses sum is an extension method provided in the system.link namespace let's see what happens if we comment out the system.link directive the c-sharp compiler immediately complains the system.link namespace contains many useful extension methods including the sum extension method a Lambda expression is passed into the sum method the sum parameter accepts a delegate argument where the delegate contains a type definition parameter I.E the I employee type and as you can see there are several overloads to the sum method where the output type of the delegate can vary so we are passing in a delegate that accepts an argument of type I employee and outputs a decimal value so because we are summing up the salary field and the salary field is of type decimal the delegate passed in in the form of Lambda expression has an output of type decimal notice the fun keyword is used to define the delegate type parameter also notice the angle brackets following the funk keyword and within the angle brackets the date type definitions are included this is an implementation of generics even in this really basic example a lot of complexity is abstracted away through the use of Technologies like link extension methods delegates Lambda expressions and generics I won't go into too much detail explaining these Technologies in this video because all of these technologies will be explored in detail in this course here is a brief definition of each of the Technologies we have just discussed link stands for language integrated query link enables the developer to write queries against strongly typed collections of objects by using language keywords and familiar operators extension methods enable the developer to add methods to existing types without creating a new derived type recompiling or otherwise modifying the original type a delegate is a type that represents references to methods with a particular parameter list and return type a Lambda expression is a shorter way of representing an anonymous method using special syntax the funk type provides a way to store Anonymous methods in a generalized and simple way generics introduced the concept of type parameters to the.net framework which make it possible to design classes and methods that defer the specification of one or more types until the classroom method is declared and instantiated by client code let's abstract the object instantiation process for an employee through the use of a factory class so we are going to implement the factory design pattern to implement this code let's first create an enum at the top of our code and name it employee type let's include the members of Staff employee roles within the context of a school in the enumerator list okay let's create a public static class named employee Factory within this class let's create a public static method named get employee instance that returns an object of the I employee type let's implement the code for this method which simply instantiates an appropriate object based on the type of the employee foreign let's write the code that Returns the employee object to the calling code right let's use our Factory class to construct our employee objects within our C data method foreign so we have now abstracted the construction of our employee objects let's run the code but now let's go one step further So within the HR admin API class Library project let's create a generic class named Factory pattern as discussed earlier to someone not familiar with generics this class may seem somewhat esoteric the method in this class named create instance instantiates an object generically even though the object is generically created generics enables the code to be strongly typed and therefore the code is checked at compile time so let's go back to the calling code in the school HR Administration project and in the employee Factory class let's update the code that instantiates our employee objects through the utilization of the generic Factory pattern class we have abstracted the object construction process even further so let's run the code great so before I conclude this video I want to highlight another reason why it is important to understand the more advanced concepts in C sharp these advanced concepts are commonly used in various.net Project Frameworks like for example asp.net MVC web API and xamarin if you are a game developer that uses the unity game engine knowing the more advanced concepts in c-sharp will also be hugely advantageous foreign code for each of these types of applications or games without having a deep knowledge of the advanced concepts that are built into the Frameworks or game engine themselves but having a knowledge of these Concepts is going to give you an advantage when building and maintaining your applications or games so for example behind the scenes as it were a reflection is used extensively in asp.net MVC for example when the control and action names are passed from the root reflection is used to find the corresponding method to invoke attributes are also used extensively to abstract aware complexities and facilitate the ReUse of common functionality asynchronous programming with async await is used here to increase performance and generics is also commonly featured with the Entity framework data access technology Lambda expressions and Link are commonly used Entity framework is commonly used in asp.net MVC applications and web API applications in the web API framework we see the same Technologies being applied note that dependency injection is a built-in feature in the asp.net core MVC and web API project Frameworks dependency injection will be explored in the c-sharp advanced course [Music] in the xamarin project we can see here the use of attributes and generics is being applied here in code in this game created with unity generics is commonly used attributes are also frequently applied and these are just a few examples of how these advanced concepts are applied in commonly used project Frameworks and the unity game engine [Music] summary what makes the concept in programming a more advanced concept the more abstract the concept the more difficult the concept is to understand for most people gaining an understanding of the more abstract advanced concepts can be applied to achieve better code reuse cleaner code extensibility flexibility of design ease of code maintenance separation of concerns the enablement of unit testing and the provision for overall better performance and efficiency of our applications the more advanced concepts are applied frequently in the various.net project Frameworks like for example sp.net MVC web API and xamarin understanding these advanced concepts will also be an advantage to game developers that create games using the unity game engine some of the advanced concepts that will be explored in detail in this Advanced c-sharp course will be for example delegates events generics extension methods Lambda Expressions link asynchronous programming with async await attributes reflection and more [Music] hi and welcome this video highlights the significance of the release of dotnet 5. [Music] I've included this content as part of the c-sharp advanced course because I feel that this.net upgrade is a game changer for net Developers this will not be a code Focus tutorial I feel that in order to put c-sharp in its correct context we must understand the underlying Plumbing as it were and how future.net upgrades will affect us as c-sharp Developers with the release of.net 5. I thought it would be prudent to cover how this will change the context of our c-sharp applications [Music] [Music] [Music] so.net 5 is expected to be released in November 2020. the first preview of.net 5 is expected to be available in the first half of 2020 and will be supported by Visual Studio 2019 and visual studio code here are some key features of dotnet 5. a single unified platform for everything including Windows Mac web mobile cloud iot gaming machine learning and data science managed by open source community and supported by Microsoft cross-platform with any device anywhere supports all major platform capabilities for net framework.net core and xamarin including Windows forms WPF uwp asp.net MVC Entity framework link and so on scalable fast and high performance smaller development and packages support for the most productive Ides and tools including Visual Studio vs code vs4 Mac and command line interface CLI okay let's go back in time to just before May 23 1995. so what is the significance of this date well this is the date that Java first appeared so what does the phrase close to the metal mean and what does it have to do with anything when programmers say a programming language or platform is close to the metal this means the developer is able to programmatically manage and operating system's memory so when Java came along in 1995 this was a huge deal compiled Java code ran within its own environment called the jvm jvm stands for Java virtual machine write once run anywhere and automatic memory management before.net framework was released by Microsoft on February the 13th 2002 visual Basics 6 had been released in 1998. Visual Basic is a third generation event-driven programming language developed for Microsoft's component object model com the first version of Visual Basic was released in 1991. Visual Basic was not a fully object-oriented language and was event driven it was also tightly coupled with the Visual Basic IDE a framework was a massive upgrade from this and the.net framework common language runtime resembled the Java virtual machine in many ways automatic memory management was achieved for Windows platforms but right once ran anywhere had not yet been enabled through.net the dotnet framework could only run on Windows platforms so the top similarities between the.net framework CLR common language runtime and Java's jvm Java virtual machine include they are both virtual machines they both include garbage collection they both employ stack-based operations they both include runtime level security they both have methods for exception handling the.net framework provides developers with an abstraction that sits above the operating system a virtual machine I.E the common language runtime and a suite of apis I.E bcls or Base Class libraries the.net framework provides thousands of Base Class libraries that Aid the developer with common development tasks interoperability multiple.net languages for example vb.net F-sharp and of course c-sharp can be included and interact with each other in the same application this is possible because the higher level.net languages are first compiled into the Intermediate Language the Intermediate Language is then compiled at runtime into machine language through just-in-time compilation the.net framework also provides memory management security and exception handling .NET Framework although a massive Evolution from VB6 and com is not modular and is not cross-platform it has to be installed in its entirety and it can only run on a Windows platform the latest version of the.net framework is version 4.8 this version was released on April 18 2019. so let's go back in time to the release of mono mono was first released on June the 30th 2004. it is a free and open source project to create an ecma standard compliant.net framework compatible software framework including a c-sharp compiler and a Common Language runtime originally created by Simeon it was later acquired by Novell and is now being led by xamarin a subsidiary of Microsoft and the.net Foundation so mono provided a.net runtime implementation which allowed c-sharp code to be compiled and implemented on multiple platforms dot net core's initial release was in June 2016. net core is a free and open source managed computer software framework it is a cross-platform successor to the.net framework .net core is similar to mono in that it enables cross-platform portability it is an open source and cross-platform framework .net core can be said to be a more agile version of.net framework because only the components required for a particular application need to be deployed to the Target computer net core has been optimized for the cloud and can also run inside a Docker container which makes it an ideal runtime environment for macro services the latest release of.net cores version 3.1 and was released on the 3rd of December 2019. so at this point we have.net framework mono and net core providing different implementations of.net so you can see how it could be difficult for Developers for example to be sure for particular.net Base Class Library component dependency would be supported across relevant.net implementations so in order to create uniformity across these implementations of.net Microsoft introduced the.net standard .net standard is a set of apis that all.net platforms have to implement [Music] it was introduced to unify the.net platforms and prevent future fragmentation for more comprehensive information on what is supported by the.net standard please check out this table that can be found at this URL dotnet standard was a great step forward in terms of providing uniformity across.net platforms but wouldn't it be great to have one framework to rule them all so why.net 5 and not.net core version 4. Microsoft is following the version progression of the.net framework where as mentioned earlier the latest release of the.net framework is version 4.8 so this is why the next release of dot net is.net 5. it follows from the.net framework visioning rather than the net core versioning so what is the significance of dotnet 5.net 5 will be open source and you will be able to use it to Target Windows Mac OS iOS Android tvos watch OS and webassembly and more I recommend reading this blog from Richard Lander the program manager of the.net team this blog post was written on the 6th of May 2019 and can be found at this URL here are some significant quotes from the blog post from the Inception of the.net core project we've added around 50 000.net framework apis to the platform .net core 3.0 closes much of the remaining capability Gap with.net framework 4.8 enabling Windows forms WPF and Entity Framework 6. Net 5 Builds on this work taking.net core and the best of mono to create a single platform that you can use for all your modern.net code we intend to release.net 5 in November 2020 with the first preview available in the first half of 2020. it will be supported with future updates to visual studio 2019 visual studio for mac and visual studio code the blog post goes on to say the following everything you love about.net core will continue to exist open source and Community oriented on GitHub cross-platform implementation support for leveraging platform-specific capabilities such as Windows forms and WPF on Windows and the native bindings to each native platform from xamarin high performance side-by-side installation small project files SDK Style capable command line interface CLI Visual Studio visual studio for mac and visual studio code integration here's what will be new you will have more choice on runtime experiences Java interoperability will be available on all platforms Objective C and Swift interoperability will be supported on multiple operating systems core FX will be extended to support static compilation of.net ahead of time aot smaller Footprints and support for more operating systems we will ship.net core 3.0 this September referring to September last year 2019.net 5 in November 2020 and then we intend to ship a major version of.net once a year every November and note the depiction of the release schedule timeline in 2021.net 6 2022.net 7. so no more.net framework or net core but rather one unified open source cross-platform framework.net 5 is a welcome release so please let me know in the comments your thoughts on.net 5. I think the move to unify features from.net framework mono and Dot net core into one framework is a big step forward [Music] this video serves as an introduction to delegates and is the first part of a video series on this Advanced c-sharp topic thanks [Music] we'll look at a broad overview of delegates in this video so that we can understand delegates conceptually and we'll also create a very basic example of using delegates and code my aim is to explain these advanced concepts in a simple way so what are delegates a delegate can be described as a typesafe function pointer a variable defined as a delegate is a reference type variable that can hold a reference to a method in order for a delegate to reference a particular method the delegate must Define parameters with types that match the parameter types contained in the relevant method the delegate must also Define a return type that matches the return type of the relevant method when a developer instantiates a delegate the developer can associate its instance with any method with compatible parameters and return type the developer can invoke or call the method through the delegate instance note that variants can be used in delegates which means that the types defined for the parameter list and the return type of the delegate do not have to match exactly with the relevant methods parameter types and return type in this video we'll keep the example simple but we'll discuss variants in an upcoming video in the meantime if you wish to read about variants you can navigate to this URL this web page contains content on both covariance and contravariance in this video I'll introduce delegates through a basic example where a delegate can reference a static method and an instance method we'll also look at multicast delegates which allows the developer to invoke or call multiple methods through one delegate call we'll also look at how a delegate can be passed as a parameter to a method and subsequently called within that method in a later video on delegates we'll explore how delegates are used for asynchronous callbacks and event handling in c-sharp we'll learn how we can take advantage of different types of delegates like action func and predicate to facilitate callbacks and add flexibility to our code but let's first look at the basics in this introduction to delegates so a delegate can reference both static methods and instance methods let's first look at how a delegate can reference static methods let's say we want to encapsulate functionality that logs text and includes a date timestamp preceding the text in some situations we want to have the ability to log the text to the console screen and in other situations we want to have the ability to log the text to a text file so let's define a delegate that can reference a method that does not return a value and accepts one string argument so to do this we use the delegate keyword followed by the name of the delegate type we wish to Define let's name this delegate log Del so preceding the logdel delegate name we have included the void keyword this is because we want this delegate to reference a method that does not return a value then after the logdale delegate name we can include brackets and within the brackets a list of parameters so let's include one string parameter and name it text so this delegate can reference methods that contain one string parameter and do not return a value note that we have included our delegate definition within the program class which means this delegate type can be accessed from anywhere within the program class we could have included this delegate definition outside the program class and within the delegate basic example namespace if we wanted to extend the delegate's accessibility to anywhere within the delegate basic example namespace in this example we'll Define the delegate scope so that it is accessible from anywhere within the program class and not accessible from outside of the program class let's create a static method named log text to screen inside the program class this static method contains the void keyword which is used to indicate that the method does not return a value and contains one string parameter named text the functionality within this method is very basic we are simply writing the text arguments value to the screen with the date timestamp preceding the value stored in the text argument you can see that the delegate type we have just defined named logdel contains a definition for a method that does not return a value and contains one string parameter so the return type and parameter type defined in our delegate named logdel matches the return type and the parameter type in the log text to screen method signature let's go to our main method and Define a variable as the logdoll type we do this by entering the logdal delegate name followed by the variable we'll name logdel then the equals symbol followed by the new keyword to instantiate an object we must then follow the new keyword with the name of the log Del delegate type and then pass the name of the method that we want the logdel variable to reference into the logdoll types Constructor like this then to call the method now referenced by the logdel variable we can simply write the name of the variable that references the delegate and pass in the appropriate parameter to the delegate like you would if you were calling a method note you're also able to invoke delegates through the use of the delegate types invoke method like this but for this example let's call the delegate without using the invoke method okay so let's make this example slightly more interesting let's write code in the main method to prompt the user for the user's name and let's pass the user's input as an argument to the logdel delegate let's run the code and that works as expected so what happens if we decide to include the date time stamp as a parameter in the log text to screen methods method signature the c-sharp compiler automatically complains this is because the log text to screen method no longer conforms to the log dial delegate definition so let's change the logdel delegate definition to accommodate a parameter of the date time data type right let's run the code great so that gives us a basic idea of how delegates work let's change the code for the log text to screen method and the logdel delegate definition to how it was previously I.E let's remove the daytime stamp as a parameter for the logdel delegate definition and let's also remove the date time stamp parameter from the log text to screen method signature let's also update the log text to screen method implementation accordingly so let's say there is a requirement to log the text to a text file to implement this functionality we can simply create a method that doesn't return a value and contains a string parameter as we now know this will allow this method to be referenced by a variable defined as the log delt delegate so let's create a static method named log text to file that contains a string parameter and does not return a value let's Implement codelogic detail that writes the input from the user to a text file let's replace the log text to screen method name being passed into the logdoll delegate during the construction of the delegate object with the log text to file method name so our lockdown variable is now referencing the log text of file method so when the logdel delegate is called this should invoke the log text to file method let's see if the user's input has been written to the relevant text file right so let's navigate to where the log file should now have been created which is the same directory path from where our code is run and you can see that the user's input has been successfully written to the log file as expected so we have now proven that we can reference static methods and delegate defined variables let's now prove that delegates can also reference instance methods let's create a class named log let's move our static methods to the log class and let's remove the static keyword from their method signatures because we want to test that instance methods can be referenced from delegates let's go to the main method and create an instance of the log type let's then pass the instance method named log text to screen into the logdel delegate Constructor Let's test the code great the user's input is logged to the screen as expected and for good measure let's also test the log text to file instance method excellent we are also able to call both methods through one delegate call this can be done through the use of what's known as a multicast delegate by using a multicast delegate multiple objects can be assigned to one delegate instance by using the plus operator let's define two delegate variables as log Del on one line like this let's name the first delegate log text to screen Dell and the second delegate log text to file though let's instantiate the first delegate named log text to screen Dell and ensure that it references the instance method named log text to screen let's instantiate the second delegate named log text to file Dell and ensure that it references the instance method named log text to file let's create a multi-cost delegate named multi-log Dell and assign it a value which is a combination of both the log text to file Dell variable and the log text to screen dial variable note that these two delegate variables have been combined through the use of the plus operator we are now able to call the log text to screen method and the log text to file method through one call to the multi-log Dell delegate Let's test the code and the user's input along with the timestamp has been logged to the screen as expected let's see if the user's input has been logged to the relevant text file and it has great and lastly let's demonstrate how a delegate can be passed as an argument to a method then invoked by the method that receives the delegate argument let's create a static method in the program class named log text this method does not return a value and contains a parameter defined as the logdel delegate type and the log text method will simply serve as a wrapper function for calling the logdoll delegate which will be passed as an argument at runtime to the log text method let's go to the main method and pass the multi-log Dell delegate as an argument to the log text static method Let's test the code so it is logged the user's text to the screen as expected let's also check whether the text has been logged to our log file excellent so you could also pass the log text to screen dull object or the log text to file Dell object as an argument to the log text method so let's do this let's first pass the log text to screen Dell object into the log text method and run the code great and let's also Test passing in the log text to file Dell object to the log text delegate let's look at the appropriate text file excellent so you can see how delegates can be used to separate design from implementation detail and facilitate flexibility of design in our applications please let me know in the comments section whether you have used delegates before in your code if not hopefully you will feel confident that you can use them in the future I hope you have enjoyed this basic introduction to delegates in the next tutorial we'll dive deeper into delegates with a more detailed example [Music] hi and welcome this is the second part of a tutorial on delegates please note that this tutorial is going to be quite code intensive and I will be going through the code creation process fairly quickly if you are struggling to follow along my advice would be to download the code from GitHub and use this video as a guide a link to the relevant GitHub repository is available in the description the purpose of this video is to help you understand delegates and how they can be applied in code and also how certain code design principles should be adhered to in order to create reusable extensible clean and easy to maintain code basically we are going to build a club membership registration form and use delegates to implement field validation functionality the advantage of using delegates for this purpose is that these delegates can be reused to validate fields for other forms that we may wish to add to our application in the future this alludes to how delegates can facilitate extensibility of our design we are effectively going to decouple validation from any one particular form these delegates will be enabled to be reused to validate any appropriate fields for any form so we have highlighted two advantages that can be gained through the use of delegates code reuse adherence to the code principle of dry which is an acronym for don't repeat yourself and code design flexibility so in this example we'll build a basic application using c-sharp and the.net console project template we'll use sqlite to store the data entered into our user registration form we will then create a login form and write a code to authenticate the user by validating the user's login information against relevant data stored in a table in a sqlite database if you are not familiar with SQL Lite please navigate to this URL for more information you can also download a sqlite client application named sqlite browser from this location foreign [Music] basic code using Entity framework core for appropriate database interactions you may have noticed that I have used the.net core console project template for all my tutorials thus far there is a very good reason for this we could implement the code we are about to write using the asp.net MVC framework we can scaffold our code and leverage Technologies like specific attributes provided in.net to facilitate field validation separation of model views and controllers and functionality like dependency injection is inherently taken care of for us in the asp.net MVC framework please don't misunderstand me Frameworks like asp.net MPC facilitate rapid application development and I am a proponent of using such Frameworks the only problem is we run the risk of not fully understanding the underlying design and code principles that are abstracted away by such Frameworks we can easily and effectively develop web applications for example using Frameworks such as asp.net MVC without understanding the fundamental underlying principles that make such Frameworks so effective so because the.net core console project template doesn't spoon feed us as it were it can force us to think about fundamental design principles that facilitate for example code reuse separation of concerns the implementation of code design flexibility and dependency and version principle with all that said let's look at a bird's eye view of what our basic application will look like we'll start with the main.net core console project we'll then create a standard class Library project which will be referenced by our main.net core console project the.net standard class Library project will be named field validator API and will contain two classes one class will be named common field validator functions it will contain a number of delegates which will encapsulate functionality for common validation like for example required field validation string length validation pattern match validation field comparison validation and date validation the other class will be named common regular expression validation patterns this class will contain a number of common regular expression patterns that can be leveraged in our application for example a regular expression pattern used for validating an email address a pattern that can be used to validate UK postcodes a pattern that can be used to validate UK phone numbers and a pattern for validating strong passwords within the main project the.net core console project will create four folders a folder named data to store data related classes and interfaces a folder named field validators to store interfaces and classes relevant to field validation a folder named models to store our data structures in this application we are only going to implement one data structure which will be a class containing user registration related properties and lastly a folder named views this folder will contain one interface and classes relevant to the screens that will be presented to the user namely the user login view the user registration View and welcome view which is presented to the user once the user is authenticated through the use of the login view there's also a main view which will be instantiated and run from within the main method so this application serves as a simple example of how we can leverage delegates and design our applications to facilitate easy maintenance and flexibility of design we are also going to create three ancillary classes within the root of the.net core console application namely common output text where we can store and make available for example heading text common output format which we can use for changing the background and foreground color of our output text and lastly we'll create a class named Factory which will abstract away the construction of our main view object this will demonstrate a very basic example of the use of dependency injection and show an adherence to the last letter of solid I.E dependency inversion principle so let's get started first let's create a.net core console project where solution as always will be auto-generated to house our project let's name this project club membership application the theme of this application will be a user registering for a Cycling Club right so let's add a folder named models let's add a class to our models folder named user let's add properties to our user class these properties will store the values entered by the user during the registration process all of these properties must be public read write properties so they must have both Getters and setters so let's create ID as integer first name is string last name as string password is string note that the password field will be stored in the user's database table without first being encrypted I have not included any encryption code because encryption and decryption are beyond the scope of this tutorial date of birth as date time phone number as string address first line as string addressed second line as string address city as string and lastly postcode as string let's decorate the ID field with the database generate attribute and pass the enumerator list item value of database generated option.identity as an argument to the database generated attribute so this is what is known as a code first approach to developing an application that uses a database for data storage we first create a model which is implemented as a c-sharp class then we are able to run certain commands either through.net CLI or Visual Studio to generate the data structure in our database from the models created within our application in this application we are going to run the relevant database commands through Visual Studio note as an alternative we could use the database first approach which would involve creating the database schema in the database and then generating the models from the database schema using appropriate database commands we'll use the code first approach in this application so note that by decorating the ID field with the database generated attribute the way we have done here we are declaring that we wish to create the ID field as a primary key in the relevant database table and that this ID field must Auto increment each time a new row is added to the relevant database table so the next step is to install the relevant Entity framework core package the package we need for this application is Microsoft dot Entity framework core dot SQL Lite so let's browse for the relevant nuget package using the nuget package manager facility provided within Visual Studio and let's install the microsoft.ensity framework core dot sqlite package so the next step is to add a DB context class to our project let's first create a folder named data let's add a class to the data folder and name it club membership DB context so this class must inherit from The Entity Frameworks DB context based class DB context class resides in the microsoft.ensity framework core namespace so let's create a directive to this namespace in our club membership DB context class and now let's override the DB context based classes on configuring method within this method we can configure a connection to the sqlite database that we wish to create and access we are using the DB context option Builder object to configure our connection string the connection string here is very basic it contains a file path to our database file the database file will reside in the same location from where our code will run this is achieved by using the appdomain.currentdomain.base directory property to establish the path to our sqlite database file we are then passing the DB context options Builder object to the DB context class using a call to the base method the next step is to create a table database structure for our relevant model class so we only have one model class to worry about here I.E the user class so we use the entity Frameworks DB set generic type and pass the user type as a generic argument to the DB set type to establish the type of property that will contain a reference to the users table that will be generated in our sqlite database Entity framework will use this user's property to add data to the user's database table and retrieve data from the user's database table we could also use the user's property to update data within the user's database table but we won't need to implement database record updates in this application so before we run the update hyphen database command within visual Studio's package manager console facility we need to create what is known as a migration so we can use the add hyphen migration command for this purpose like this okay so why has that failed the reason is that we need to install the microsoft.entity framework.tools nuget package so let's do this let's try to create the migration again and this time it succeeds and there's the migration class created for us and you can see that the code in this class contains a method to create the user's table and it also creates a method to drop the user's table so in order to run the migration we can run the update hyphen database command like this okay great so let's see if our database has been created as expected and it has great let's open the database in the sqlite browser client facility to see if our users table has been created as expected and it has excellent so now let's create a project that will serve as an API providing reusable validation functionality let's remove the default class and let's create a class named common field validator functions let's make this class public and let's add five delegate definitions the first delegate definition defines a delegate type that can reference a method used for the purpose of ensuring that a form field is not left empty the second delegate that finds a delegate type that can reference a method used for constraining the character length of a text field to between a minimum and maximum value the third delegate definition defines a delegate type that can reference a method that validates the date the fourth delegate definition defines a delegate type that can reference a method that can be used for validating a text input field value against a regular expression pattern the fifth delegate definition defines a delegate type that can reference a method that validates the text field value against another text field value we'll use this delegate to store a method reference to a method that provides functionality for ensuring that the user re-enters the user's chosen password so that it matches the original entry for the password field during the registration process let's create private static member variables for each of these delegates let's create the method implementations for each of these delegates namely required field valid string field length valid date field valid field pattern valid and field comparison valid so to expose our delegate objects to calling code let's create a public static read-only property for each related delegate with each of these public properties we are creating a new delegate object of the appropriate delegate type and passing in the appropriate method name into the delegate types Constructor we are using a Singleton pattern to ensure that only one instance of each of these delegate objects can be created foreign so let's create a class and name it common regular expression validation patterns I've already sourced four common regular expression patterns from the following useful website that can be found at this URL I'll also include a link to this URL Below in the description I've copied the relevant regular Expressions to notepad I'll copy and paste these regular expression patterns from notepad into the common regular expression validation patterns class as stated earlier the code for this tutorial can be downloaded from GitHub please see a link to the appropriate repository Below in the description note that you are able to copy and paste these regular expression patterns into your code from the GitHub webpage at this URL a link to this webpage has been included Below in the description okay so let's create a directory named field validators this directory will contain field validator classes each validator class will correspond to a particular View we'll create the view classes in a bit let's first create an interface named I field validator let's make this a public interface So within the club membership application.fieldvalidators namespace let's create a delegate definition named field validator Dell this is a very important delegate as it can reference a method that validates fields for any form so for example we are going to reference a method to validate our user registration form Fields but say for example we needed to capture banking information we could create a custom validator class for this purpose and within a newly created banking form view class we could reference an appropriate validator object derived from the validator class and use this validator object to validate the banking related fields so we will be using this delegate definition to create a delegate that references a method for validating Fields presented to the user in our user registration view class so the parameters defined for this delegate are field index defined as an integer for the purpose of referencing a field value within an array of fields field value as string this parameter will be past the field value to be validated field array this is an array that will store all validated fields for a particular View and lastly a parameter named field invalid message and preceding this parameters definition is the out keyword which allows its value to be outputted to calling code so for field is invalid a relevant message created within the relevant referenced method can be outputted to the calling code which can then for example output the message to the user so let's create a method signature for a method named initialize validator delegates a method that implements code for this method definition can be used to initialize the validation delegates that will be used for a particular View then field array provides a definition for a read-only property that stores a reference to an array of field values and lastly validated Dell provides a definition for a read-only property that stores a delegate object that references a method responsible for validating the fields in a particular View let's create a class named field constants we are only going to store one enum in this class which will be used to index an array which contains field values for the user registration form using enum list item values to index our array instead of integer values makes our code more readable simply because at a glance we can see exactly where our field resides in the relevant array so let's create an enum named user registration field and let's create an enum list item value for each of the fields in our user registration form great so let's create a class that implements the I field validator interface so this class is named user registration validator let's define four constants at the top of the class these will be used a bit later to validate our first name and last name field lengths let's create a delegate that will be used to determine if an email address already exists in the system if an email address already exists the user's entry will be deemed as invalid let's create a private member variable of the field validator Dell type this delegate will store a reference to a method responsible for validating the user registration fields let's define a private member variable for each of our common validator delegates required valid Dell string length valid Dell date valid Dell patent match valid dull and compare field valid Dell let's create a private member variable to store the delegate object that will reference a method responsible for checking if a user email address input already exists in the system let's create a private member variable for storing an array of valid field values entered by the user and let's create a property named field array that will create a field array object if one has not yet been created note how we are using the length property of the enum.getvalues method to make appropriate space Provisions for our field array array each enum list item in our user registration field enum must have an index counterpart in the field array array yeah let's expose the validator Dell delegate through a public read-only property and one thing I've forgotten to do is indicate that this class implements the I field validator interface so let's do this and now let's initialize the appropriate validator delegates within the initialize validator delegates method here we are referencing the delegates already wired up to their appropriate methods created for us in the common field validator functions class which resides in the field validator API project foreign let's create a private method that will be responsible for validating each of the fields used to register a club member this method will be referenced by the field validator Dell delegate let's create the basic structure for the valid field method let's wire up the valid field method to the field validator Dell delegate within the initialize validator delegates method okay let's implement the code for the valid field method let's first convert the field index parameter to the user registration field enum for the purpose of creating more readable code so the first field we wish to validate is the email address field so let's write code to ensure that text has been entered into the email address field by calling the required valid Dell Delegate for this purpose so if the text has not been entered for this field we wish to Output an appropriate message to do this we can set the field and valid message parameter to an appropriate message note that the field and valid message parameter contains the out keyword in its definition which means its value can be outputted to the calling code so we also want to ensure that the user's email address input conforms to an appropriate regular expression pattern used for validating email addresses we can do this by using the pattern match validol delegate and if the user has entered an email address but it is not in a valid format we want to set the field invalid message output parameter to an appropriate message so for the first name field we must include validation so that the first name field can only contain a text value with a length that is between 2 and 100 characters the last name field must also only contain a text value that has a character length between 2 and 100. foreign the password field must contain a value that conforms to the following rules it must contain at least one small case letter one capital letter one special character and must be between 6 to 10 characters in length an appropriate regular expression pattern is used to validate the password the password compare field must contain a value and its text value must be an exact match to the password field date of birth must contain a value and be a valid date the phone number field must contain a value that conforms to a pattern defined for a valid UK phone number address first line must contain a value address second line must also contain a value and address City must also contain a value postcode must contain a value that conforms to a pattern defined for a valid UK postcode foreign and you can see that the method returns a Boolean expression if the field invalid message output parameter has not been set during the validation of a particular field this means that the field is valid and a Boolean value of true will be returned to the calling code however if the field and valid message output parameter has been set to one of the validation messages the field valid method returns false because the field value inputted by the user has been deemed to be invalid by our field valid method I know there is quite a lot of detail in that method please feel free to copy the code for this method which can be found at the GitHub webpage at this location okay so let's go back to the data folder let's add an interface named I register let's add a method definition named register that contains a string array parameter the method that implements code for this method definition will accept a string array argument which will contain valid field data inputted by the user and this field data will be saved to the users table in our sqlite database this method definition must also return a Boolean value then let's create a method definition for a method that will be referenced by a validation delegate the delegate will be executed in order to check if the email address entered by a user already exists in the database table named users this method definition provides a definition for a method that contains a string parameter and returns a Boolean value right let's create another interface and name this interface I login this interface defines one method definition for a method that accepts two string arguments and returns an object of type user let's add a class named register user and indicate that this class implements the I register interface so let's provide a code implementation for the register method let's instantiate a DB context object from the club membership DB context class with any using block let's create a user object and set its properties so we can save its values to the user's database table okay there's a problem here I forgot to include the email address field in the user model so what we need to do is first update the user model then we need to add a migration thank you and update the database let's use the SQL browser client application to see if our email address column has successfully been added to the user's database table and it has great let's add a directive to the club membership application dot field validators namespace at the top of the code so that we can access the user registration field enum and we can use the user registration field enum to index the field array passed into the register method using an enum for the index provides better readability of our code we must ensure that we cast the enum values to integer values when using these values to index items within the field array foreign once we have finished creating the user object we can save it to the users database table note that we simply pass the user object as an argument to the add method to add the data stored in the user object to the user's database table and to confirm our intention we must call the save changes method on the DB context object to save the data stored in the user object to the user's database table let's now Implement code for the email exists method foreign we can use the any extension method provided in the system.link namespace to check if the email address text value passed into the method already exists within the user's database table if it does this method will return true if it doesn't exist this method will return false and we can now go back to the user registration validator class and wire up the email exists method to the email exists Dell delegate first let's make sure that the register object derived from the register class that we just created is passed into the user registration validator classes Constructor then let's wire up the email exists method provided in the register class to the email exists delegate within the initialize validator delegates method we can then implement the appropriate validation code in the field valid method to check if the inputted email address already exists within the user's database table foreign classes let's create two ancillary classes let's first create a class named common output text let's create and Implement three read-only static properties one for returning the main application heading one for returning a heading for the user registration View and one for returning a heading for the user login View so let's create three corresponding methods that write these headings to the console screen write main heading right login heading and write registration heading let's create another class and let's name this class common output format let's create an enum named Font theme with three enamelist item values namely default danger and success let's create a method named change font color that contains a parameter of type font theme so if the font theme is equal to Danger let's make the output font color red and let's make the foreground font color white if the font theme is equal to success let's make the background color green let's make the foreground color white else if the font theme is equal to default let's reset our console screen to its default color settings right let's create our view classes let's create a folder named views within the views folder let's create an interface named I view let's make this a public interface let's create a method definition named run view which contains no parameters and does not return a value let's create a property definition of type I field validator note that each view can have zero or one field validate to objects associated with it if for example the relevant view does not contain input fields and therefore does not need a field validator class the appropriate property will be set to null so let's add a new class name to user registration view let's add two private member variables one of type I field validator the other of type I register let's indicate that this class implements the iview interface let's ensure that the Field validator property Returns the private member variables value which is of the same type thank you let's create a Constructor this Constructor contains two parameters one of type I register and the other of type I field validator let's appropriately assign our two private member variables the object values that will be injected into the user registration classes Constructor when the user registration class is instantiated into an object at runtime let's create a private method named get input from user this method contains two parameters one parameter of the user registration field enum type and the other of the string type foreign let's create a local string variable named field vowel this string variable will store the user's input let's create a do Loop the doolib's condition returns true if the user's input is deemed invalid by the field valid method so when the field valid method returns false within the while condition the while condition returns true which means the do Loop will perform a subsequent iteration the effect of this is an appropriate message will be outputted to the user instructing the user that the input just entered is invalid the user will then be prompted once again to enter a value for the relevant field so the user will be prompted for a particular Field's value until the user's input is deemed valid by the validation code let's write code within the do Loop to prompt the user for the user's input for the appropriate field let's assign the user's input to the field valve string variable in the field valid method let's call the validator Dell delegate and pass an appropriate arguments let's write code that will output text in an appropriate format when the user input is deemed as invalid let's write code in the run view method that will assign the user's input to a space within the field array array if the user's input is valid let's write a private method that will save the user's registration information to the user's database table in our sqlite database let's call the register user private method from the run view method okay so let's create the login View let's add a class to the Views folder named user login View let's write code to indicate that we want the user login view to implement the iview interface let's Auto generate the iview members that we must implement let's set the Field validator property to null because in this code example we are not going to include validation on the login fields we could add a custom validator class and Implement validation code for the fields of this login view if we chose to do so but in the interests of time let's omit this functionality let's create a Constructor that contains a parameter of type I login let's create a private member variable of the type I login let's assign the object argument that will be injected into the user login view classes constructed during the instantiation of the user login view class to this private member variable So within the run view method let's first write the application heading to the screen and let's then write the login heading to the screen so let's make sure we are writing the main heading to the screen within the run view method of the user registration view class let's go back to the user login view class let's write code to prompt the user for the user's email address let's assign the user's input to a local string variable let's write code to prompt the user for the user's password and let's assign the user's input to a local string variable let's call the login method on the underscore login user object and pass in the two local variables containing the user's input into the login method and this method returns a user object if the user is authenticated so we need to check if the user object is not null which means the login has been successful and we'll write a to-do comment for now to indicate that we wish to implement code here to run the welcome view when the login is successful we'll create the welcome view class in a bit then replace the to-do comment with the code to run the welcome view else if the login is not successful we'll simply clear the screen and output a message stating that the user's entered credentials do not match any of the system's records so let's create the welcome View in the run view method of the user welcome view class we are simply outputting a message welcoming the user to the Cycling Club and let's replace the to do comment in the run view method in the login view class with code that creates a user welcome view object that invokes the run view method which displays a welcoming message to the user on the console screen so let's create the main view class we'll set the field validator to null because this view doesn't have any fields that require validation let's Implement code in the run view method let's write the application heading to the console screen let's prompt the user to press either the L key to log in or the r key to register if the user presses the L key the user will be presented with the login screen if the user presses the r key the user will be presented with the registration screen so let's use the console.read key method to capture the user's key press let's create an if statement structure so that the appropriate functionality can be executed depending on which key the user presses and let's simply write goodbye to the screen when the user presses a key that isn't L or R let's create a Constructor that contains two parameters and let's create two corresponding member variables that will store the appropriate objects that will be passed into this Constructor at runtime let's create a private method that will run the user registration View let's implement the code for this method which simply invokes the run view method on the user registration view object which is of type I view and let's also write a private method that invokes the user login View let's go back to the if statement and if the user has pressed the r key we want to present the user registration View and once the user is successfully registered we want to present the user login View if the user presses the L key the user is presented with the login screen so now we want to abstract the creation of the main view object let's create a class named Factory let's make it a public static class let's create a public static method named get main view object that returns an object of the iview type let's create a login object this object will be used to authenticate the user but it looks like I forgot to implement the authentication logic so let's create a class within the data folder and name it log in user we are going to need two namespace directives in this class so let's create a namespace directive for the club membership dot models namespace and let's also create a namespace directive for the system.link namespace this class must implement the I login interface and let's Auto generate the members of the ilogin interface that must be implemented so the I login interface only contains one method a method named login it contains two parameters one is a string parameter for the user's email address and the other is a string parameter for the user's password and now we can simply write code that compares the user's email address and password with the records stored in the user's database table in our sqlite database if the user is registered with the application the first or default extension method returns a user object if the user is not registered with the application null is returned so let's go back to the factory class and finish creating code that abstracts the construction of the main view object so in order to create the main view object we must create an object derived from the user login view class and an object derived from the user registration view class in order to create an object derived from the user login view class we must first create an object of the I login type which will be injected into the Constructor of the user login view class when the user log in view class is instantiated as an object in order to create an object derived from the user registration view class we need to First create an object of type I register the user registration view classes Constructor also contains a parameter for a custom field validator object so let's create an object of Type R field validator that derives from the user registration validator class and in order to initialize the validation delegates we must first call the initialize validator delegates method on the object derived from the user registration validator class so we can now create an object derived from the user registration view class in order to create the object successfully we must inject an object derived from the register user class and an object derived from the user registration validator class into the user registration view classes Constructor we can now also create an object derived from the user login view class and inject an object derived from the login user class into the user login view classes Constructor we are now able to inject the object derived from the user registration view class and the object derived from the user login view class into the main view classes Constructor when constructing the object derived from the main view class then we can write code to return this object from the get main view object method so notice something very important that is going on here when we construct our objects all our classes Constructor parameters are not concrete types they are interface types we are adhering to the dependency inversion principle which is represented by the last letter of the solid acronym the dependency and version principle states that classes should never depend on concretions but rather should only depend on abstractions so in this method we have implemented very basic dependency injection functionality so when the main view object is created using the get main view object method an object derived from the user login view class and an object derived from the user registration view class is automatically injected into the main view classes Constructor the main view classes Constructor contains two parameters that are of the iview type the user registration view class implements the iview interface and the user login view class also implements the iview interface so now the way we have designed this application should allow for the calling client code to be rather simple so in the main method we can simply get an object derived from the main view class by calling the factory classes get main view object static method see how clean the client code is this is because we have abstracted away all the complexities of constructing an object derived from the main view class then all we need to do is invoke the object derived from the main view classes run view method to run this application and that is our application pretty much written but inevitably there will be bugs Let's test the code let's press the r key so that we are presented with the user registration view where we'll register a user's information so let's leave the email address field blank and press enter okay and the required field validation message should have been presented so why has this not worked okay so in the field valid method within the user registration view class I forgot to include a not operator in the if condition where the appropriate field validation delegate isn't worked to test if the users input is valid so we want to Output an appropriate message to the user when a field is deemed as invalid and subsequently prompt the user to try again Let's test the fix and this time step through the codes to make sure that the code is doing what we expected to do so let's once again leave the email field blank great and this time the code that outputs an appropriate invalid field message is run and what happens if we enter a valid field value on our second attempt at entering an email address but this time we enter an invalid email address format great that is working as expected and now let's enter a correct email address and we have another bug this email address has not been saved to the system so why is our application behaving is there a record with this email address already exists in the system right so this time it is because I included a not operator where I should not have done so let's remove the not operator because we want a message to be displayed when an email address already exists in the system Let's test the code again great that is working as expected so I don't like the formatting of the prompts at the moment I want the user to enter the user's information on the same line as the prompt text so let's make the appropriate fixes let's use the console.write method rather than the console.writeline method to prompt the user for the user's input and let's append a colon followed by a space to The Prompt text for each of the users can put prompts okay so let's test the code let's enter a valid email address let's enter a valid first name and let's enter an invalid last name and that is working as expected we have included validation code whereby the first name and last name fields must contain a character length between 2 and 100. this time let's enter a valid last name let's enter a valid password and for the field where we have to re-enter our password let's enter text that does not match the password we entered great so the comparison Fields validation functionality is working and this time let's re-enter our password correctly let's enter a valid date for the date of birth field let's make up an address for the first line of our address and let's leave the second line of our address blank great so our validation message is correctly advising that we must enter a second line of our address so on the second try let's enter a made up second line for our address let's enter a valid City and let's enter a postcode in a correct UK postcode format great so we have successfully registered Carl Smith as a member of the Cycling Club so let's press any key to continue to the login screen and let's enter our credentials hi Carl welcome to the Cycling Club great so we have successfully been authenticated but the welcome view should be displayed on its own screen so let's fix this in the run view method of the user welcome view class let's clear the console screen before displaying the welcome message so I've noticed that we are not being prompted for a phone number so let's navigate to the run view method in the user registration view class and ensure that the appropriate functionality for the phone number field is added okay let's test the code and we can use the made updates of Carl Smith again because I've removed the record we added earlier from the user's database table because an old value had been added into the phone number field so let's enter some made up but valid data into the user registration form and let's open our sqlite database named Club membershipdb.db in the sqlite browser client application we can do this by dragging and dropping the data file onto the sqlite browser applications user interface like this and we can now run a SQL query through the sqlite browser client application to check if the record for Carl Smith has been added to the users table and has the phone number been added correctly this time yes it has great let's enter another record Let's test that we are now not able to enter Carl Smith's email address into the email field great let's enter information for a made-up character named Ethel Jones and we can test some of the field validation functionality along the way [Music] okay let's log in as Ethel Jones excellent let's log in as Carl Smith great [Music] hi and welcome this tutorial is being created to help with your understanding of covariance and contravariance when using delegates in C sharp in the first part of this tutorial on delegates I've mentioned that the return type and parameter types of the method referenced by a delegate object must match the return type and parameter types defined in the relevant delegates definition but I also mentioned that the return type and parameter types of the relevant method definition don't have to match with the relevant return type and parameter types delegate definition exactly so what does this mean the c-sharp language allows for the developer to have a little bit of design flexibility when it comes to a delegate's compatibility with a method covariance and contravariance provide flexibility when matching a delegate definition with a method definition covariance permits a method to have a return type that is more derived than that defined and the relevant delegate if you are unfamiliar with what is meant for a class to be more derived or less derived than another class that is a member of the same inheritance hierarchy please check out two tutorials which were provided by this channel as part of a c-sharp for beginners course one on c-sharp inheritance and the other on c-sharp polymorphism a link to these tutorials can be accessed from the cards in the right hand corner of your screen and links to these tutorials have also been included Below in the description Contra variants permits a method that is parameter types that are less derived than those in the relevant delegates type if you haven't yet subscribed please consider subscribing and please ring the bell so that you can be notified of content on advanced c-sharp concepts and much more let's look at a code example where we can demonstrate how covariance works when using delegates in c-sharp this example demonstrates how a delegate object can reference a method that has a return type that is derived from the return type defined and the relevant delegates definition so I'm going to create two Factory methods by Factory method Amino method implemented for the abstraction of constructing a specific object and returning the relevant object to calling code the first method will return an object of type ice car which is a user-defined class that will create representing a blueprint for an object that can store information for an ice car the second method will return an object of type EV car which is another user-defined class that we'll create representing a blueprint for an object that can store information for an electric car both of these classes will inherit from a base abstract class named car we are going to create a delegate that defines a method definition that contains an ID parameter of type int and a name parameter of type string the delegate type will return the car type which is the base abstract class from which the class named ice car and a class named EV car will inherit this delegate type can be used to create an object that can store reference to a method that returns a type that is derived from the car base type this is at the heart of what covariances regarding delegates even though the return types of the delegate and the method it references are not an exact match because the return type of the delegate is the base class for the return type of the method the c-sharp compiler allows the delegate to reference the method let's create a.net core console application I'll name the project and solution covariance and contravariance delegate example let's create an abstract class named car let's add two auto-implemented properties to the car user-defined class one named ID of the integer data type and the other named name of the string dates type let's add a virtual method that doesn't contain any parameters and returns a value of type string let's name this method get car details this method is very basic and returns an interpolated string value containing the values for the ID and the name properties so let's create our first class that inherits from the car abstract class let's name this class ice car and we are going to keep this example very basic so that we can focus our attention on the topic of this tutorial namely applying covariance and contravariance when using delegates and C sharp so let's override the get card details method this method will simply return an interpolated string value which will contain a value returned from its base method counterpart followed by the text which will contain a hyphen followed by the text internal combustion engine ice and let's create a class that is very similar to the ice car class but this class will serve as a blueprint for objects that store information about an electric car so let's duplicate the ice car class and change it so that it is appropriate for our EV car class so this class is named EV car so the get card details method in the EV car class will return an interpolated string value containing a value returned by its base method counterpart which will contain the relevant car objects ID and name property values followed by the string literal hyphen Electric so now let's create a factory class let's name it car factory and let's make this class a static class and let's create a static method named return ice car that returns an object of type ice car this method contains two parameters one of type int and the other of type string and the code for this method simply returns an object derived from the ice car type to the calling code unless creates another method which is almost identical to the return ice car method the only difference being that instead of returning an object derived from the ice card type it returns an object derived from the EV car type so the question is can we reference either of these two methods from a delegate object where its delegate definition is an almost exact match of the return ice car method definition and the return EV car method definition the only difference being that the delegate will Define a method definition that Returns the car type I.E a less derived type so let's create a delegate named car factory Dell that defines a method definition that contains two parameters one of type int and the other of type string and returns a value of type car so in the main method let's define a delegate named car factory Dell and assign it the method name of return ice car the return ice car method returns an object of type ice car and the delegate definition Returns the car type notice that the c-sharp compiler is not complaining about this because the ice car type derives from the car type and covariance is allowed in C sharp so let's write code to execute the delegate and assignee object to a variable named ice car so we'll give this car object an ID of one and a name of Audi R8 let's write code to write the type of the object to screen let's write code to execute the objects get card details method to retrieve the object's available information and write this information to the screen and let's use the same delegate type to reference the return EV car method the EV card type is derived from the car type so because covariance is permitted in the c-sharp language the return EV car method is deemed as compatible with the car factory Dell delegate let's run the code and we have successfully demonstrated how covariance can work when using delegates in c-sharp so let's demonstrate how contravariance can work when using delegates and C sharp so to demonstrate contravariance when using delegates and c-sharp we are going to create two delegates both delegates will be used to reference a method used for logging information about a car both delegate definitions will not return values the first delegate definition contains one parameter of the ice car type the second delegate's definition contains one parameter of the EV card type the key to relating this example to contravariance is that both of these delegates contain one parameter that inherits from a car type note the two delegate definitions contain a parameter that is more derived than the parameter contained in the method that these delegates will reference the method that both of these delegates will reference will contain one parameter of type car the method will not return a value so let's first remove the lines of code not needed in this example demonstrating how contravariance Works in C sharp when using delegates let's create the first delegate and we'll name it log ice car details Dell let's create the second delegate and we'll name it log EV card details Dell and now let's create the static method that will be referenced by both of these delegates we'll name this method log car details and notice how the parameter contained in its method definition is of type car note that the delegates that will reference this method will contain parameters that inherit from the car type so let's implement the code for this method the logic for this method is that if the type of object passed in as an argument to this method is of type ice car log the car's object type and information to a text file we'll use the appdomain.currentdomain.base directory property to establish the path of the relevant text file so that it is created in the same path from where our code will execute else if the type of object passed into the log car details method is of type EV car log the car's object type and information to the console screen else throw an argument exception so let's run code to reference the log card details method from our log ice car details Dell delegate let's write code to execute the log ice card details Dell delegate let's write code to reference the logcard details method from our log EV car details Dell delegate let's write code to execute the log EV card details Dell delegate notice that even though the parameter contained in the log ice car details Dell delegate definition is not an exact match of the parameter contained in the log car details method definition the c-sharp compiler does not complain when we write code where the log ice car details Dell delegate references the log car details method and the same is true when we write code where the log EV card details Dell delegate object references the log car details method this is because the parameter type contained in the log ice car details delegate definition inherits from the parameter type contained in the logcard details method definition and the parameter type contained in the log EV car details Dell delegate definition inherits from the parameter type contained in the logcard details method definition this example demonstrates contravariance when using delegates in C sharp where a delegates parameter may not match exactly with a parameter of a method that the relevant delegate object references but if the relevant parameter in the relevant method definition is part of the same inheritance hierarchy and is less derived than the relevant delegates parameter this is allowed because contravariance is permitted in the c-sharp language let's run the code and this is an expected result let's see if the EV car's information has been logged to the relevant text file [Music] [Music] great [Music] I hope you've enjoyed this tutorial on understanding covariance and contravariance when using delegates in C sharp this is the fourth part of a video series on delegates in this video we'll look at the funk action and predicate built-in generic delegates so before we dive into this topic we must have at least a basic understanding of generics generics is a topic that we'll explore in detail in upcoming videos but for now a basic understanding will suffice so what is generics in c-sharp version 2 generics was introduced generics makes it possible to for example design classes methods and delegates that defer the specification of one or more types until the class method or delegate is declared and instantiated by client code use generic types to maximize code reuse type safety and performance a developer can create generic interfaces classes methods events and delegates in this video we'll look at three types of generic delegates that are provided in the c-sharp language namely Funk action and predicate all of these generic delegates are available in the system namespace let's look at an overview of each of these built-in generic delegates before we look at basic code examples demonstrating their implementation so let's first look at funk in this depiction we can see the basic structure for a funk delegate the T represents a placeholder where the developer can pass a type parameter in order to strongly type the parameter relevance to the encapsulated method at compile time in keyword in this context means that the parameter type is contravariant we are not going to be discussing covariance and contravariance in this video because these topics were discussed in detail in the previous tutorial foreign [Music] there are 17 Funk delegates available in the system namespace this funk Delegate for example can be used to encapsulate a method that contains no parameters and returns a value There are 16 more Funk delegates here is a fund delegate that contains one perimeter and returns a value here's another Funk delegate that contains two parameters and returns a value Funk delegate definitions always return a value the return type is always defined in the last type parameter and the available func delegates allow for 0 to 16 parameter type definitions note that the last parameter declared in the funk generic delegate defines the type of The Returned value of the method that the func delegate encapsulates the out keyword in this context means that the return type is covariant the action generic delegates allow developer to encapsulate a method that can have 0 to 16 parameters and must not return a value the predicate's generic delegate encapsulates a method that contains one parameter and returns a value that must be of the Boolean data type a predicate delegate represents a method that defines a set of criteria and determines whether the specified object meets those criteria let's look at code examples using each of the built-in generic delegates I.E func action and predicate at the end of the tutorial we'll look at an example of using an extension method that takes a predicate as an argument let's start by looking at an example using the funk built-in generic delegate let's create a.net core console project I'll name this project and solution func action predicate examples [Music] thank you [Music] let's create a public class named math class and add one method named sum the sum method contains two parameters of the int data type and returns a value of the end data type this method simply Returns the integer result of the sum of two integer arguments passed into this method let's instantiate the math class in the main method let's use the generic built-in Funk delegates to encapsulate the sum method altar parameters passed into the funk delegate are of the in-states type the last type parameter represents the return type and the first two type parameters represent the methods parameters data types so as you can see through the use of generics we have made our Funk delegate compatible with the sum instance method we have strongly typed the funk delegate with the in-states type for the parameter types and the return type we can therefore use the func delegate to encapsulate the sum method let's write code to execute the delegate and then code to write the results to the screen Let's test the code great we can replace the sum method with an anonymous method using the delegate keyword like this an anonymous method is as the name suggests a method that does not have a name Let's test the code great we can further abstract the method by removing the delegate keyword the return keyword the curly brackets and the parameter type definitions so here we have now reduced the functionality of the sum method to a Lambda expression a Lambda expression is an anonymous function which as discussed is a defined function not bound to an identifier we previously created the same function using the delegate keyword a Lambda expression is a shorter way of representing an anonymous method Lambda Expressions were introduced in C sharp version 3 along with link for more information on link please navigate to this URL Let's test our code excellent to further understand the func generic built in delegates let's create our own imitations of a few of the built-in Funk delegates let's call our delegates funk 2. foreign keyword with func 2 in our code great but we don't need to do this because appropriate generic delegates are already available to us in the system namespace let's create a slightly more complex example where our delegate encapsulates a Lambda expression that performs the functionality of adding two operands of the float data type together then multiplies the result of this operation by a value that is of the int data type great let's create a more practical example where our Lambda expression adds a bonus to an employee's annual salary foreign so let's look at some examples using the action generic built-in delegate so in this example let's create a Lambda expression that accepts fields for an employee record as arguments and outputs the employee details to the console screen note that the action delegate is used to encapsulate a method that does not return a value so in this example we'll output three fields of an employee record to the console screen ID first name and last name foreign let's add an annual salary field so to do this we can use a different action delegate to accommodate this new field let's update the Lambda expression accordingly let's add a gender field which is of the Char dates type and the Boolean field representing whether an employee is a manager or not a manager so to achieve this we need to use a different action delegate that can accommodate the two new fields foreign foreign excellent so let's use an example where we'll use the predicate built in generic delegate let's first create an employee class let's create a generic list that will contain four objects of the employee data type let's add some employee objects that contain made up employee details to the employees list foreign foreign that will filter the employees list based on criteria that will be passed to the method in the form of a predicate so this method simply traverses the employees list if employee items within the list meet the criteria of the predicate passed into the method the relevant item is added to another list that is returned to the calling code once all the items in the original list passed into this method have been traversed and evaluated so let's call the filter employees method and pass in the employees list followed by the Lambda expression which is encapsulated by a predicate delegate let's say our Lambda expression in this example is used to return only mail employees let's write code to Traverse the list returned by the filter employees method and use the display employee Records action delegate which I have now renamed to display employee details just for better readability that we created in the previous example to write the relevant employee records to the console screen Let's test the code great let's alter the logic of our predicate so that we return only details for employees that earn less than 45 000 a year great let's alter our logic so that we only return employee details for employees that are managers great so we can abstract this code even further through the use of an extension method so let's create a public static class named extensions let's copy the filter employees method to our extensions static class let's make the filter employees method public and it must also be static then to finish making this method an extension method all we need to do is add the this keyword before the first parameter the first parameter is defined as a generic list that is strongly typed with the employee user defined type so the filter employee extension method should now automatically be available on generic lists that are strongly typed with the employee user-defined type in our main method if you are not clear on extension methods don't worry extension methods will be discussed in detail in upcoming tutorials basically three extension methods the developer can add methods to existing types without creating a new derived type recompiling or modifying the original type so let's see if we can access the filter employees method on the employees generic list and there it is it shows up in the intellisense as expected so we no longer need to pass the employees list to the filter employees method as a parameter and all we need to do is pass in the Lambda expression Let's test the code [Music] great the system.linknamespace contains a number of extension methods let's demonstrate how we can use an extension method which is available in the system.link namespace to achieve the same result link is beyond the scope of this tutorial we'll look at Link in detail in upcoming videos [Music] let's include a directive to the system.link namespace at the top of our code the where extension method is available on the generic I enumerable type the generic list type implements the innumerable generic interface so now that we have added the system.link directive the where extension method should now be available on the employees list object so let's replace the filter employees method with the where method the where method returns a value of type I innumerable so we must convert our result to a generic list using the to list explicit conversion method Let's test the code [Music] great so let's finish up by using the funk delegate that we created earlier to add a bonus to the employee annual salary fields of each of our employee objects stored in the employees list [Music] [Music] Let's test the code foreign excellent I hope you've enjoyed this tutorial on the three built-in generic delegates namely Funk action and predicate hi and welcome this is the fifth part of a video series on delegates this is also the final part of this video series on delegates but there are a lot more upcoming videos to be released as part of this Advanced c-sharp course in this video we'll look at how delegates can be used to encapsulate a callback method so what is a callback method basically callbacks are simple functions which are used to notify the calling instance when an asynchronous code block has been executed and the result is available so I found a great code example on a Microsoft docs webpage that uses a callback method encapsulated by a delegate to run code when asynchronous tasks have completed the code in this code sample performs a basic function of retrieving the IP addresses associated with user-inputted domain names using the.net built-in DNS static class for example if we input microsoft.com the DNS class behind the scenes as it were asynchronously looks up the IP addresses associated with the microsoft.com domain name I'm going to Simply copy this sample code demonstrating the use of a callback method interp.net core console application we can then demonstrate the code and go through the code step by step to understand how it works basically this code demonstrates using asynchronous methods available in the built-in DNS static class to retrieve domain name system information for user-specified domain names you can navigate to this URL to copy the relevant sample code as well as read more information about the sample code the link to this URL has also been included Below in the description so let's create a.net core console application let's name this project and solution DNS async callback sample code let's copy the code from the relevant web page and paste it into the project we have just created so to do this we can select all the code that has been Auto generated in our program.cs class file and paste the code currently copied to our clipboards over the selected code right so let's start by running the code so let's enter a few well-known domain names this code has been written so that we can press the enter key without entering anything at the input prompt as an indication that we are finished inputting our data so let's enter a few domain names so for the first entry let's enter google.com for the second entry let's enter microsoft.com and for the third entry let's enter yahoo.com right let's press the enter key without entering anything at the command prompt to indicate that we are finished inputting our data and then the output presented to the screen we can see three headings namely addresses for Google addresses for Microsoft and addresses for Yahoo under these headings are the IP addresses relevant to the domain names that we have entered if you're interested in reading more about what DNS IE domain name system is please navigate to this URL so let's go through the code to see how a delegate is used to encapsulate a method that is used as a callback method through the execution of the relevant delegate once relevant asynchronous tasks have been completed so the first line of code in the main method instantiates a delegate named async callback this delegate is built into.net and is provided specifically for the purpose of encapsulating callback methods that are used during asynchronous operations so I'm going to right click the delegate name in the visual studio code editor and click the context menu item named go to definition and here we are presented with the delegate definition of the async Callback delegate this delegate can encapsulate a method that doesn't return a value and contains one parameter of the I async result type and if we look at the I async result type this interface provides a standard definition for objects that are passed as an argument to the Callback method the relevant object that implements the I async result interface represents the status of an asynchronous operation you can see here the async state read-only property gets a user-defined object that qualifies or contains information about an asynchronous operation okay so let's go back to our code and you'll see that a method name is passed into the Constructor of the async Callback delegate in the code written for the purpose of instantiating an object derived from the async Callback delegate type so our callback method is named processdns information let's have a brief look at this method you can see its method signature conforms to the method definition defined in the async Callback delegate so we'll come back to this method in a bit for now let's go back to the code in the main method so next the code is prompting the user for domain names and you can see that for each entry the DNS dot begin get host entry method is fired DNS is a static class provided in.net and provides simple domain name resolution functionality the DNS dot begin get host entry method asynchronously Returns the Internet Protocol IP addresses for the specified host you can see that our delegate named callback that encapsulates our callback method named process DNS information is passed as an argument to the DNS dot begin get host entry method here the code essentially informs the DNS static class of the memory address of our designated callback method which is stored in the Callback delegate object note that above this line of code we have a line of code that increments an integer variable named request counter the number of asynchronous tasks is stored in the integer variable now the reason why this incrementation is done in an unusual way here whereby the.net built-in interlocked dot increment method is used for this purpose is because each time our asynchronous process is kicked off as it were by the DNS dot begin get host entry method a new thread is created and executed in parallel asynchronously to the main thread when each asynchronous process is finished processing the Callback method is executed on the main thread and if we go back to our callback method you can see that each time an asynchronous task completes the request counter variables value is decremented within the process DNS information callback method so because the timing of when this callback method will be called by potentially multiple threads is uncertain we must ensure that the request counter variable is updated in a thread-safe way multi-threading solves problems with throughput and responsiveness but in doing so it introduces new problems Deadlocks and race conditions for more information in this regard please navigate to this URL so the next line of code monitors the state of the value of the request counter variable when the request counter variable's value is zero we know that all asynchronous tasks have completed which means our output data is ready to be presented to the screen so this while loop ensures that if our asynchronous tasks have not yet completed that the subsequent lines of code responsible for outputting the results of the asynchronous tasks are only executed once the asynchronous tasks have completed so this while loop will continue processing and outputting Status information to the screen until the request counter variable has been decremented to xero within the Callback method I.E the process DNS information method so let's look at the process DNS information callback method and you can see the dns.get host entry method is called to return the result of an asynchronous task the dns.beginget host entry method and the dns.get host entry method are used for asynchronous processing the dns.get host entry method gets called from within the Callback method remember a reference to the Callback method was passed as an argument to the dns.beginget host entry method this was done by passing the async Callback delegate object stored in a variable named callback to the dns.beginget host entry method as an argument remember an async callback delegate object was coded to encapsulate the process DNS information method within the main method this object was then passed as an argument to the DNS dot begin get host entry method so the application knows that an asynchronous task has completed because at this stage the Callback method process DNS information method has been invoked So within the Callback method it is safe to call the dns.get host entry method to return the result of the asynchronous task to the calling code so the results here are stored in an arraylist member variable named host data the host data arraylist can be used to retrieve the relevant results and present the relevant results to the console screen and you can see the code here in the main method responsible for outputting the results of each asynchronous task to the console screen so the IP address is relevant to the domain names entered by the user are written to the console screen let's run the code and enter some domain names excellent note that the code we have just demonstrated here uses the asynchronous programming model APM pattern also called the I async result pattern which is the Legacy model that uses the I async result interface to provide asynchronous Behavior Microsoft recommends moving forward that we use the task-based asynchronous pattern tab for asynchronous programming which uses a single method to represent the initiation and completion of an asynchronous operation the async and await keywords in c-sharp add language support for the task-based asynchronous pattern we'll look at the task-based asynchronous pattern tab in detail in upcoming tutorials this video serves as a demonstration of how delegates can be used to encapsulate callback methods and also serves as a brief introduction to asynchronous programming we'll look at the recommended approach to asynchronous programming I.E the task-based asynchronous pattern tab in upcoming videos please navigate to this URL for more information on asynchronous programming patterns available in c-sharp summarize in this five part video series on delegates we discussed that a delegate is a reference type in c-sharp that references a method that contains a particular parameter list and return type we discussed that due to a concept called variance the delegate definition does not have to exactly match the parameter types or the return type of the method that it encapsulates contravariance means that a delegate for example can reference a method where a particular parameter in the delegates definition is more derived than the parameter counterpart contained within the method that it encapsulates covariance means that the return type in the delegates definition can be less derived than the return type of the method that it encapsulates we looked at three built-in generic delegates namely Funk action and predicate we looked at how these generic delegates can be used in code for better code reuse type safety and to improve performance we also briefly looked at Anonymous methods Lambda expressions and extension methods in this final video on delegates we looked at how a delegate can be used to encapsulate a callback method that can be called once an asynchronous task is completed we haven't looked at delegates in relation to events yet an upcoming tutorial on events will include how delegates are used in relation to events in C sharp I hope you have enjoyed this tutorial on asynchronous programming using delegates to encapsulate callback methods and I hope you've enjoyed this video series on delegates if you didn't fully understand all the concepts discussed in this video please don't worry the more you practice the more you'll understand and the more proficient you'll become as a software engineer learning to become a proficient software engineer is a marathon and not a Sprint I'd also like to add that I think it is more important to understand the concepts behind the code rather than the code itself [Music] hi and welcome this is the first part of a tutorial on c-sharp events in this video we'll look at the basics of c-sharp events by examining a piece of code taken from a Microsoft docs web page for more content on advanced c-sharp concepts like this and much more please consider subscribing and please ring the bell so that you'll be notified of future releases from this channel I usually use my Windows PC to record my demonstrations but I've decided to demonstrate this code example using visual studio 2019 Community Edition for Mac it doesn't ultimately matter which code editor you use if you want to follow along it makes no difference because this video is about the code more specifically about the basics of what events are and how they relate to delegates so I'm going to use Visual Studio 2019 for Mac Community Edition to create a.net core console project you can name it what you like I'll name this project threshold reached event application I'm going to copy the code from the appropriate Microsoft docs web page and paste it over the code in the program.cs file like this code sample is available at this URL so the code here performs a very basic function it first generates a random integer value which can be any non-zero integer value where the maximum value is 10. the centage of value serves in this example as a threshold value the code then prompts the user to press the a key to increment an integer value by a value of 1. when the integer value has been incremented to the extent that it reaches the threshold value I.E the generated random integer value and event is raised and the calling code handles the raised event by outputting text stating that the threshold value has been reached the text also includes the date and time when the threshold value was reached by the value that the user is able to increment by pressing the a key so let's start by running the code and then we'll look at the code in order to see how an event and a delegate have been implemented in the code let's press the a key until the threshold is reached and the threshold has been reached so the event is raised and the event handler outputs appropriate text to the console screen so what exactly is an event in C sharp events are special kinds of multicast delegates that can only be invoked from within the class or struct where they are declared if other classes or structs subscribe to the event their event handler methods will be called when the class where the delegate has been declared raises the event [Music] events can be marked as public private protected internal protected internal or private protected these access modifiers Define how users of the class can access the event for more information on access modifiers please navigate to this URL events.net are based on the delegate model the delegate model follows the Observer design pattern which enables the subscriber to register with and receive notifications from a provider we'll discuss the Observer design pattern in an upcoming video an event sender pushes a notification that an event has happened and an event receiver receives the notification and defines a response to it an event is a message sent by an object to Signal the occurrence of an action delegates were explored in detail in the last tutorial the third part of this course links to the playlist on delegates have been included Below in the description you can also access this playlist through the card available in the top right hand corner of your screen let's recap what is a delegate a delegate is a type that holds a reference to a method a delegate is declared with a signature that shows the return type and parameters for the method it references and it can hold references only to methods that match its signature a delegate is thus equivalent to a type safe function pointer or a callback a delegate declaration is sufficient to define a delegate class right let's look at our code example to see how an event can be implemented in C sharp so an event can be fired through a user action for example button press or through the code logic itself in this example the event is raised through the code logic here we have a user-defined class named counter where an event is declared the name of the event is threshold reached let's look at how this event is defined so this event has a public access modifier and to Define an event we must use the event keyword then the event keyword is followed by a built-in c-sharp delegate named event handler delegates have many uses in.net in the context of events a delegate is an intermediary or pointer-like mechanism between the Event Source and the code that handles the event you associate a delegate with an event by including the delegate type in the event declaration let's select the event handler delegate name in the code editor let's right click and select the go to declaration menu option if you are using visual Studio for Windows this context menu item will be marked go to definition so here you can see the event handler delegate declaration that can be used to store reference to a method that contains a matching parameter list and return type to the event handlers parameter list and return type in the delegate definition this is a built-in delegate provided in the system namespace notice the T event args generic parameter there is another built-in event handler delegate of the same name also provided in the system namespace this particular delegate declaration looks like this the difference between this delegate and the one we are using is you are restricted to using the event args class to provide event data to the event handler method using this delegate notice that in the definition of the event-handed delegate that we are using we are able to provide a type parameter through generics this means we are not restricted to the use of the event args class to pass data to the event handler method and we can use a custom class for this purpose here you can see we are using the threshold reached event args custom class where data are about an event can be stored in two public properties namely threshold and time reached so this event handler delegate contains two parameters in its delegate definition the first parameters of type object which allows for the calling code event handler method to accept an argument that references an object instance derived from the class where the relevant event resides that this keyword can be used as a reference to the object that contains the event so that this keyword can be used to pass a reference of the sender object to the appropriate event handler method when the relevant event is raised the second parameter through generics allows the developer to define a type for this parameter the advantage of being able to use generics with this delegate is that we are able to create our own custom user-defined type that can contain the relevant event data which can be passed as an argument to an appropriate event handler method in the calling code so let's look at a basic overview of the counterclass I.E the user-defined type where our event is declared here we have two member variables both of the integer data type one to store the threshold value the other to store value that will be incremented by the user so the threshold value is passed through by the calling code through a parameterized Constructor when the calling code instantiates an object derived from the counter class the past in argument is then stored in the member variable named threshold let's look at the add method this method can be used to increment the member variable names total the value stored in the total member variable is then compared to the values stored in the threshold member variable if the value stored in the total variable which is incremented by the user reaches the value stored in the threshold variable and event is raised let's look at the code responsible for raising the relevant event firstly an object derived from the threshold reached event args class is instantiated the threshold reached event args used to define type is the custom type we have passed as a parameter to the event handler delegate an object instantiated from the threshold reached event args class can be used to store event information if you look at the threshold reached event args class you can see that it contains two properties one named threshold for storing the threshold value and the other named time reached when the user incremented value stored in the total member variable reached the value stored in the threshold member variable so these two properties are appropriately set on an object derived from the threshold reached event args class this object is then passed into a method named on threshold reached the on threshold reached method contains the logic for raising the appropriate event in this method code is first created where a variable named Handler is used for referencing the threshold reached event the next line of code is an if statement checking if the Handler variable contains a value if the Handler variable is null this means that calling code has not subscribed to the relevant event which means no appropriate method has been designated on the client calling code to handle the relevant event when the event is raised in a bit we'll look at how a calling client can subscribe to an event that resides in a particular class so if however calling client code has subscribed to the relevant event the Handler delegate is invoked this delegate will point to a method that has been defined in the calling client code the relevant method is designated to handle the relevant event at the point where the calling client subscribes to the relevant event so let's look at the calling client code let's go to the main method so the first line of code is instantiating an object derived from the counter class note that the random.next method is being used to pass a non-negative random integer that is less than the specified maximum which in this case is hard coded to a value of 10. so the randomly generated number is our threshold which will be stored in the relevant object derived from the counter class so the object derived from the counterclass is stored in a variable named C using the object referenced by the C variable we are now able to subscribe to the event named threshold reached which is declared in the counter class so the code here is assigned a method that resides in the program class to the threshold reached event we can do this because the method named C underscore threshold reached is compatible with the event handler delegate in other words the parameter list and the return type of the C threshold reached method definition matches the parameter list and return type of the event handler delegate definition the effect of this is that when the threshold reached event is raised from the add method within the counterclass the subscribed method in the calling code IE the C underscore threshold reached method will be invoked a reference to the relevant object derived from the counterclause or sender object is passed in to the C underscore threshold reached method as well as the object that stores the relevant event data in this case the object arrived from the threshold reached event args class note how in this example the event handler delegate is an abstraction that allows any calling client that contains a method with a method definition that matches the event handler delegate definition to handle what happens when the relevant event is raised this means the calling client is Loosely coupled with the class where the event is declared you see the calling code doesn't have to know anything about the class where the event is declared and the class where the event is declared doesn't need to know anything about the calling code the event handler delegate in this case is used to establish a loose coupling this is a key concept to understand when it comes to using events in C sharp how delegates can be used to create a loose coupling between components so let's watch this in action let's put a breakpoint in the code to a point where the value incremented by the user has reached the threshold value and the event is about to fire we can then see what happens when the threshold reached event is raised let's run the code and let's press the a key to increment the value that is compared to the threshold value until our breakpoint is hit which means the user incremented value matches the threshold value and there it is a breakpoint has been hit so a variable named Handler is set to the threshold reached event the code checks if their Handler variable is null if the Handler variable is not null this means the calling code has subscribed to the event so I'm going to put a break within the C underscore threshold reached method which is the designated method for handling the relevant event and when we step through the code the threshold reached event is raised the C underscore threshold reach method is invoked and the C underscore threshold reached method handles the event in the custom way that the method has been coded and if we look at the values associated with the two arguments passed into the C underscore threshold reached method we can see that this is an expected result we have the sender object which is the object from where the event was raised and we have an object derived from the threshold reached event args class where the relevant event data is stored and let's press F5 to run the code right through and you can see the expected output presented to the screen I hope you've enjoyed this video on the basics of events in c-sharp please consider subscribing for more content on advanced c-sharp concepts like this and much more and please ring the bell so that you can be notified of future content released by this channel if you feel you've gained value from viewing this video please consider hitting the like button and please feel free to share any of my videos with anyone you feel May benefit from their content a link to the Microsoft web page that contains the code example I have used in this video is available Below in the description [Music] thank you hi and welcome this video is the second part of a tutorial on events in C sharp in this video we'll create a practical example where multiple events exist in a class we'll look at using add and remove accesses to encapsulate the functionality that gets executed when client code or calling code subscribes or unsubscribes to the relevant events code within the add accessor is executed when the client code subscribes to the relevant event code within the remove accessor is executed when the client code unsubscribes to the relevant event we'll use the event handler list built-in c-sharp collection class to store the relevant delegates associated with the relevant events when the calling code subscribes the event handler list collection class is a built-in c-sharp collection class that can be found in the system.component model namespace and is a collection specially suited for storing delegates so here's the basic idea behind this code example a device could be any device contains a thermostat which contains a heat sensor as well as a cooling mechanism so we'll have a class to represent the device a class to represent the heat sensor and a class to represent the cooling mechanism each of these classes will Implement an appropriate interface so the heat sensor class will contain three events one event that gets fired when the temperature of the device reaches or goes above 27 degrees Celsius which is 80.6 degrees Fahrenheit this event Flags a warning alert a cooling mechanism is switched on to cool the device back down to an acceptable temperature we'll create another event that gets fired when the temperature of the device has reached or gone above 27 degrees Celsius and then subsequently Falls below 27 degrees Celsius this event Flags an informational alert and the cooling mechanism is Switched Off and lastly we'll create an event that gets fired when the temperature reaches or goes above 75 degrees Celsius which is 167 degrees Fahrenheit this event Flags an emergency alert the device is shut down and Emergency Services Personnel are notified about the event foreign we discussed in the previous part of this tutorial that an event is raised either by the user's action for example the user clicks a button or the code logic itself in this example we are going to use codelogic to raise specific events for more content on advanced c-sharp concepts like this and much more please consider subscribing and please ring the bell so that you will be notified of future releases from this channel right let's get started let's create a.net core console app and let's name this project and solution thermostat Events app [Music] let's start by building a custom class to store our event information let's name this class temperature event args and let's make this class inherit from the c-sharp built-in event args class we want our custom class to store the current temperature so this will be the temperature at the time when an event is raised and we also want to store the date and time when the event was raised so let's create an auto implemented property named temperature and Define it as the double data type let's create another autoimplemented property named current date time and Define it as the date time date type next let's create an interface named I heat sensor and we'll include definitions for three events in the eye heat sensor interface all the events are associated with the built-in c-sharp delegate named event handler and here we can pass our custom class the one we have just created named temperature event args that will be used to store event information as a generic parameter to the event handler delegate so let's create a definition for an event that will be fired when the temperature reaches or exceeds a predefined emergency level let's create a definition for an event that will be fired when the temperature reaches or exceeds a predefined warning level and lastly let's define an event that will be fired when the temperature has reached or exceeded the warning level and subsequently Falls below the warning level so next let's create a heat tensor class to implement the eye heat sensor interface and we want to explicitly implement the events defined in our eye heat sensor interface for the heat sensor class so one way we can do this is hover our Mouse pointers over the red squiggly line under the eye heat sensor text then select show potential fixes and then select Implement interface explicitly and now you can see Visual Studio has created our event implementations with add and remove accesses note that these add and remove accesses are very similar to the get and set accesses that are implemented for c-sharp read write properties the add accesses will contain code that is fired when the client code subscribes to the relevant event the remove accesses will contain code that is fired when a client unsubscribes to the relevant event so we'll add code to the add and remove accesses in a bit so one thing I forgot to do was include a method definition for running the heat sensor let's include the appropriate method definition in the eye heat sensor interface and now you can see a red squiggly line under the eye heat sensor text in the class definition for the heat sensor class this is because we are not implementing all the members of the eye heat sensor interface so to fix this we can hover our Mouse pointers over the red squiggly line click show potential fixes and then click Implement interface and you can see that Visual Studio generates a method implementation for the method that we had not yet implemented for the eye heat sensor interface the Run heat sensor method we'll Implement code for the Run heat sensor method a bit later let's create two member variables at the top of the heat sensor class both defined as double the first member variable is named warning level and the second member variable is named emergency level these member variables will store values that serve as our triggers for when a relevant event should be raised for example if the temperature of the device rises above the emergency level the appropriate emergency event is raised so let's set these values within a parameterized Constructor so let's create a member variable named underscore has reached warning temperature and this is defined as the Boolean data type we'll see the significance of this member variable in a bit let's create another member variable which will reference a collection of delegates associated with the events implemented in this class we could use any of the appropriate collection classes in c-sharp for storing these delegate objects but we are going to use the built-in c-sharp event handler list class for this purpose so to use the event handler list class like this we must include a directive to the system dot component model namespace at the top of our code as mentioned earlier the event handler list class is a member of the system dot component model namespace we are going to use the event handler list classes add event handler method to add the appropriate delegates the add event handler method accepts a key value of type object for its first argument this object value serves as a unique key for accessing values in the collection and its second argument is a value of type delegate the event handler list collection class allows the developer to store delegates that can be accessed within the collection using a unique key we are also going to implement code using the remove event handler method to remove delegate objects from the relevant collection the method definition for the remove event handler method is the same as the method definition for the add event handler method definition please navigate to this URL for more information on the event handler list class so let's create three static read-only objects which will serve as key values that can be used to access the relevant delegates from within the event handler list collection let's create another private member variable which is an array of the double type named underscore temperature data so this array will Store Mock data to simulate data coming from the heat sensor at regular time periods so this data will be used to simulate the heat sensor outputting temperature data so let's create a method named seed data and populate the underscore temperature data array with data note that I'm deliberately including temperature data that is greater in value than 27 which will be used as our warning level and toward the end data that is greater in value than the emergency level which will be set to a value of 75. this is so we can raise our events appropriately when the heat sensor outputs our mock values okay so now let's implement the code for the add and remove accesses for the events that reside in the heat sensor class so in the add accesses all we want to do here is add the appropriate delegate to the event list Handler collection which is done at the point where the client code subscribes to the relevant event so in the remove accesses all we want to do is remove the appropriate delegate from the event list Handler collection and this is done at the point where the client code unsubscribes to the relevant event you can see we are using the appropriate key objects when adding the relevant delegates to the collection we are also able to use the appropriate key to remove the relevant delegate from our event list Handler collection so let's encapsulate functionality for raising the relevant events by creating three methods responsible for raising the relevant event for each of the events to find in the heat sensor class let's name the first method on temperature reaches warning level this method accepts one argument which is our custom type named temperature event args the temperature event args class is responsible for storing event data let's then write code to reference the relevant event using the underscore temperature reaches warning level key variable to reference the appropriate delegate within the underscore list event delegates object which is derived from the event handler list class when assigning the value stored in the underscore list event delegates collection object to the Handler variable we must type cost the delegates to the appropriate delegate type which is the event handler delegate that accepts the temperature event args type as a generic parameter then we need to see if indeed the client code has subscribed to the relevant event if the client code has subscribed then the Handler variable will not be null so if the Handler variable is not null we can raise the relevant event by executing the handle delegate object and passing in the appropriate arguments to the Handler delegate though this keyword is the first argument which references the current object which of course is an object of the heat sensor type the second argument contains relevant event information and is of the temperature event args custom type if you'll recall we made Provisions for storing the current temperature as well as the date and time of when the relevant event occurred and the temperature event args class right and we can now repeat the same basic pattern for the other two methods responsible for raising the other two events declared in the heat sensor class thank you so let's Implement a method to encapsulate raising the temperature Falls below warning level event handler event and let's Implement a method to encapsulate raising the temperature reaches emergency level event handler event and now let's Implement a private method named monitor temperature this method simulates the heat sensor outputting temperature information for the device being monitored so this method traverses the data stored in the underscore temperature data array which contains our mock temperature data let's write code to display the temperature to the console screen each time a temperature is read from the underscore temperature data array then we can create an else if letter whereby we can compare the temperature output to the warning level and the emergency level the emergency level has the highest value that will be evaluated so this is the first value that will be evaluated if the temperatures above the emergency level the emergency event is raised else if the temperature is above the warning level but below the emergency level the warning event is raised else if the temperature was above the warning level and subsequently Falls below the warning level we can raise the temperature Falls below warning level event note how we are using the underscore has reached warning level Boolean member variable to evaluate if the temperature Falls below warning level events should be raised the underscore has reached warning level variable must be set to True when the warning level reached event is raised so that the temperature Falls below warning level event can be raised when the temperature subsequently Falls below the warning level when the temperature subsequently Falls below the warning level we must set the underscore has reached warning level variable to false and for effect I'm going to introduce a one second delay between iterations of the underscore temperature data array as you can see I'm using the system.threading.thread.sleep method for this purpose I'm passing 1000 as an argument to this method this value denotes one thousand milliseconds which is one second and let's finish off the heat sensor class by implementing code for the Run heat sensor method so we'll simply write the text heat sensor is running to the screen to indicate that the heat sensor is running and then let's call the monitor temperature method okay so let's create the interface for the cooling mechanism class let's keep this really simple so this interface contains two method definitions one named on and the other named off as the names imply these methods represent the behaviors of switching the cooling mechanism on and off let's create a class named cooling mechanism and implements the eye cooling mechanism interface and each method will simply write appropriate text to the screen let's create an interface named I device this interface contains two method definitions one named run device the other named handle emergency we'll create the class that implements the I device interface in a bit but let's first create a class to represent the thermostat let's first create an interface named I thermostat this interface contains one method definition named run thermostat right let's create a class named thermostat that implements the Run thermostat method let's create a member variable of type I cooling mechanism let's create a member variable of type I heat sensor and let's create a member variable of type I device let's create two constants one to store the warning temperature level which is set to 27 degrees Celsius and want to store the emergency temperature level which is set to 75 degrees Celsius please note that these figures are arbitrary and serve only to help us with the code example let's create a parameterized Constructor that accepts an argument of the eye cooling mechanism type an argument of the eye heat sensor type and the idevice type we want the thermostat to have a reference to the device to which it is attached let's set the appropriate member variables to their counterpot arguments within the Constructor let's create a method where we'll wire up the events contained in the heat sensor class let's name this method wire up events to event handlers so let's use the heat sensor object passed into the thermostat class to wire up all of the appropriate events so to do this we can write underscoreheatsensor dot the event name which is in this case temperature reaches warning level event handler Then followed by the plus equals operator then we are able to press the Tab Key to Auto generate an appropriate method definition then we can rename the method if we choose and click the apply button to confirm the change so let's write code to wire up the remaining events so in the Run thermostat method let's add code to write that the thermostat is running let's call the wire up events to event Handler's private method and lastly let's call The Run heat sensor method on the underscore heat sensor object let's write code for each of the client event handlers so to handle the event for when the temperature reaches or exceeds the warning level let's first change the color of the font to dark yellow let's write warning alert the warning level is between warning level and emergency level to the console screen let's then write code to switch on the cooling mechanism then when the temperature subsequently Falls below the warning level we want the font to change to a blue color and let's write information alert temperature Falls below warning level warning level is between warning level and emergency level and then to handle the emergency event let's change the font to a red color let's output emergency alert emergency level is emergency level and above and this event is handled slightly differently to the other event handlers because we are calling the underscore device objects handle emergency method we are using the idevice interface to handle the emergency event and the device object's code which we'll soon implement and we must make sure that each font color is reset after each event is handled okay so now let's create a class to represent our device I.E the device that we are monitoring for temperature changes let's name it device and within the classes definition let's indicate that we wish to implement the idevice interface let's hover our Mouse pointers over the red squiggly line under the idevice text show potential fixes and then click Implement interface and visual studio Auto generates implementations for the members of the idevice interface for us so let's Implement code for the handle emergency method and we'll simply write out a basic Narrative of what should happen in the event of an emergency so let's write sending out notifications to Emergency Services Personnel to the console screen and then in the event of an emergency we also want to shut down the device so let's create a private method named shutdown device and this method simply outputs a narrative stating that the device is shutting down let's call the shutdown device private method from the handle emergency method let's Implement code for the Run device method so let's simply output that the device is running to the console screen then we want to construct our objects for our cooling mechanism heat sensor and thermostat components and we'll use their interface abstractions to Define each of their types and I've encountered a bit of a snag here when writing the code to construct the heat sensor object we have already created the constants for the warning level and emergency levels in the thermostat class I think these constants should rather be members of the device class and passed into the heat sensor class during the construction of the heat sensor object so let's create the two relevant constants in the device class and so that we can encapsulate the values of these constants and expose the values of these constants publicly let's create two corresponding read-only properties let's first create definitions for these read-only properties in the idevice interface and then let's implement the code for these properties in the device class and then within the thermostat class which has a reference to the relevant device object we can replace the references to the relevant constants that once resided in the thermostat class with references to the relevant read-only properties of the device object okay let's then write the code to run the device from our main method so let's write code to prompt the user to press any key to run the device then let's instantiate an object for the device then let's call the relevant object's run device method sorry I know I'm jumping around here a bit we still need to finish off the code for the Run device method let's finish creating the thermostat object then let's call the object's run thermostat method let's run the code foreign and you can see by the status output the device is running the thermostat is running and the heat sensor is running the temperature changes of the device can be seen with the output of each temperature to the console screen a warning event is raised when the temperature exceeds 27 degrees Celsius the cooling mechanism is then switched on but there's an issue because when the temperature subsequently Falls below 27 degrees Celsius the relevance status is not being outputted to the screen instead the code is raising the warning event so let's investigate what is going on here and the issue was caused I think because of all the copying and pasting I forgot to change the call to the on temperature reaches warning level method to a call to the on temperature Falls below warning level method obviously a call to the on temperature reaches warning level method is inappropriate for the condition when the temperature has reached or is over the warning level and then subsequently Falls below the warning level so let's fix this issue and let's run the code foreign and that is a correct result we can see the cooling mechanism is turned on when the temperature of the device exceeds the warning level and when the temperature has been above the warning level and subsequently Falls below the warning level the correct event is raised the correct status is therefore outputted to the screen in a blue font and then the cooling mechanism is Switched Off and we can see that all the events are firing correctly and being handled correctly toward the end the emergency event is being handled correctly which is in line with the mock temperature data that we created for this example great I hope you have enjoyed this video on handling multiple events within a class using the add and remove accesses we also use the event handler list built-in c-sharp collection class to add and remove the relevant delegates for when a user subscribes or unsubscribes to an event me [Music] [Music] [Music] [Music] hi and welcome to the third part of this tutorial on c-sharp events we have discussed that events can be triggered either by code logic or through a user's actions for example clicking a button in the previous parts of this tutorial we focused on events triggered by code logic in this video we'll focus on events triggered through user actions [Music] so in most of the tutorials provided by this channel regarding C sharp the.net core console app project template has been used as a starting point for creating the relevant sample code this has been done deliberately so that we can focus on the language of C sharp and not be distracted by framework related Concepts in this video we'll do something a little bit different we'll create a very basic code example and we'll use the blank app universal windows project template to create the project responsible for the front-end functionality of our application so we are going to develop a basic application using the uwp or universal windows platform framework this is so that we can look at how user actions for example a button click can trigger events and how the relevant events can be handled appropriately in code in this video we'll show how a separation of concerns can be achieved whereby the front-end display functionality is Loosely coupled with the back end functionality so specifically we'll look at how events can be implemented to achieve this so one of the advantages that can be achieved by separating concerns is we can have one team that specializes in front-end design working on the look and feel of the application and the back-end functionality can be developed by a completely different team these two concerns can evolve independently from one another and in parallel to one another the integration of the relevant components at an appropriate time can become a relatively trivial task we are going to show how this loose coupling effect is achieved through the appropriate use of an event a design pattern that can be used to achieve this loose coupling of front-end and back end components is called mvvm which stands for model view view model for more content on advanced c-sharp concepts and much more please consider subscribing and please ring the bell so that you can be notified of future content released from this channel another advantage of implementing the mvvm design pattern to achieve this loose coupling of components is we are able to easily port for example the back-end functionality to other platforms let's say for example you have a particular app which is being distributed via the Microsoft store this app was written using the uwp framework let's say the app is selling really well marketing research tells us that there is a huge demand for this app to run on IOS and Android platforms time is a key factor in keeping the momentum of sales going for this application so we want this app to be appropriated for IOS and Android platforms as soon as possible so that the app can be distributed via Apple's app store for the iOS implementation of the app as well as Google Play for the Android implementation of the app so we know that we can use the xamarin technology to create a cross-platform app for IOS and Android devices so if we have designed our app appropriately using the mvvm design pattern the back end functionality that we have already created would not need to be recreated for the IOS and Android platforms please navigate to this URL for more information on xamarin a team specializing in Android and iOS front-end design could focus on the native front-end functionality for their respective platforms or the use of xamarin forms could also be utilized for the creation of the front-end design using xaml we'll discuss xaml in a bit the backend code already created for the uwp version of the app can be reused for the Android and iOS apps created using the xamarin technology for more information on xamarin forms please navigate to this URL the appropriate use of the mvvm design pattern could make the integration of the front-end functionality with the backend functionality a relatively trivial task the details of mvvm are beyond the scope of this tutorial please navigate to this URL for more detailed information about mvvm model view view model uwp stands for universal windows platform so a uwp application can run on any Windows device that runs Windows 10 or Windows versions greater than version 10. Windows 11 is due to be released on July the 29th 2020. these devices can include PC tablet Xbox hololens surface Hub and Internet of Things devices so we are not going to go into depth regarding the universal windows platform uwp demands an entire course on its own if you want to learn more about universal windows platform please navigate to this URL foreign [Music] but let's look at a very basic example of loosely coupling back-end functionality from front-end functionality using events on the universal windows platform so let's create a Project based on the blank app universal windows project template [Music] thank you let's name this project and solution employee uwp app so once we click the create button we are prompted with a dialog box where we are able to choose the minimum version and Target version that our uwp application will support so to Aid us with our decision let's click on the link labeled which version should I choose which is available in the bottom left hand corner of the relevant dialog box so we are presented with a web page and at the end of the first paragraph on the web page it states projects using.net standard 2.0 must have a minimum version of build 16299 or later so we are going to develop our backend functionality using.net standard 2.0 so let's choose version 16299 from the drop down list labeled minimum version right let's add a standard Library project to our solution and let's name it employee component this Library will contain our back-end functionality so firstly let's reference our employee component project from our uwp project so let's right click the references node within our uwp project and add a reference to the employee component project okay let's delete the class that has automatically been generated let's create a class that will serve as our view model and let's name this class employee view model as the name suggests a view model represents the data that will be displayed to the user let's make this class a public class let's write code so this class implements the I notify property changed interface we must include a directive to the system.component model namespace the I notify property changed interface is a member of the system.component model namespace so to do this we can hover our Mouse pointers over the red squiggly line click show potential fixes and then click using system.componentmodel this interface contains an event that is key to how we can achieve a loose coupling between the backend components and the uwp front-end component that will soon develop so to implement the I notify property changed interface let's hover our Mouse pointers over the I notify property change to text which has a red squiggly line under it and click show potential fixes and then let's click Implement interface note that a public event named property changed which is defined as the delegate type property changed event handler is generated for us this event will be raised to the front end code when a relevant property value in this class has changed this example is going to be simplistic so that we can focus on the Core Concepts of this video namely how events can be used to achieve a loose coupling between front end and back-end components so let's create a read write property named first name and let's create a private member variable named underscore first name let's encapsulate the underscore first name private member variable within the first name property and within the set accessor of the first name property let's include code to raise the property changed event so if the first name property is changed we want to raise the property changed event which will have the effect of notifying the front-end view presented to the user that the relevant field must be changed on the front-end display so that the change in value of the property is presented to the user and this is a key concept to understand when the view model is changed the event notifies the actual view presented to the user of the change and the change is then reflected in the view presented to the user so the view presented to the user is never directly changed for example by referencing an element of the view presented to the user the underlying view model which is part of the back end code is changed and this change is propagated to the view presented to the user through the implementation of the property changed event we'll demonstrate later on how the uwp front-end component subscribes to the property changed event to receive notifications when a relevant property value changes let's wrap the relevant functionality that raises the property changed event and a private method and let's name this method notify property changed notice that this method accepts a string argument which will contain the name of the property that is changed so now within the set accessor of the first name property let's write codes to call the notify property changed private method for when the first name property is changed and let's create auto implemented properties for the other employee fields ID last name annual salary gender and is manager let's create a class named employees we are going to be storing the employee view model objects in a generic collection type called an observable collection the observable collection type represents a dynamic data collection that provides notifications when items get added removed or when the whole list is refreshed for more information about the observable collection class please navigate to this URL so firstly let's include a directive to the system.collections.object model namespace the generic observable collection class is a member of this namespace this class will simply contain a method that returns a collection of employee records let's create a public method named get employees we want this method to return a collection of employee data so the get employees method returns an object of type observable collection the observable collection is a generic collection type and we are able to strongly type the collection with the employee view model type so let's include code within this method that creates a new observable collection object and assign the relevant object reference to a variable named employees let's write code to return the employees object and I have made up some employee data for our employee view model objects that we can add to the observable collection object we have named employees so to save time let's navigate to a GitHub repository where I have already uploaded the code for this tutorial so please navigate to this URL let's select the relevant code that adds the employee data to the employee's observable collection and appropriately paste it into our code editors we could have written code to retrieve this data from a data source like for example a SQL Server database but in the interests of keeping this code sample simple we are using mock data as a substitute the observable collection object represents a dynamic data collection that provides notifications when items get added removed or when the whole list is refreshed we are going to use our observable collection type which is strongly typed to store objects of type employee view model to bind our collection of employee view model objects to a list view that we'll create in our front-end design when we develop the uwp component okay so let's develop our uwp component so the user interface for a uwp application is created using a declarative markup language named xaml which stands for extensible application markup language we are not going to go into the details of xaml in this tutorial but she has a basic explanation of what xaml is in a uwp application xaml is used to define UI elements data bindings events and other features xaml elements map directly to Common Language runtime object instances while xaml attributes map to Common Language runtime properties and events on those objects for more information on xaml please navigate to the following URL so as mentioned earlier I have already uploaded the relevant code sample to GitHub in the interest of time let's copy the relevant xaml from GitHub and then we'll paste the xaml code over the xaml currently in the main page.xaml file right so let's navigate to this URL let's copy all the xaml code from this page to our clipboards foreign let's paste the xaml code in our clipboards over the xaml code currently in our main page.xaml file and if we look at the xaml code here you can see a blue squiggly line under the code where we are binding a list view data template elements to the employee view model type the reason for the blue squiggly line is because we need to compile the employee component so that our uwp project is referencing the relevant latest compiled assembly so let's compile the employee component and the blue Squiggy line goes away great and we can also see a design view rendering of our xaml code if we take another look at the xaml code you can see that the data binding functionality in the first name field includes a mode attribute which is set to the value of one way this is an important part of the functionality that allows changes to the first name property of our employee view model objects to be reflected in the relevant list view displayed to the user so in our code example here we are demonstrating one-way binding from The View model to the list view element of The View let's write the code and the code behind file named Main page.xaml.cs the code we are going to write here will enable the user to select an employee record from the list view that is created through the xaml code which will contain a collection of employee records the user will then be able to dynamically change the first name field for the selected employee record by typing the new first name value into a text box and clicking a button to confirm the change let's create a member variable named underscore employees OC which is of the observable collection generic collection type and is strongly typed with the employee view model type thank you let's create a public Field named change first name command this is a public field and is defined as the xaml UI command type for more information on the xaml UI command type please navigate to this URL let's write the code in the Constructor of the main page class let's create a new object of type employees so let's take a quick look at the xaml code and you can see here we have a list view named employee list and you can see that there is data binding markup to bind the fields in the list view named employee list to each of the fields to find in our employee view model type so let's go back to the main page.xaml.cs class and let's write code to bind the data stored in the underscore employees OC observable collection object to the employee list list View note that the item Source property in the employee list list view is set to the underscore employees OC observable collection so let's go back to the xaml code notice here we have a button named BTN change first name that contains an attribute named command and this code is binding the BTN change first name button to the public Field named change first name command that we defined as the xaml UI command type in the main page class also notice that the command parameter attribute includes code that binds to the employee list list view element so let's go back to the main page.xaml.cs class and let's create a new xaml UI command object for the change first name command public field and let's use the plus equals operator to subscribe to the execute request event on the change first name command xaml UI command object so after we have typed the plus equals operator we can press the Tab Key and a method with the appropriate method signature is generated for us so when the user clicks the button named BTN change first name the code in this method will be invoked so let's write the code for this method firstly let's write code to get a reference to the employee list list view object we can use the args.parameter property to get a reference to this object we must type cost this object to the list view type then let's write code to check if an item in the list view has been selected If an item has not been selected the selected index property will be negative one so if the selected index property is not negative one we can use the relevant list view object selected index property to index the underlying observable collection object and we want to set the relevant items employee first name field to whatever the user types in the relevant text box if we look at the relevant xaml mock-up code we can see that a text box element is included in our markup this text box can be used to rename a selected employee's first name field to whatever the user types in the relevant text box so let's run the code so the employee list view is not populating let's investigate why this is occurring okay so we haven't included the code to assign the relevant observable collection object named underscore employee OC with a value returned by the employees classes get employees method the get employees method populates the observable collection object with objects of the employee view model type and Returns the relevant observable collection object to the calling code so to fix the issue let's write the code to assign the underscore employee OC variable with a value returned by the employees.get employees method let's run the code again great that has resolved the issue we can see that our list view is populated with employee view model data okay so let's select the third record and in the text box here let's type Bob and then press the button that is wired up to our change first name command object and let's repeat the same process for some of the other employee records great we are now able to change the employee records first name field on the front-end display by updating the underlying observable collection note that the code is not updating the employee list listview object directly when the relevant underlying observable collection has changed an event notifies the employee list list view object of this change and the relevant changes are reflected on the front-end display if we look at the change first name command underscore execute request method that gets invoked when the BTN change first name button is clicked we can see that the underlying observable collection object is changed and the employee list object is not directly changed this highlights the decoupling of the uwp front-end component from the employee component which is responsible for data handling and business rules for example when the first name field was changed for the third employee record the property changed event which is a member of the I notify changed property interface was fired signaling to the front end that there has been a change to the first name field and the relevant employee view model object which must be reflected in the relevant list view front-end object and just for fun let's include code to make our application speak to the user so I've already prepared the code that will make our application talk to us in the relevant GitHub repository so let's navigate to this URL let's copy the speak async method to our clipboards and paste it into the main page.xaml.cs file this method includes an asynchronous method called to the synthesized text to stream async method in order to call the speak async method that we have just included within our code we must appropriately include the async and await keywords I'm also going to make a minor change in that I'm going to rename the underscore employee OC variable to underscore employees OC so that the code we have just created is consistent with the code in the relevant GitHub repository let's run the code foreign first name from Bill to Bob changing first name from Jamie to Dom changing first name from Sally to Debbie excellent so to summarize this code that we have just created shows how the I notify changed interface and the generic observable collection can be implemented to Loosely couple the front-end component from the relevant code within the backend component this loose coupling effect has many advantages which can include reuse of components across disparate platforms for example let's say we have an initial application written to run on multiple windows devices through the use of the appropriate uwp project template and then at a later stage we decide that we want this application to run on IOS and Android platforms the component responsible for the implementation of business rules and data handling written using the standard Library project template can be easily ported to run on the Android and iOS platforms without the need to change the relevant code we do not need to rewrite this code for the Android and iOS platforms separation of concerns allows separate teams to work independently from one another for example the front-end xaml experts or as the case may be the Android and iOS front-end developers could focus on the look and feel of the application and the user experience of the application while not having to worry about the details of the business rules and the database handling functionality a separate team that specializes in writing the business rules and database related functionality can focus on this concern without worrying about the implementation detail of the front-end design the front end and back-end functionality can evolve independently from one another and in parallel to one another the front-ended back-end components can then be seamlessly integrated with one another at an appropriate time I hope you have enjoyed this tutorial on events raised through user actions in the context of a uwp application uwp is a very powerful platform that can be used for creating Rich user interfaces that can run on multiple windows devices examples of related Windows specific Frameworks include WPF or Windows presentation foundation and win forms if you want to learn more about WPF please navigate to this URL and if you want to learn more about winforms please navigate to this URL for more content on advanced c-sharp concepts and much more please consider subscribing and please ring the bell so that you'll be notified of new releases from this channel if you feel you've gained value from viewing this video please hit the like button and please feel free to share any of the videos released from this Channel with anyone you feel May benefit from their content as always the code created in this video can be downloaded from GitHub a link to the relevant repository has been included Below in the description thank you and take care [Music] hi and welcome to the fourth part of this tutorial on c-sharp events this video is also part of a tutorial that serves as the fourth part of an advanced c-sharp course in this video we'll focus on the Observer design pattern this is a very powerful design pattern and is suitable for any scenario that requires push-based notifications the implementation of the Observer design pattern entails subscribers registering to receive notifications from a provider push notifications simply means that the notifications are sent pushed from a central point to the relevant subscribers the source of the push notifications is known as the provider also known as the observable observers register with the provider in other words subscribe to the provider and whenever a predefined condition event or state change occurs one of the observer's methods is called by the provider in this method call the provider can also provide current state information to observers so note that the observable can also be referred to as the provider and observers can also be referred to as subscribers so I'll be using these terms interchangeably throughout this tutorial for more content like this on advanced c-sharp concepts and much more please consider subscribing and please ring the bell so that you'll be notified of future releases from this channel in.net the implementation of the Observer design pattern can be achieved when the subscribers class or observers implement the genericsystem.i Observer generic interface and the provider class implements the system.observable generic interface the generic type represented here with the capital T represents the type which can be a user-defined type that encapsulates the notification information communicated from the provider to its subscribers through push notifications so the generic type represented by the capital letter T in the interface definitions of both the provider class and the subscriber classes is key to how loose coupling between provider and subscribers can be facilitated while still enabling rich and extensible data to be pushed from providers to subscribers the system.i observable and system.i observer built-in.net generic interfaces enable this pattern to be reused for multiple scenarios the generic type represented by the capital T allows for users to find types to serve as communication vehicles that can be extended without breaking the design of the relevant application so let's look at a quasi-real world example that can be used to explain the Observer design pattern and give us an idea of when it is appropriate to use this design pattern so we'll have to use our imaginations a bit to Picture This example let's say a particular company owns a building with an automated security system one of the functions of the security system is to identify external visitors arriving at the building for example to have a business meeting with one of the employees that work inside the building so the process first involves the external visitor registering to visit the relevant employee on a particular day let's say that before an external visitor arrives at the building for the relevant visit the external visitor must first register and during the registration process provide a clear photograph of the external visitors face as part of the registration process so when the external visitor arrives on the day of the visit and attempts to enter the building a camera first scans the external visitors face and subsequently sends the relevant pictorial facial information to a system whereby biometric artificial intelligence algorithms are applied to ascertain whether this particular visit can be authenticated I.E has this person registered and if so can this person be verified as the person the person claims to be so this is essentially an automated authentication process once the relevant visitor has been identified the visitors automatically given access to the building this triggers notifications to be sent to the building's security team and any internal staff members I.E employees of the company that owns the relevant building who have subscribed to receive notifications regarding the relevant actions of the external visitors the information that is sent to the subscribers I.E the notification data sent from the provider contains information about the relevant external visitor and the time the relevant external visitor gained access to the building and then subsequently once the visit is completed a notification is sent when the external visitor exits the building another notification will be sent to All subscribers from the provider when a predefined time is reached and all external visitors have exited the building for example the predefined time could be 6 pm which has been deemed the end of the Working Day for the relevant company the rule could be that after this time no external visitors can gain access to the relevant building in this example we'll refer to this time as the cut-off time okay so as I've said we need to use our imaginations of birch here because we are going to implement code for the scenario just described within a consoleapp.net core framework in other words the code will be highly simplified so that we can focus on understanding The Observer design pattern so the provider in this example will be the security surveillance system used to identify external visitors that have registered to visit a member of Staff within the relevant building on a particular day this example will contain two types of subscribers one of the types of subscribers that we will create will represent the security team they must be notified of all significant movements of external visitors for example entering and exiting the building the other type of subscriber will represent any individual internal staff member who has subscribed to receive relevant notifications regarding external visitors this employee would subscribe because a visitor must have a point of contact inside the building in order to successfully register as an external visitor when the external visitor is authenticated on the day of the visit a notification will be sent to the security team as well as any employee who is registered as the point of contact for the relevant external visitor okay let's look at an overview of the main classes that will be created for this example so here is a class that represents the observable this class will represent a central place where surveillance data is processed we'll create two classes that represent two types of Observer the first class represents an employee I.E a person that works inside the relevant building who wants to be notified when a particular external visitor enters the building this class is named employee notify the second class represents the security team who must be notified when any external visitor enters or exits the relevant building this class is named security notify we have a class here named external visitor which represents an outside visitor to the relevant building this class serves as a generic type argument to both the I observable generic interface implemented by the observable class as well as the generic arguments to the I Observer generic interface which is implemented by The Observer classes so this class allows data about the external visitor to be communicated from the observable object to its Observer objects when the relevant notifications are sent we have an eye employee interface and an employee class that implements the I employee interface the employee class provides a way to store details about an employee who works inside the relevant building this class represents the employee details of a person who serves as a point of contact for an external visitor an employee object is passed into the Constructor of the employee notify class during the instantiation of an object derived from the employee notify class so in summary here are our main classes employee notify and observer class security notify and observer class security surveillance hub the observable class I employee and interface defining and internal staff member record employee a class that implements the I employee interface so it represents an employee record external visitor a class representing the person that has registered to visit a member of staff that works inside the relevant building this class represents a person that must be authenticated on the day of the relevant visit let's look at the class that will serve as our observable class we'll name this class security surveillance hub this class represents a central location where surveillance system information is processed and will be responsible for notifying subscribers with the relevant information about an external visitor so notifications will be sent to the relevant observers when an external visitor enters the building and another notification will be sent to the relevant observers when an external visitor exits the building firstly let's answer the question how can we Implement a class so that it can be instantiated as an observable object the answer to that question is that a class that will be instantiated as an observable object must implement the eye observable generic interface the eye observable generic interface is a built-in.net interface that is a member of the system namespace the next question is what makes the observable interface a generic interface the I observable interface is generic because the calling code is able to pass a type as a generic argument to a class that implements the eye observable generic interface in our example the type that will pass as the relevant's generic type argument will be a user-defined type named external visitor as you may have guessed this class will represent an external visitor we'll discuss the external visitor class in more detail a bit later the I observable generic interface contains one method definition this method definition is for a method named subscribe the Subscribe method contains one parameter of a type that implements the I Observer generic interface so this parameter is defined as an observer type we'll discuss the I Observer generic interface a little bit later so the Subscribe method must be implemented by the type that implements the I observable generic interface the implementation of the Subscribe method must contain functionality that is executed when an observer subscribes to receive notifications from the relevant observable object so we've now looked at the essence of what we are trying to achieve here by implementing The Observer design pattern let's get started and create the code example let's create a Project based on the consoleapp.net core project template let's name this project and solution building surveillance system application so for our first class let's create a class that represents the external visitor this class represents the information about an external visitor that will be sent to the relevant subscribers when an external visitor enters the building and subsequently exits the building once the external visitor completes the external visitors visit so let's create a public class and name it external visitor let's create the properties for the external visitor class so let's create a property for ID defined as int first name defined as string last name defined as string company name defined as string job title defined as string entry date time defined as date time this property will store the date and time of when the relevant external visitor entered the building exit date time defined as date time this property will store the date and time of when the relevant external visitor exited the building and lastly an auto-implemented property named employee contact ID and let's define this property as int this property facilitates the storage of the ID of the internal employee I.E an employee who works within the building responsible for being the point of contact for an external visitor on the relevant day of the external visitors visit great and that is our external visitor class so let's create our observable class let's create a public class named security surveillance Hub as explained earlier this class serves as a metaphor for a central location where security related information is processed so for example an external visitor's face is scanned before gaining access to the building and this pictorial information is subsequently sent to the security surveillance Hub where the biometric information and the relevant image is compared against registered image information captured when the external visitor registered to visit the building so if the two pieces of information match the visitor is granted access to the building which will trigger notification information about the external visitor to be sent to the relevant Observers so as discussed earlier in order for this class to represent our observable it must implement the I observable generic interface so let's write the code to do this and let's pass in the external visitor type as our generic type argument what makes the eye observable interface a generic interface it is a generic interface because we are able to strongly type the I observable interface the capital T within less than and greater than symbols in the eye observable interface definition means that we are able to replace the T with our c-sharp type when this is done it means we have strongly typed our generic interface so let's strongly type the I observable interface with our external visitor class like this generics allows us to stipulate a particular type for the relevant type placeholder at compile time note that a capital t is commonly used to represent the generic type placeholder generic functionality can also be accomplished through the use of the.net system.object type as we know all types in c-sharp ultimately inherit from the system.object type so we are able to type cost a variable at runtime to any managed.net type the advantage of using generics for the same purpose is that we can achieve the same functionality but this is done at compile time this provides the advantage of compile time type checks ensuring type safety as well as results in Greater performance for our code because we are able to omit the need for runtime typecasting typecasting which is performed at runtime also carries the risk of incurring runtime errors please don't worry if you didn't understand this brief explanation of why generics is significant generics will be discussed in detail in upcoming tutorials so let's develop the security surveillance Hub class so you can see that there is a red squiggly line under the eye observable text and the class definition this is the c-sharp compiler letting us know that we have not yet implemented code for the member definitions of the I observable generic interface in the security surveillance Hub class so let's hover our Mouse pointers over the red squiggly line click show potential fixes and click Implement interface as you can see there is only one method definition in the I observable interface that we must Implement in the security surveillance Hub class this method is named subscribe notice how the Subscribe method definition contains a parameter of type I Observer and the I Observer parameter type definition is automatically strongly typed with the type definition with which we have already strongly typed the I observable interface so we have strongly typed the I observable interface with the external visitor type and this has propagated to the Subscribe method definition when we automatically generated the method definition that is contained in the I observable generic interface I.E the Subscribe method definition this is a key concept to understand when understanding how we are able to use the I observable and I observe a generic interfaces to implement the Observer design pattern the generic type gives us a means for creating a loose coupling between the observable component and the relevant Observer components the generic type both defined in the I observable and I Observer interfaces allows the developer to strongly type these two interfaces with a common type in this example we are strongly typing these two interfaces with the external visitor user-defined type this will become clearer as we develop this example application right let's implement the code for the security surveillance Hub class so let's create two member variables both of these member variables are of the generic list type let's define the first one and name it underscore external visitors as the name suggests this list will store a list of external visitors when an external visitor gains access to the building the external visitor is added to the underscore external visitors list and you can see that we are strongly typing the underscore external visitors list with the external visitor user defined type let's include a directive to the system.collections.generic namespace the second generic list we need to Define will store a list of observers so this list will contain objects that are derived from the I Observer generic type that is strongly typed with the external visitor user defined type let's name this generic list variable underscore Observers so when an observer subscribes to receive notifications from the observable the relevant Observer is added to the underscore observers list conversely if an observer unsubscribes the relevant Observer is removed from the underscore observers list so the Subscribe method will be the last method that we will Implement as discussed the Subscribe method has to be implemented because it is a member of the I observable generic interface which the security surveillance Hub class implements for now let's create a public method that gets called when an external visitor gains access to the building let's name this method confirm external visitor enters building this method's parameters contains relevant information associated with an external visitor namely ID defined as int first name defined as string last name defined as string company name defined as string job title defined as string entry date time defined as date time and employee contact ID defined as int then we can write the functionality to instantiate an external visitor object and set the properties of the object we have derived from the external visitor user defined type with the values that will be passed as arguments to the confirm external visitor enters building method then let's write the code to add the newly created external visitor object to the underscore external visitors list as mentioned the underscore observers list is populated with observers observers are of course objects that have subscribed to be notified when certain conditions are met for example an external visitor entering the building so this method represents an external visitor entering the building the visitor has been authenticated and is automatically given access to the building so let's use our imaginations and let's say that when an external visitor enters the building the framework in which our observable exists invokes the confirm external visitor enters building method the observable can Now notify all subscribers of this event as well as send the relevant data pertaining to the event to all the relevant subscribers in this particular example the relevant data is encapsulated with the external visitor object which is derived from the external visitor class remember the I Observer generic interface is strongly typed with the external visitor user defined type which makes it easy to send the data to the relevant Observer objects the relevant Observer objects are stored within the underscore observers list so in order to notify the relevant observers with the relevant data we can write code to Traverse the underscore observers list and call each Observer objects on next method note that when we call each Observer objects on next method we are passing the relevant external visitor object as an argument to the on next method this is how each Observer receives notification data whenever the relevant event occurs in this example the relevant event is an external visitor gaining access to the relevant building so how does the observable I.E and object derived from the current class we are creating know that an observer object implements a method named on next and even further to that how does the relevant observable object know that the on next method accepts an argument of type external visitor this is at the heart of how the Observer pattern Works in c-sharp each Observer object is derived from a class that implements the I Observer generic interface if we look at the definition for the I Observer interface we see three method definitions namely on next on error and on completed the on next method contains a parameter of a generic type so when we create an observer class a bit later we'll strongly type the I Observer interface that our class must Implement with the external visitor user defined type this action will mean that the on next method will be strongly typed with the external visitor user-defined type so the external visitor type becomes a common communication facility between the observable and the relevant Observers so the fact that we know that each Observer implements the I Observer generic interface means we know that each Observer object implements a method named on next the fact that the I Observer interface for each Observer class is strongly typed with the external visitor user-defined type means that we know the type of the argument that needs to be passed into the our next method the I Observer generic interface contains a definition for a method named on error this allows for the observable to notify relevant Observer objects if an exception occurs and also provides information about the exception through the built-in exception type we are not going to implement custom functionality for the on error method in this example each Observer object must however Implement code for the on error method because the definition for the method is contained within the I Observer generic interface the last method that we need to talk about is the uncompleted method so we will be implementing custom code for the uncompleted method in this example the uncompleted method does not contain any parameters the uncompleted method notifies The Observers that the observable has finished sending notifications so this method should be called for each Observer when a condition is met whereby no more notifications need to be sent to the relevant Observer objects in this example the uncompleted method will be called on all Observer objects within the underscore observers list when the relevant cutoff time has been reached on a particular day and all external visitors have exited the building the cutoff time could be for example designated as 6 pm there may be external visitors who exceed this time constraint due to for example a meeting that goes on for longer than expected or something of that nature so two conditions need to be met for the uncompleted method to be invoked a certain time in the day is reached for example 6 pm and all external visitors have exited the building so next let's Implement a method that is called when an external visitor exits the building so let's name this method confirm external visitor exits building this method is a public method that contains two parameters one parameter which is a value that serves as a unique identifier for an external visitor it is defined as the int data type the other parameter is named exit date time and as the name suggests this parameter denotes the date and time when an external visitor exits the building so firstly let's write code to find the external visitor within the underscore external visitors list foreign if the external visitor is not now I.E the external visitor is found within the underscore external visitors list let's write code to update the relevant external visitor objects exit date time property to the date and time when the external visitor exited the building let's then write code to Traverse the underscore observers list and call each observers on next method and pass an argument to the on next method of the relevant external visitor object to notify The Observers that a specific external visitor has exited the building so let's create another public method that will be called when the cut-off time is reached so by cut off time I mean this is a time after which external visitors are not allowed to enter the building so we need to use our imaginations for some of these methods because we are basically saying that this method is called when certain conditions are met in this case when a certain time in the day is reached just like for example when the external visitor enters the building the confirm external visitor enters building method is invoked or when the external visitor exits the building the confirm external visitor exits building method is invoked so let's create a public method that will be executed when the visitor cutoff time is reached let's name this method building entry cut off time reached so this method is called at a particular time but we only want to call each observer's on completed method if all external visitors have left the building the fact that the uncompleted method is called means that no further notifications will be sent from the observable object to the Observer objects for a particular day so we are going to use the Link Technology to check if any external visitor objects exist within the underscore external visitors list but first i'm going to extend the external visitor class to include a property named inbuilding this property is of type Boolean and we can set this property according to the external visitors current location so we want to set the inbuilding property value to True when we confirm external visitor enters building method is invoked conversely we want to set the inbuilding property value to false when a confirm external visitor exits building method is invoked so we can now use the inbuilding property value to check if there are still external visitors left inside the building after the cutoff time has been reached if you don't fully understand this code don't worry link will be discussed in detail in upcoming tutorials as part of the c-sharp advanced course if the count of external visitor objects within the underscore external visitors list that have their in-building property values set to True is equal to zero this means that the cut of time has been reached and all external visitors have exited the building so we can now call the uncompleted method on all the Observer objects that are currently in our underscore observers list by calling the uncompleted method on these Observer objects this is notifying the relevant observers that no further notifications will be sent okay let's implement the Subscribe method so notice that the Subscribe method contains a parameter of type I observable which is a generic interface the implementation of the I observable generic interface in this class I.E the security surveillance Hub class is strongly typed with the external visitor user defined type so this is automatically propagated through to the Subscribe method definition where the I Observer generic interface is also strongly typed with the external visitor user defined type note that when an observer object subscribes to the observable object The Observer object passes a reference to itself into the Subscribe method though this keyword can be used for the purpose of referencing an object derived from the class in which that this keyword is implemented we'll implement this code when we create the Observer classes in a bit for now let's implement the code for the Subscribe method and the code for this method is pretty simple we first check if the Observer object exists within the underscore observers collection if the Observer object does not exist within the underscore observers list this means that a new Observer object is subscribing so we can write code here to add the Observer object to the underscore observers list which means that the relevant Observer is now subscribed the subsequent lines of code reverse all the external visitor objects within the underscore external visitors list and notifies the new Observer object of the current information related to external visitors that exist within the underscore external visitors list now notice that the Subscribe method returns a type that must implement the built-in eye disposable interface so we are now going to create a class named unsubscriber and this class will implement the eye disposable interface as the name suggests the purpose of the unsubscriber class is to provide a facility for the Observer objects to unsubscribe to the observable object I.E to elect to no longer receive notifications from the relevant observable object the unsubscriber class implements the built-in I disposable interface which contains a definition for a method named dispose when an observer object calls the dispose method this action causes the relevant Observer object to unsubscribe from the relevant observable object so you can see that the Subscribe method in the observable class in this case the observable class is the class named security surveillance Hub allows for an observer object to subscribe to the relevant observable object the Subscribe method returns a reference to the relevant unsubscriber object which is derived from the class that we are about to create I.E the unsubscriber class that implements the eye disposable interface The Observer object can simply call the dispose method which is a member of the eye disposable interface to unsubscribe to the relevant observable object the built-in eye disposable interface is a member of the system namespace let's create the unsubscriber class as mentioned the unsubscriber class implements the eye disposable interface which contains a method definition for a method named dispose so let's create the class definition for the unsubscriber class let's indicate that we wish to implement the eye disposable interface let's ensure that we are implementing all the members of the I disposable interface the eye disposable interface contains one member a method named dispose let's create the Constructor you can see that this Constructor contains two parameters the first parameter is a list that contains Observer objects the second parameter is an observer object so the functionality for this class is literally just to remove the past in observer object from the relevant observers list so let's create two member variables these member variables will be appropriately assigned to the passed in arguments to the Constructor then the logic within the dispose method is simply to check if the relevant Observer object exists within the relevant observers list if it does remove the relevant Observer object from The Observers list the result of this action is that the relevant Observer is unsubscribed from the relevant observable object and will therefore no longer receive notifications from the observable object so let's go back to the Subscribe method in the security surveillance Hub class and let's return a new unsubscriber object derived from the user-defined type that we have just created note that the construction of the unsubscriber object entails passing a reference to the relevant Observer and a list of all observers currently subscribed okay so we have now written the code for the observable object the class that defines the observable object is the security surveillance Hub class so we can now create the classes that will represent our Observer objects we are going to create two classes which represent two types of Observer objects the first tab we'll create is a class named employee notify this class will represent an employee a staff member that works in the building that has been designated as the contact point for an external visitor so this employee wants to know when the relevant external visitor has entered the building so that the employee can welcome the relevant external visitor at the entrance of the building the second type or class will represent the security team which must receive details of the external visitor when the external visitor enters the building and later exits the building so let's first create code for the employee notify class this class is an observer so it must implement the generic I Observer interface we also need to strongly type the I Observer generic interface with the external visitor type so one way we can automatically generate the definitions for the members of the I Observer interface that we must Implement is to hover our Mouse pointers over the red squiggly line under the I Observer generic interface text within our class definition and click show potential fixes and then click Implement interface and visual studio automatically generates default implementations for three methods the method definitions for these three methods are members of the I Observer generic interface the red squiggly line disappears because we now have implementations for the members contained in the I Observer generic interface so in a bit we'll Implement more useful code for these methods before we create a Constructor for this class I want to create a definition for an employee record let's create an interface named I employee we'll keep the employee record really simple so let's create definitions for just four properties ID as int first name as string last name as string and job title as string let's create a class named employee that implements the I employee interface so let's go back to the employee notify class and create the Constructor for this class so when an object is Created from the employee class we want an employee object to be passed into the Constructor of the employee notify class so let's include a parameter of the I employee type within the Constructor definition we want to adhere to solid principles the last letter in the solid acronym is dependency inversion principle which states that classes should not depend on concrete implementations but should only depend on abstractions this is why the parameter within this Constructor is defined with an interface type rather than a class so we are defining this parameter of type I employee rather than of type employee very basically solid is an acronym representing a set of principles that are design principles that can be followed in order for a programmer to develop software that is easy to maintain and extend we'll discuss solid principles in detail in upcoming tutorials solid principles serve as a foundation for object-oriented design patterns like for example The Observer design pattern these design patterns can be implemented to solve problems that have been repeatedly identified in real world scenarios if you wish to read more about solid principles please navigate to this URL so let's create an appropriate member variable of the I employee type and within our Constructor let's assign the past and value to the member variable we have just created so let's Implement our code Logic for our on next method notice that the parameter contained within this method is of type external visitor when we automatically generated our default method implementations through Visual Studio the fact that we had strongly typed the I Observer interface with the external visitor uses defined type propagated through to the on next method so the purpose of the on next method is that it gets called by the observable object every time it is appropriate to send out notifications to the relevant Observers this is how the observable object is able to send out notifications to each of its subscribed Observer objects because the observable object knows that each Observer object implements the on next method so the observable object traverses all of its observers and calls the on next method on each of its Observer objects to send out the relevant notifications each Observer is able to handle the notification through its custom implementation of logic within its on next method so the code we are about to write gets called when the observable sends out its notifications in this case we want the designated employee contact to receive a notification when the relevant external visitor has gained access to the building so let's write the logic for this method firstly let's assign the past in argument of type external visitor to a local variable named external visitor let's create an if statement the condition for the if statement checks the external visitor objects employee contact ID property value against the ID property value of the employee object reference that is passed into the Constructor of this employee notify object if these two values match this means that the relevant employee is the registered point of contact for the external visitor referred to in this particular notification so we want to maintain an up-to-date local list of external visitors for this employee notify Observer object so let's define a member variable named underscore external visitors as a generic list that can store external visitor objects so let's write code to check if the external visitor object passed into the on next method exists within the underscore external visitors list we can do this by using link and checking if the ID of the external visitor object passed into the on next method matches any of the external visitor objects ID properties currently stored within the underscore external visitors list and we are assigning the result of the link expression to a local variable named external visitor list item so let's write a nested if statement where the if condition checks if the external visitor list item variable value is null if it is null the external visitor object does not exist in our local list containing external visitor objects so let's add this external visitor object to our list then the next line of code simply outputs a message to the relevant employee that the expected external visitor has entered the building and we can also include the external visitors details within the message thank you so if the else part of the nestative statement condition is true the external visitor has already visited and the notification must refer to the relevant external visitor exiting the building so the logic simply updates the inbuilding property of the relevant external visitor object within the underscore external visitors list to false the relevant external visitor list items exit date time property is also appropriately updated with relevant exit date Time Properties stored in the external visitor object passed in from the observable object to the on next method of this object so we have now implemented the logic for the on next method of the employee notify Observer class so in the interests of time we are not going to bother implementing code for the on error method we'll simply retain the default implementation generated by Visual Studio in this example but please note that this method provides a mechanism for observers to handle exceptions that may occur within the observable object so now we must implement the logic for the uncompleted method the purpose of this method is so that the observable object can notify the relevant Observer objects when no further notifications need to be sent in this example there is a rule that the observer's on completed methods will be called from the observable object when a cut-off time is reached for example perhaps 6 pm on a workday and all external visitors must have left the building so a few external visitors may still be in the building past 6 PM for example they may be in meetings that have gone on for longer than was first anticipated the uncompleted method on all relevant Observer objects will only be invoked from the observable object once all external visitors have left the building and the cutoff time has been reached let's say the cut of time means that no further external visitors are allowed to gain entry into the building on a particular work day after a predefined cut off time so if these conditions are met the observable can notify all observers through the observer's implementation of their uncompleted methods and this means that no further notifications will be sent at this point the relevant Observer objects will have a complete list of external visitor objects that visited the building during the course of the day the external visitor objects will contain relevant information like for example certain details about the external visitors as well as their entry and exit times to and from the building on the relevant day so the Observer at this point is able to create a final report relating to the external visitor data on a specific day so let's implement the code for the uncompleted method in the employee notify class let's say that the relevant employee is only interested in the details of those external visitors that were there to visit the employee during the course of that day so in the on next method we have only added the external visitors where the relevant employee was registered as the external visitors contact in the building so we can simply output the details of external visitors stored within the underscore external visitors list for the implementation of the on completed method so let's first write an appropriate heading to the console screen this heading will simply contain the employee name followed by the text daily visitors report let's write code to Traverse the underscore external visitors list let's set the inbuilding property to false because if this method is being invoked this means that all external visitors have left the building and we want to keep our local copy of the underscore external visitors list up to date let's then write the details of each relevant external visitor to the console screen this information serves as a final daily report for a specific employee and contains information about the external visitors that have visited the employee so this is a report and we want to space The Columns for each of the outputted fields evenly one way we can achieve this is by using the pad write method which is available on all string objects the pad write method accepts an integer value as an argument so if for example we wish for the ID field to always occupy six character spaces we can pass an argument of six to the pad write method so if for example the ID value only takes up one character space the pad write method will add the extra five character spaces which will be empty spaces or white spaces to the relevant field output we can actually achieve the same effect when outputting variable values using an interpolated string like this so using the interpolated string Technique we can achieve the same thing and use less code foreign and that is the implementation for the uncompleted method of the employee notify class so we also want to include a method that performs the action of subscribing to the observable in this case as we know the observable is represented by the surveillance system Hub class so let's create a method named subscribe that contains a parameter name to provider which is of the generic interface type I observable and is strongly typed with the external visitor user-defined type and to subscribe we can simply write provider.subscribe and pass a reference to the current object using the this keyword to the observables Subscribe method but remember that the observable subscribe method returns an object that implements the eye disposable interface so let's create a member variable of type I disposable let's name this member variable underscore cancellation so now we can create a method named unsubscribe the logic to unsubscribe The Observer is simply underscore cancellation dot dispose so as mentioned we also want to implement code for another type of Observer class so the class we'll create for this will be named security notify and as the name suggests this class denotes the security team that must receive a notification every time an external visitor enters the building and a notification when the external visitor later exits the building so let's include the I Observer generic interface that is strongly typed with the external visitor user defined type within our security notify class definition let's Auto generate the methods that we must Implement for the I Observer generic interface so let's hover our Mouse pointers over the red squiggly line click show potential fixes and then click Implement interface so the first method we need to implement is the on next method the logic here simply checks if the external visitor object already exists within the underscore external visitors list if it doesn't exist we add the external visitor object passed into the onnext method to the underscore external visitors list we then output notification text that is appropriate for the security related Observer to the console screen foreign visitor does already exist within the underscore external visitors list this means the relevant external visitor has just exited the building so we must update the relevant properties for this external visitor object list item appropriately so we update the inbuilding Boolean property to false and we also update the exit date time property with the date and time when the external visitor exited the building and then let's update the code to Output text to the security team that the relevant external visitor has now exited the building and we have just written the on next method so let's implement the code for the on completed method So within the uncompleted method we simply want to Output the details contained within the underscore external visitors list to the console screen and this serves as a report to the relevant security team conveying information about the entry and exit times of external visitors throughout the day so we can simply copy the implementation for the uncompleted method within the employee notify class to the uncompleted method within the security notify class and then manually change the heading to reflect that this is a daily report for the security team regarding external visitors so let's finish off this class by implementing our subscribe and unsubscribe methods so you may have noticed that we would actually be repeating the code for the Subscribe and unsubscribe methods across our Observer classes namely the employee notify and security notify classes so if we repeat the Subscribe and unsubscribe implementations here we are violating the principle of dry which is an acronym that stands for don't repeat yourself yeah we would be clearly repeating ourselves so let's refactor our code so that the Subscribe and unsubscribe methods are reusable across our Observer classes and are written in only one place to centralize the functionality for these methods let's create an abstract class named Observer let's make the Observer class implement the I Observer generic interface let's strongly type the interface with the external visitor class so the rule here is that we must implement the members of the I Observer generic interface in this case however we don't want to centralize the functionality for the on next on error and on completed methods defined in the I Observer generic interface we have different implementations for the on next and on completed methods for our two different Observer classes so what we can do is we can create abstract method definitions for the relevant methods within our Observer class we can consolidate two member variables within this abstract class I.E the underscore cancellation member variable and the underscore external visitors member variable the underscore cancellation member variable is of the I disposable type and is used for unsubscribing and observer object the underscore external visitors variable is of type generic list and is strongly typed with the external visitor type the underscore visitors list maintains a central local storage facility for the relevant Observer object of external visitor information we can then centralize the functionality for the Subscribe and unsubscribe methods so that these methods can be reused across both Observer classes as you may have guessed The Observer classes will inherit from this abstract class so we can now change the class definitions for our Observer classes namely the employee notify class and the security notify class to inherit from The Observer abstract class we then need to include the override keyword within the on next on error and on completed methods within our employee notify and our security notify classes which are of course classes that represent our Observers this is because we are no longer implementing the I Observer generic interface directly we need to override the abstract method definitions for these methods that have been defined in the Observer abstract class so before we Implement code in our main method and run the code let's create a basic class that will help us differentiate between the text that will be outputted by our two Observer classes namely the employee notify class and the security notify class so the obvious way that we can do this is by changing the color of the outputted text for each of these Observer classes so let's create a static class let's create a public enum and name it text output theme each list item value in this enum denotes an output theme so let's name the first enum list item security let's name the second enum list item employee let's name the third enormous item normal let's add a method to the static class let's name this method change output theme this method contains one parameter named text output theme and is defined as the enum we have just created I.E the enum named text output theme then the logic for the change output C method simply evaluates through an if else if block the value passed into this method so if the value passed into the change output theme method is the employee enormous item value let's write code to change the background color to dark magenta and the color of the text to White else if the value passed into the change output theme method is the security e number list item value let's change the background color to dark blue and the color of the text to Yellow else let's reset the state of the text color and the background color back to their default colors so let's go to the security notify class and we can now change the color theme for the output text colors in the on next method accordingly and once the relevant text has been outputted let's change the foregrounded background colors back to their default values and we can do this using our change output theme method like this let's go to the employee notify class and implement the same functionality but of course change the color theme to the appropriate color theme we have defined for the employee notify output text so now when we test our code we will be able to differentiate between the output coming from an object derived from the employee notify class and the output coming from an object derived from the security notify class okay so let's write some code in the main method to test our implementation of the Observer design pattern we have implemented code here for the purpose of understanding The Observer design pattern and to keep things simple and focused on the Observer design pattern itself we have used the consoleapp.net core project template to create the infrastructure or framework to house our code logic so before we write calling code in the main method to test our Observer design pattern it may be helpful to use our imaginations to picture a real world representation of this example so in the real world we would have three types of entities we have our two types of observers namely an employee who works within the building and the building's security team so the relevant Observer employees I.E the employees who have subscribed to receive notifications when an external visitor enters or exits the building may have apps running on a handheld device like tablets or smartphones that alert the employees when relevant external visitors enter or exit the building the security team may have various Personnel whose responsibility it is to monitor the entry and exit of external visitors so the relevant security Personnel may be notified through security related software where one of its components is subscribed to receive notifications when an external visitor enters or exits the building so the relevant security officer or officers may be sitting at a laptop or desktop monitoring the relevant notifications then we have the observable entity which could be a server that resides on-premises or in the cloud that is constantly receiving surveillance information from security cameras it provides facial recognition functionality and assesses whether a registered external visitor can be authenticated and therefore enter the building so in summary The Observers I.E employees within the building and a security team are subscribed to the observable and receive notifications from the observable once a certain condition is met in this case the condition is an authenticated external visitor entering or exiting the building with all this in mind let's Implement a few scenarios within our main method to test our implementation of the Observer design pattern so let's create an instance of our observable class let's create an instance of the Observer class named employee notify and pass an employee object as an argument to the employee Notifier Constructor so we can imagine that Bob Jones is carrying a handheld device that receives a notification when an external visitor that has registered Bob Jones as the external visitors point of contact arrives let's create another instance of the Observer class employee notify and pass a new employee object as an argument to the employee notify Constructor so it's essentially the same scenario as before but this time we can imagine that Dave Kendall is carrying a handheld device that receives a notification when an external visitor arrives that has registered Dave Kendall as the external visitors point of contact and these employees will also receive notifications once the relevant external visitor exits the building although they don't receive text output when the relevant external visitor exits the building the notification is received and the relevant employee notify external visitors object list containing the relevant external visitor object is updated with relevant information for example the time the relevant external visitor exited the building this information is relevant when the employee receives a report regarding external visitors when the relevant cutoff time is reached and all external visitors have exited the building and let's create the other type of Observer object which is represented by the security notify class this type represents a security team that must receive notifications whenever an external visitor enters the building and later exits the building all observers will also receive a report once a cut-off time is reached and all external visitors have left the building remember the cut-off time denotes a time after which no further external visitors are allowed to enter the building so for example this cutoff time could be 6 PM which could be deemed as the end of the Working Day for the relevant company so now we have three Observer objects which is comprised of two employees and the security team and we have a provider which can also be called the observable object which is the central location where security related data is processed so let's subscribe all of our Observer objects to receive notifications from the observable object so when we call the Subscribe method we must also pass a reference to the observable object so we can call the confirm external visitor enters building method to simulate an external visitor entering the building the arguments that we are passing to this method denote information about the external visitor the time the external visitor enters the building as well as the ID of the employee that serves as the contact point for the external visitor so let's call the confirm external visitor enters building method to simulate the entry of an external visitor named Andrew Jackson and then an external visitor named Jane Davidson note that the last argument passed into the confirm external visitor enters building method denotes the ID of the employee whom the external visitors have registered as their point of contact so the point of contact for Andrew Jackson is Bob Jones and the point of contact for Jane Davidson is Dave Kendall let's then call a method to simulate these two external visitors exiting the building we can do this by calling the confirm external visitor exits building method on the observable object once where the ID pertaining to the external visitor Andrew Jackson is passed into the method we can then call the method again but this time passing the ID of the external visitor Jane Davidson signifying that Jane Davidson has exited the building these two method calls to the confirm external visitor exits building method simulate these two external visitors exiting the building so let's say that Andrew Jackson exited the building two hours after entering the building and let's say that Jane Davidson exited the building three hours after entering the building lastly let's call the building entry cutoff time reached method on the observable object which denotes that the end of the working day has been reached we have referred to this term as the cutoff time throughout this tutorial if all external visitors have exited the building a report of external visitors is sent out to all the subscribed Observer objects on a technical level this is achieved through the observable object calling the uncompleted method on all relevant Observer objects we have structured the code in the main method so that all external visitors have left the building before the cutoff time so a full report should be sent to All Observers and this also means that no further notifications will be sent for that particular day so let's run the code okay so an error is flagged because the underscore observers variable is null and we have tried to call its contains method so I've realized I forgot to include a Constructor for the security surveillance Hub class where we should have instantiated an appropriate generic list object and assigned it to the underscore observer's member variable as well as instantiate an appropriate generic list object and assign it to the underscore external visitors variable so let's fix this issue and implement the appropriate Constructor code for the security surveillance Hub class okay let's try again let's run the code great and if we look at our output we can see that this is an expected result Bob Jones an employee is notified when Andrew Jackson an external visitor enters the building Dave Kendall an employee is notified when Jane Davidson an external visitor enters the building the security team is notified when both external visitors have entered and exited the building when the cutoff time is reached an appropriate report is sent to the employee Observer objects as well as the security Observer object the employee report contains information regarding external visitors where the employee served as the relevant external visitors point of contact the security Observer object is notified of the relevant activities and relevant details of all external visitors for the relevant day through a report tailored for the security team great so our Observer design pattern has been implemented correctly and is therefore working as expected though I've noticed that the date time output is not in the format I would prefer I want to include whether the time is AM or PM so we can do this by including TT within the date time formatting string passed to the relevant tostring methods this is not ideal because notice that we are having to change this format in several places in a professionally developed application it would be good practice to configure this format in one place for the purposes of this demonstration we'll update the date time string formatting in several places but let's be cognizant that this is not the best way to implement this formatting functionality let's run the code again great so let's simulate the scenario where the cut of time is reached so no further external visitors are allowed to enter the building past the cutoff time but there are still external visitors in the building so we can simulate this scenario by commenting out the line of code that simulates the external visitor Jane Davidson exiting the building so in this particular case Jane Davidson has not yet exited the building let's run the code and the output reflects this we see the correct output pertaining to the entry and exit of Andrew Jackson but we only see an output for Jane Davidson entering the building and not exiting the building this is an expected result note that we also do not see any of the reports outputted to The Observers because these reports are only sent when the cutoff time is reached and all external visitors have exited the building the code implementation for this is implemented in the building entry cut of time reached method contained within the observable class I.E the security surveillance Hub class in the building entry cut of time reached method the uncompleted methods of all relevant Observer objects is called but only if all external visitors have left the building and if we include the method called to the confirm external visitor exits building method for Jane Davidson but call the unsubscribe method on the employee notify object after this external visitor has entered the building but before the building entry cutoff time reached method is called so let's appropriately call the unsubscribe method on the Observer object pertaining to the employee Bob Jones let's run the code and you can see that Bob receives a notification when his external visitor enters the building but a report is not sent to Bob Jones when cutoff time is reached because he has unsubscribed before cutoff time is reached this is because if an observer unsubscribes The Observer will not receive any further notifications after the Observer has unsubscribed on a technical level when the Observer unsubscribes the code removes The Observer from the observer's list contained within the observable object and therefore that Observer is excluded from the list of observers that has traversed and sent notifications when certain predefined conditions are met I hope you have enjoyed this video on the Observer design pattern this completes the final video in a video series on c-sharp events and completes the fourth part of a course on Advanced C sharp so in this video series we looked at the basics of events in C sharp we demonstrated how we are able to subscribe to an event contained within another class and how we can designate a method to handle the event event handling code and c-sharp is implemented by using a delegate as an intermediary between the event and designated method that is called when the relevant event is raised we demonstrated the use of racing events through codelogic I.E when certain logical conditions are met in a class where the relevant event resides the event can be raised in order to invoke the methods that have been designated to handle the relevant event we demonstrated how we're not calling clients subscribes or unsubscribes to an event that this functionality can be encapsulated with an add and remove accesses which are similar in nature to the use of get and set accesses for properties we demonstrated how events can be raised through user actions for example a button click we use the uwp universal windows platform project framework as a foundation for this demonstration we briefly touched on how the mvvm model view view model design pattern is used to Loosely couple front-end functionality from business rules related functionality when implementing code for a uwp project in this regard we also discussed the advantages of separating concerns for example to allow for cleaner code to facilitate easier unit testing to facilitate better maintainability of code and to allow for separate teams to specialize in different aspects of a project so relevant aspects of the project can evolve independently and without adversely affecting one another lastly in this video we demonstrated an example where the implementation of the Observer design pattern was deemed as suitable because its core functionality involves pushing notifications out to multiple entities from a central point when certain conditions are met please consider subscribing for more content on advanced c-sharp concepts like this and much more and please ring the bell so that you can be notified when this channel releases new videos if you feel you've gained value from viewing this video please hit the like button it will be greatly appreciated please feel free to share any of the videos released from this Channel with anyone you feel May benefit from their content and please feel free to provide feedback about this video in the comments section as always the code can be downloaded from GitHub a link to the relevant GitHub repository has been included Below in the description [Music] hi and welcome to the first part of a tutorial on c-sharp generics tutorial is also the fifth part of a course on Advanced c-sharp topics this video will serve as a basic introduction to generics and c-sharp we'll first answer the question what is meant by generics we'll look at a basic example of implementing generics in c-sharp and the advantages associated with the use of generics and c-sharp so let's start with the question what is meant by generics in relation to the c-sharp programming language generics was introduced in c-sharp version 2 and enables developers to use type parameters and code this makes it possible to design classes and methods that defer the specification of one or more types until the classroom method is declared and instantiated by client code for example by using a generic type parameter T you can write a single class that other client code can use without incurring the cost or risk of runtime costs or boxing operations we'll discuss what is meant by boxing operations and runtime casting a bit later in this video generic classes and methods combine reusability type safety and efficiency in a way that their non-generic counterparts cannot generics are most frequently used with Collections and the methods that operate on them for more content like this on advanced c-sharp concepts and much more please consider subscribing and please ring the bell so that you'll be notified of future content released from this channel let's look at a simplistic example to help us understand generics and C sharp to help us understand generics as a whole we're going to look at a c-sharp collection type the arraylist versus a c-sharp generic collection type a generic list an arraylist provides the advantage of encapsulating the functionality of dynamically increasing the size of the list as more items are added to the arraylist in other words unlike with an array we do not have to Define an arraylist with a size it will dynamically handle its size as items are added to the arraylist the arraylist stores values as objects this involves implicitly boxing value type items when they are added to the arraylist unboxing these items is required when these items are retrieved from the arraylist we'll discuss boxing and unboxing in a bit so we are only using an arraylist in this example to highlight the benefits that replacing an arraylist with a generic list provides in doing so we can understand the overall benefits provided through the use of generics note that Microsoft has stated that Microsoft does not recommend using the arraylist for future development so we'll first use the arraylist collection in our example and later replace the arraylist collection with a generic list to highlight the benefits of generics let's create a console app.net core project I'm going to name my project generics basics let's create a class named salaries let's define a member variable as an arraylist the arraylist type is a member of the system.collections namespace so let's ensure that we include a directive to the system.collections namespace at the top of our code and let's create a Constructor within the Constructor let's populate our arraylist with data that denotes salaries let's create a public method named get salaries that simply Returns the arraylist that has been populated with the salary data so this method returns an object of the arraylist type to the client code so the code within our main method is our calling client code the code share will create an instance of the salaries class and then call the get salaries method and assign The Returned collection from the get salaries method to a local arraylist variable so let's write the code in the main method to do this let's say there is a requirement to add a bonus of two percent to the second item within the collection so let's write code to achieve this we know that the salaries collection contains floating Point numbers so let's assume that we can assign a member of the collection to a local variable defined as float so let's write the code for this okay great so this is good we have a red squiggly line under the code where we are assigning the second item of the relevant arraylist to a variable we have defined as float so a type in compatibility has been flagged by the c-sharp compiler if we hover our Mouse pointers over the red squiggly line we can see a message from the c-sharp compiler which is telling us that we cannot implicitly cast an object to a float but that an explicit conversion exists so let's write code to explicitly convert the relevant object value stored in the relevant arraylist to the float data tab like this great and the red squiggly line goes away and all seems well then we can finish off The Code by writing code to write the salary which now includes a bonus of two percent to the console screen let's run the code oh what is happening here we have received a runtime error specifically an invalid cost exception the exception message States unable to cast object of type system.double to system.single remember float is an alias for system.single so note that when we added the salaries to the arraylist within the Constructor of the salaries class we simply added literal values that our floating Point values we did not explicitly Express the type of the relevant literal values the type of floating Point literals are by default interpreted as the double date type we could have expressed the types for these literal values as float data types by adding an F after the relevant literal value like this but we did not do this so in the main method or in our client code we assumed that a value within the arraylist was of the float data type and this assumption resulted in a runtime error occurring in a bit we'll talk about how generics preemptively prevents such erroneous assumptions from causing runtime errors let's first discuss boxing and unboxing okay so an arraylist stores values that are automatically typed as the root c-sharp data type which is the system.object data type note that all.net data types ultimately inherit from the system.object data type when a value type in our case a numeric floating point value type is stored within an arraylist the value type is wrapped within an object type and stored in memory on the Heap this process is known as boxing what does boxing mean boxing is the process of converting a value type to the type object or to any interface type implemented by this value type so when the common language runtime boxes the value type it wraps the value inside a system.object instance and stores it on the managed Heap for more information on data types in c-sharp please access a video created by this channel by clicking on a card made available in the top right hand corner of your screen a link to this video has also been included Below in the description so when a value is retrieved from the arraylist as we are doing in the main method the value must first be unboxed unboxing extracts the value type from the object boxing is implicit unboxing is explicit the concept of boxing and unboxing underlies the c-sharp unified view of the type system in which a value of any type can be treated as an object so this highlights two disadvantages of using an arraylist where a generic list can be used instead and can be implemented whereby the values contained within the generic list can be strongly typed through generics at compile time firstly as we have proven writing code in this way can result in runtime errors because the values in an arraylist are not strongly typed at compile time secondly when a value type is stored within an arraylist the value type is automatically boxed and when a value type is retrieved from the arraylist the value must be explicitly unboxed this is done through explicit type casting this boxing and unboxing functionality carries with it a performance overhead boxing and unboxing can affect the performance of our applications using a generic list to strongly type the values stored within the relevant generic list has two distinct advantages one type safety the code is type checked at compile time which preempts runtime errors this makes typecasting at runtime not necessary which eliminates the potential for type-related runtime errors occurring number two enhanced performance unlike with an arraylist the overhead of boxing is not necessary when adding a value to a strongly typed generic list and the overhead of unboxing is not necessary when retrieving a value from the strongly typed generic list like an arraylist the generic list carries the advantage of being able to grow dynamically I.E it is not necessary to define the size of the collection when it is declared so with all that said let's Implement generics in our code to implement generics let's replace the arraylist within our salaries class with a strongly typed generic list the generic list is part of the system.collections.genericnamespace so let's ensure that we have a directive to this namespace at the top of our code thank you let's hover our Mouse pointers over the list type in our code so notice the T with an angle brackets this T serves as a placeholder for a data type the developer is able to pass a data type as an argument to the generic list in order to declare that only the type passed into the T parameter must be stored within the relevant generic list so we have passed in the float data type to our generic list notice how there is a red squiggly line under each of the floating Point values we are attempting to add to our strongly typed generic list the c-sharp compiler is insisting that we express these floating Point values as the float data type and we know we can do this by adding an F to the end of each of these values like this through the use of generics the c-sharp compiler checks our code at compile time which prevents the possibility of type related runtime errors so we are simply commenting out the code where we previously used the arraylist and in its place applying the relevant generic list code our list is now strongly typed with the float data type which means that our list can only store value types that are of the float data type this is the basics of generics let's run the code great I hope you have enjoyed this video which serves as an introduction to generics and C sharp in the second video we'll go further into generics and introduce Associated Concepts like for example constraints for more videos on advanced c-sharp concepts and much more please consider subscribing and please ring the bell so that you'll be notified of future content released from this channel if you feel you've gained value from viewing this video please hit the like button it'll be greatly appreciated please feel free to share any of the videos released from this Channel with anyone you feel May benefit from their content your comments are of course welcome the code created in this tutorial can be downloaded from GitHub please see a link to the relevant repository Below in the description [Music] hi and welcome this video is the second part of a video series on c-sharp generics this video is also the second part of the fifth tutorial in a course on Advanced c-sharp topics so in this video we'll create a class to encapsulate the bubble sort algorithm cost will be a generic class that can be implemented to sort an array that contains values of any managed c-sharp data type this will include user-defined types so in order to enable sorting user-defined types the relevant user-defined type must implement the eye comparable interface the generic class that will implement the bubble sort algorithm will contain a constraint as part of its class definition we'll discuss the significance of using constraints in the context of generics and c-sharp and we'll demonstrate the use of a constraint through the code example for more videos on advanced c-sharp concepts and much more please consider subscribing and please ring the bell so that you'll be notified of future content released from this channel firstly to highlight the advantage of using generics and c-sharp I'm going to implement the functionality for this example in a non-generic way we'll then modify the code to implement generics to create the equivalent functionality so let's get started let's create a.net core console application and let's name this project generic bubble sort application I'm not going to explain the details of the bubble sort algorithm in this tutorial there are many available online tutorials regarding the bubble sort algorithm if you'd like me to explain the details of the bubble sort algorithm please let me know in the comments section and I'll be happy to make a video on the details of how the bubble sort algorithm works very basically the bubble sort algorithm is a simple sorting algorithm that repeatedly steps through a collection of values Compares adjacent elements and swaps them if they are in the wrong order our implementation of the bubble sort algorithm will work for any array of any c-sharp value type string data type as well as any user-defined type that implements the eye comparable interface so let's create a class that encapsulates a method containing the bubble sort algorithm let's first create this class as a non-generic class so that we can later turn this class into a generic class and in doing so highlight the benefits of using generics in our c-sharp code so let's create a public class named sort array let's create a public method within the sort array class named bubble sort this method does not return a value and contains a parameter which is an array defined as the system.object type remember we are first implementing our code in a non-generic way we want to be able to sort an array of any built-in value type string type and even user-defined types we are using the object dates tab rather than generics to enable sorting arrays of varying data types we are able to achieve this because all managed data types in c-sharp ultimately inherit from the system.object data type for Value types boxing functionality can be applied to store value type values inside an object reference type for more information on boxing and unboxing please click the card in the top right hand corner of your screen to watch the first part of this tutorial on c-sharp generics a link to this video has also been included Below in the description so let's write the code for the bubble sort method firstly let's set a local variable of the integer dates type to the length of the array that will be sorted by our bubble sort code this is the array that will be passed into this method at runtime we are now going to create two for Loops an outer loop and an inner loop let's create the outer loop first so this Loop simply traverses all the elements of the array that will be passed into this method at runtime for every traversal of the outer loop the inner loop traverses all the elements of the array minus the current value of the outer Loops incremented value in this case an integer value stored and a local variable named I and of course we know that the minus one and both the outer and inner Loops is there because arrays and C sharp are zero based so now within the inner loop we can write the code that compares the current elements value I.E the value currently being traversed with the value of the adjacent element in the relevant array so we can get the adjacent element by adding 1 to the value stored in the J variable which is being incremented by the inner for Loop statement so notice the red squiggly line when we try to perform our comparison code using the greater than symbol this is because the object type does not support the use of this operator for comparing one object value to another so value types like for example intload long Etc and the string dates type implement the eye comparable interface so we should be able to use the compare to method to perform the comparison functionality we need for our bubble sort algorithm the compare two method definition is a member of the I comparable interface the system.object type does not implement the eye comparable interface so we need to perform a runtime casting operation in order to use the compare to Method this highlights the danger of using the object data type and code like this because we are assuming that the elements of the array passed into this method at runtime will implement the eye comparable interface so this code runs the risk of causing a runtime error and at the very least carries the performance overhead and could when the costing operation is performed at runtime so we can perform the casting operation like this the way that comparet2 method works is that the current value is compared to another value and if the current value is greater in value than the other value an integer value greater than zero is returned to the calling code if the values are equal an integer value of 0 is returned from the compare to method to the calling code if the current value is less than the other value that it is being compared to the compared to Method returns an integer value less than zero to the calling code so with regards to the bubble sort algorithm if the compare to Method returns a value greater than zero this means that the current value is greater than the value it is being compared to and the two elements need to be swapped in terms of their positions in the array so let's write the code for this let's set a variable named temp to the value of the current item being traversed let's then set the value for the current item in the array to the value of the adjacent item in the array I.E the value that the current item is being compared to then let's set the adjacent items value in the array to the current items value in the array I.E the value that is stored in the temp variable so in effect we have simply swapped the positions of two adjacent values in the relevant array so in the interests of cleaner code let's encapsulate the swapping functionality and a private method named swap and that's it we have implemented our bubble sort algorithm so let's go to the main method and write code to test our sort array class let's create an array of integer values where the values are stored in no particular order let's write code to instantiate an object of the sort array type let's write code to invoke the bubble sort method and pass in the relevant array that we want sorted okay there's a red squiggly line under the past in Array argument to the bubble sort method in our code this is because we need to change our definition of the relevant integer array to an object array let's write the code to write the values stored in the relevant array to the console screen let's run the code great and we can see that the values have been appropriately sorted Let's test our bubble sort functionality for an array of strings let's run the code great and let's now test our bubble sort code for an array of a particular user-defined type let's create our user-defined type so let's create a class named employee this will be the user-defined type that we'll use for this example where our bubble sort code sorts an array of a particular user-defined type let's keep this class simple and give it two Auto implemented properties ID as int name as string let's go to the main method and create an array of employee objects I'm going to add made up data for each employee object and these employee objects are deliberately unordered foreign let's run the code and we are getting a runtime error this is because our bubble sort code relies on the compare to method to compare the relevant values in the relevant array this means that the object stored within the relevant array must implement the eye comparable interface this highlights one of the reasons why our code should Implement generics we'll implement the generic version of this code in a bit for now to fix the runtime error let's make the employee class implement the icomparable interface let's hover our Mouse pointers over the red squiggly line under eye comparable click show potential fixes then let's click Implement interface we can now see that Visual Studio has created a method named compare to so we must Implement code here that compares the current object's ID with the ID of the object passed into the compare to method so to get the current object we can simply use the this keyword the object that will compare our current object to is the object that will be passed into the parameter named object which is a parameter contained within the compare to method as you can see the relevant parameter named object is of type object so we need to type cost this object to employee notice that we need to perform a lot of runtime casting to make this code work this is not a good thing and we'll solve this problem in a bit using generics so we are going to sort the employee objects in the relevant array by their ID properties the ID property is of type integer integers and c-sharp implement the compare to Method so we can simply write code to return the result of the compare to method to the calling code like this so this code simply compares the ID of one employee object with the ID of another employee object and returns an appropriate value to the calling code as stated earlier a value greater than zero if the current employee object's ID is greater then the other employee object's ID 0 if they are equal in value and a value less than zero if the current employee object's ID is less then the employee object ID that the current employee object's ID is being compared to the string data type also implements the eye comparable interface so we could replace this code with similar code that compares the current employee object's name property with the other employee object's name property we'll test this a bit later I'm also going to override the tostring method in the employee class so that we can display the employee objects ID property followed by the employee object's name property when an employee item's values are written to the console screen so when we write an employee item to the console screen both the ID and the name properties of the relevant employee objects will be outputted to the screen so let's run the code okay so this is not the result we expected in order for our override of the tostring method to be executed we need to type cast the item we are writing to the screen to the employee type note the need for more bad type cost and code let's try again and now our code works as expected you can see that the employee objects within the array have been ordered by their ID properties as expected great so the sort array class now works for multiple data types we have achieved this functionality by using the system.object type this is because all managed data types in c-sharp ultimately inherit from the system.object type for more information on c-sharp data types please click the card made available in the top right hand corner of your screen to view a video on c-sharp data types so let's see how we can achieve the same functionality but through the use of generics we'll also see why it is more advantageous to use generics to avoid the performance penalties incurred by using the system.object type to achieve the desired functionality so through our use of generics we can also eliminate the risk of data type related runtime errors so let's change our sort array class into a generic class we can do this by adding a placeholder represented by a capital T with an angle brackets after the sort array class name and our class definition let's then replace all of our object type definitions with the placeholder data type represented by the capital T in our code in the main method we must add angle brackets after the sort array type when we instantiate an object of type sort array like this within the angle brackets we must include the relevant data type to strongly type the class in this case we are testing sorting an array of employee objects so we must include the employee data type within angle brackets we can now remove the costing operation from the code that writes the employee data to the console screen let's run the code great we are using generics now so let's remove the typecasting functionality where we are casting type object to type I comparable in the bubble sort method foreign squiggly line under the compare to Method call within the bubble sort method the red squiggly line is a result of the fact that we have not told the c-sharp compiler that type T implements the eye comparable interface which contains the compare to method so you'll notice when we add a DOT after an item referenced in our array the compare to method is not available in the intellisense drop-down list this is because visual studio and the c-sharp compiler has no way of knowing that type T implements the eye comparable interface so how can we declare that type T implements the eye comparable interface we can do this through the implementation of a constraint by adding a constraint we are constraining our T-Type parameter to a rule that any type passed as an argument to the T parameter must implement the I comparable interface so to add the desired constraint we can add the following code to our sort array class definition where space t colon I comparable so we have now implemented the desired constraint for our generic sort array class and the red squiggly line goes away and now if we add a DOT after our item referenced in the relevant array we can see the compare to method which is a member of the icon Parable interface and our intellisense drop down list so let's go to the main method let's first test our new generic version of the sort array class that now contains a constraint with an array of integers now that we are using generics to implement the sort array class we can use the int type to declare our array of integers rather than the object type so notice how we are passing in the end dates type between the angle brackets for the code that instantiates the sort array class we are now able to strongly type our sort array class Let's test the code great Let's test our string array so this time we must include the string data type within angle brackets when we instantiate the sort array class great and then let's test our code with our array containing values of the user-defined type employee but before we do this you'll notice that we currently need to perform a conversion operation within the compare to method of the employee class to convert the obj argument which is defined as object to an employee type we don't want this extra overhead caused by the costing operation at runtime so to solve this problem we can implement the generic version of the icomparable interface we can pass the employee data type as an argument to the generic version of the eye comparable interface like this so let's modify our code so that we are implementing the compare to Method contained within the generic version of the icomparable interface to do this let's first comment out our current compare to method let's then hover our Mouse pointers over the red squiggly line in our class definition click show potential fixes and then click Implement interface you'll notice that the new version of the compare to Method generated by Visual Studio contains a parameter that is strongly typed with the employee user-defined type so let's copy our old implementation of the compare to method and paste it into our new version of the compare to method we can now remove the casting operation from our new strongly typed version of the compare to method so now there is a red squiggly line under the employee type being passed as a data type argument to the sort array class in our main method this is because in our sort array class definition we have a constraint which enforces a rule at compile time that any type passed into the sort array class must implement the eye comparable interface our employee class is now implementing the generic version of the eye comparable interface so we need to modify our constraint and our sort array class definition to establish a rule that any data type passed to the relevant T data type parameter must implement the generic version of the icomparable interface so our constraint now pertains to any type that implements the generic I comparable interface following this modification our code will still work for the integer data type which is a value type and the string dates tab because both the int data type and the string data type implement the generic version of the eye comparable interface our sort array class will also work for any user's defined type like our employee type that appropriately implements the generic version of the eye comparable interface Let's test our code great so let's say we want to sort our employee objects by name to achieve this we can simply change the implementation of the compare to Method within the employee class like this Let's test the code great let's also test the code for an integer array foreign let's firstly select the int dates type in our code right click on it and then select go to definition you can see the in-states type implements the non-generic version of the eye comparable interface and also implements the generic version of the eye comparable interface let's run the code great let's also test the code for a string array great so we have written a generic class that can sort an array of any built-in value type string data type as well as any user-defined type that appropriately implements the eye comparable generic interface by using generics we eliminated the need for a lot of type conversion operations which would be performed at runtime and carries the risk of incurring runtime errors using generics can also enhance the performance of your application because the.net runtime no longer has the overhead of Performing these casting operations at runtime generics allows us to defer type specifications for a unit of code this allows us to strongly type a unit of code for example a class method or collection type at compile time this means generics inherently has the advantage of compile time data checks to prevent the possibility of type-related runtime errors occurring we use the constraint to indicate to the compiler that the generic type parameter represented by the capital T between angle brackets in our class definition must implement the generic I comparable interface this allowed Visual Studio to make available the compare to method on an object defined as T through intellisense and ensured that the compare to method is available on all relevant elements within the relevant array which are of type T at runtime so generics and the use of a constraint has been implemented so that we can Implement one pattern of logic in this case the bubble sort algorithm for any c-sharp built-in value type EG int long float double Etc the string dates type as well as any user-defined type that appropriately implements the generic I comparable interface I hope you've enjoyed this video on using generics with constraints in C sharp in the next video we'll delve deeper into generics for more videos on advanced c-sharp concepts and much more please consider subscribing and please ring the bell so that you'll be notified of future content released from this channel if you feel you've gained value from viewing this video please hit the like button it will be greatly appreciated please feel free to share any of the videos released from this Channel with anyone you feel May benefit from their content your comments are of course welcome the code created for this tutorial can be downloaded from GitHub please see a link to the relevant repository Below in the description [Music] hi and welcome this video is the third part of a video series on c-sharp generics this video is also part of a tutorial which is the fifth part of a course on advanced c-sharp concepts in this video we'll look at generic delegates and events in c-sharp we'll also look at other Concepts associated with c-sharp generics including the use of a generic c-sharp built-in data structure namely the queue data structure we'll explore these Concepts associated with generics through a practical example the theme I've chosen for this practical example is a warehouse management system for more videos on advanced c-sharp concepts and much more please consider subscribing and please ring the bell so that you'll be notified of future content released from this channel we need to use our imaginations a bit because the example will be highly simplified and expressed through a.net core console application so the code will provide the functionality of a real-time monitoring system for items entering a warehouse and subsequently being processed by processed I mean the item is placed in a predefined location within the warehouse for storage so an event is raised when an item enters the warehouse and an event is subsequently raised once the relevant item has reached its predefined location within the warehouse note that when I refer to an item I'm referring to a batch of units of a particular type so in our example the item can refer to a quantity of units a unit in this example will be a hardware related item for example a drill hammer ladder Etc so if we use our imaginations we can picture the scenario in the real world an item enters the warehouse and is scanned so let's say the item has a QR code attached to it that when scan provides necessary information about the item when the item is scanned an event is raised so for example a supervisor could be monitoring the relevant activities relating to the warehouse and when an event is raised the relevant information is displayed on a screen in real time so the supervisor could for example be monitoring these real-time events using a handheld device a desktop computer or a notebook computer the display could perhaps be a large screen TV that multiple employees can monitor the use of events decouples the component that raises the event which could for example be an on-site scanning facility from a component that receives the event notification which could for example be a handheld device used by a supervisor to monitor events either on site or even remotely if required so for example a box containing drills arrives to be stored at the warehouse the QR code attached to the relevant box that the drills are in is scanned the box is then transported to a predefined location in the warehouse to be stored so when the box is placed in its relevant location perhaps pressure pads at the location are used to detect that the box of drills has been processed when I say processed Amin has arrived at its designated location to be stored in the warehouse so when the relevant pressure pad detects that the relevant box has been placed in its designated location in the warehouse an event is raised and the relevant information about the event is sent to the calling code which will then display the relevant information about the event and the processed item to the supervisor's screen so this is a real-time monitoring system for a warehouse please note I have never actually worked in a warehouse and this example is purely from my imagination it's obviously always best when building a particular kind of application or system to consult with someone with the relevant domain knowledge this example only serves to help with the understanding of generic delegates and events right let's begin let's create a.net core console application [Music] and let's name this project hardware warehouse management system so this project will contain our calling client code we want this project to reference another component responsible for generic functionality associated with a warehouse so let's add a net standard Library project and let's name this project warehouse management system API let's create a reference to the warehouse management system API project from the hardware warehouse management system project so we'll start by building the generic functionality for our hardware warehouse management system by adding code to our warehouse management system API project so we have separated concerns here we have created two components one to handle the specific functionality of the hardware warehouse this functionality will be encapsulated in the hardware warehouse management system project the code in this component will focus on displaying the status and data about specific Hardware related items to a screen in real time as certain events are raised the other component is a generic component specifically created for handling the management of any warehouse this component is responsible for racing events associated with any warehouse to the calling client code when each event is raised from the warehouse management system API component to the hardware warehouse management system component the relevant data associated with the relevant event and item is displayed to the screen in real time to for example a supervisor so let's write the code for our example let's start by deleting the default class from our warehouse management system API project let's add a class named custom queue in the custom queue class we are going to wrap the functionality provided by the built-in c-sharp generic Q data structure we are going to customize the functionality of the queue by adding two events simply put one event will be raised when an item is added to the queue the other event will be raised when an item is removed from the queue as you may have guessed when an item is added to the queue this denotes an item for example a box containing drills entering the warehouse the second event denotes the event that will be raised for example once the relevant box containing the drills has been processed I.E has been placed in its specified location to be stored within the warehouse so let's make our custom Q class a generic class a generic class can contain more than one type parameter but we are only going to add one type parameter for this class so using the capital t is the generally accepted way to represent the placeholder for a type parameter and a generic type definition if there were two type parameters we could add a comma and then the capital letter U to represent a second type parameter this generic class will only contain one type parameter so let's remove the second type parameter so by adding t with an angle brackets following our class's name we have created our custom Q class as a generic class so let's create a private member variable of the inbuilt c-sharp Q generic collection type so let's define this member variable as the generic Q data type and let's name our variable underscore Q and you can see that a directive at the top of our code already exists to the system.collections.generic namespace the queue data type is a member of the system.collections.generic namespace let's create a parameterless Constructor for the custom queue class let's instantiate the underscore Q variable within our Constructor let's create a read-only property and Implement code that Returns the number of items currently stored in the underscore queue collection let's create the definitions for the public methods that will be included in the custom queue class we'll first add their definitions and then implement the code for each method let's create a method named add item that contains a parameter of type t this method will be called when an item is added to the custom queue let's create a method named get item this method will return an item stored within the queue to the calling code this method returns a value of type T and contains no parameters let's create a protected virtual method named On Cue changed this method will encapsulate the functionality for raising the events of this class it contains a parameter of a user-defined type that we need to create the value passed to this parameter will store information about the relevant event being raised from within this method so let's create a class definition for a class named Q event args this class will extend the functionality of the system.eventorg's built-in class so let's write code so that this class inherits from the system.event args built-in class let's add a read write autoimplemented property named message to the queue event args class the message property will return a string narrative which will include details about the item to which the event pertains as well as information about the event itself so the last method we need to create is a public method named get enumerator so this method returns a value of the generic I enumerator interface type to the calling code so let's implement the code for this method the implementation is one line of code which Returns the value returned from the underscore Q member variables Getty numerator method by implementing this get enumerator method on our custom queue class this will allow the calling code to Traverse the elements stored within the custom Q class collection using a for each Loop we'll demonstrate this at an appropriate time during the development of this example so let's create our delegate type which will be used to define an event in the custom queue class I.E the event that is raised when an item is added to the queue and also an event raised when an item is returned from the queue let's define our generic delegate type directly within the warehouse management system API namespace let's create a public delegate named Q event handler that does not return a value and contains two generic parameters the first parameter is of type t and the second parameter is of Type U this is a generic delegate that contains two type parameters so we must include the placeholder data types within angle brackets the capital letter T represents a placeholder for the first generic data type parameter and the capital letter U represents a placeholder for the second generic data type parameter so now we can define the definition for the event contained within our custom queue user-defined type so to do this we use the event keyword this is a public event to which we want our calling code to subscribe so we proceed the event keyword with the public access modifier then we follow the event keyword with the generic delegate type that we have just defined the generic Q event handler delegate and let's strongly type our generic delegate let's pass the custom Q generic user-defined type to the first generic data type parameter and let's pass the Q event args use the defined type to the second generic data type parameter let's name our event custom queue event so let's implement the code for the On-Q changed method this method centralizes the code for raising the custom queue event event so the first argument passed to this event is of the generic user-defined type named custom queue which is the class in which this method resides so to get the current object we can use the this keyword the second argument is the argument passed to this method's parameter and will contain information about the event and is of type Q event args so we pass the On Cue changed methods argument a as the second arguments to the custom queue event event so let's implement the code for the add item method firstly let's write code to add the item passed into the add item method to the underscore queue collection note that in order to add an item to the built-in C Sharp Q data structure we must use the NQ method so before we write the code to raise our custom queue event event which will be executed every time the relevant queue is changed let's look at the Q generic collection type in C sharp when we use the NQ method to add an item to a queue data structure in C sharp the underlying functionality of the Q collection type is adding the relevant item to the back of the queue as it were so later when we write the functionality to retrieve an item from the queue we'll use the DQ method the DQ method retrieves an item from the front of the queue the queue data structure works on a fifo basis fifo is an acronym for first in first out so the item in the queue that was the first item to be added to the queue when the NQ method was executed will be the first item to be retrieved from the queue when the DQ method is executed we'll use the DQ method when we implement the functionality for the get item method note that when the DQ method is executed to retrieve an item from the queue the first item added to the queue which will be the item at the front of the queue is removed from the queue which means the item that was added to the queue right after the item that was just retrieved from the queue takes the position previously occupied by the item just retrieved from the queue so the way the ordering of the Q data structure works is just like how a queue works in the real world for example consider people queuing to buy tickets to an event when a person joins the queue the person joins the Queue at the back of the queue the person at the front of the queue buys a ticket then leaves the queue making the person that was behind the person who has just left the queue now the person at the front of the queue this person can now buy a ticket and the cycle repeats so after the NQ method has been executed this means the relevant queue has changed so we want to raise an appropriate event to the calling client code to let the client code know that the relevant queue has changed when the event is raised we can pass two arguments to the calling client the first argument is the queue itself which is encapsulated in our custom Q generic class the second argument contains information about the event as well as information about the item that triggered the event this information is encapsulated in the queue event args user-defined type so let's write code to instantiate an object of type Q event args and we want to send information about the item being added to the queue through the message property which is a member of the Q event args class to the calling client code notice at the moment if we include a full stop after the item variable we don't get any properties in the intellisense drop down list in Visual Studio for example we don't get the ID name or type properties that could provide useful information to the calling client code about the item that triggered the relevant event so how can we solve this problem we can solve this problem by ensuring that items added to the queue Implement a specific interface then we can add a constraint to our generic custom queue class that enforces a rule that type T must implement the relevant interface so let's add an interface to our warehouse management system API project let's name this interface I entity primary properties foreign let's add three property definitions ID as integer name as string and type as string let's go back to the custom Q class and let's add a constraint to our custom queue class so we can add the constraint like this where space t colon I entity primary properties so we now know that any item added to the queue will implement the I entity primary properties interface which means the item will have an ID property a name property and a type property so because we have added this constraint we should now be able to see these properties if we add a DOT at the end of an object passed into the add item method as an argument so let's add a DOT at the end of the item variable and you can see the ID name and type properties in the intellisense drop down list this means we can include the information stored in these properties in our message to the calling client code so in the message property let's add a timestamp foreign so I'm going to add a new class named constants so that I can store a string constant that can be reused to represent a date time format for this project and let's include the formatting for the relevant date time stamp using our date time format constant followed by the relevant ID name and type property stored for the relevant item great but let's say we want to include additional information in our message to the calling client code we want to include the quantity of units that make up the item that has entered the warehouse remember items are composed of units we also want to include the value of each unit with the additional information for design reasons we don't want to include the quantity property and the unit value property in the I entity primary properties interface so let's add another interface to the warehouse management system API project and let's name this interface I entity additional properties let's add two properties to this interface quantity as int unit value as decimal let's go back to our custom queue class and let's add another constraint to the custom Q class definition to do this we can simply add a comma and then I entity additional properties to the custom Q class definition for now let's see if our new properties appear in the intellisense drop down when we add a DOT after the item variable which is of type t and there you can see our additional properties quantity and unit value so let's include the quantity property in our message the unit value property will be displayed to the user along with all the other properties in a tabular format every time the queue changes we'll see this when we develop the calling client code let's add the following narrative text literal to the message property has been added to the queue so let's implement the code for the get item method so let's first assign The Returned value from the relevant Q IE the value returned from the DQ method to a local variable of type t the DQ method also removes the item at the front of the queue so let's write the code that will notify the calling client that the queue has changed let's set the message property of the queue event args object in much the same way as we did in the add item method the difference is that this method denotes that the relevant item in the queue has been processed so let's reflect this in our narrative so let's add the literal text has been processed to our narrative so an item is removed from the queue once the item has been processed by processed we mean that the item has been placed in a designated location in the warehouse for storage the item is added to the queue when it first enters the warehouse then the item is scanned when the item is scanned the event and the add item method is raised when a predefined amount of items are in the queue the items in the queue are processed I.E each item is placed in a specific location in the warehouse to be stored each time an item is placed in its location for storage a pressure pad is activated at the relevant storage location which raises an event to notify the calling client code that the relevant item has been processed we have now implemented the code for the custom queue class and we have also completed the code for the warehouse management system API component let's implement the code for the calling client so in this example we have a warehouse used for storing Hardware related items when we refer to an item in the context of this example we mean a collection of a certain type of Hardware item so for example we are going to use four distinct item types drill hammer ladder and paintbrush so in this example an item could refer to a collection of drills a collection of hammers a collection of paint brushes or a collection of ladders so let's define an abstract class named Hardware item which must implement the interfaces we created in the warehouse management system API component namely the I entity primary properties and the I entity additional properties interfaces we have already created a reference from the hardware warehouse management system project to the warehouse management system API project but we must also ensure that we have included a directive at the top of our code to the warehouse management system API namespace so let's do this great let's create auto implemented properties for each property definition in the I entity primary properties and the int additional properties interfaces foreign classes representing a specific type of item that will be stored in the warehouse let's start with the drill so we must make the drill class inherit from the hardware item abstract class let's say we also wish to create more specific Properties or behaviors for the drill class we can do this by adding an interface to define specific Properties or behaviors relating to the drill class by creating an interface that the drill class must implement so let's create an interface named I drill for the sake of keeping our example simple let's just add one property definition for the ideal interface let's make it a string property and name it drill brand name so this property is only intended to acknowledge that we are able to extend each of the classes representing specific products in this example but we won't be using these properties further than this so let's ensure that the drill class implements the idrill interface let's implement the same design for our other items ladder paintbrush and Hammer great so let's go to our main method and simulate items entering the warehouse by adding items to a custom queue object let's instantiate an object of the generic custom Q class to find in the warehouse management system API component that our calling client code references let's strongly type our queue with the hardware item abstract class we do this because all items in our warehouse will inherit from the hardware item abstract class so the next step is to wire up a method to handle the event defined within the custom queue class this is an event that is raised whenever the relevant queue changes for example an item is added to the queue denoting a hardware item entering the warehouse or an item is removed from the queue denoting that the item has been processed I.E the item has been moved to a predefined location within the warehouse for storage so to wire up the relevant event we type the object reference custom queue add a DOT and then we can see the relevant event in the intellisense drop down list so let's select the event named custom queue event then we can type in the plus equals operator to establish a method that we want to execute when the relevant event is raised so we can Auto generate the relevant method through Visual Studio by pressing the Tab Key we can now implement the custom code we want to execute it every time the queue changes within the relevant method we have just generated so let's first write code to clear the screen so notice that the first argument passed to this method is an object of type custom Q it is named sender because the event that is fired resides in this class so the event notification is sent from the custom cue class when the relevant event is fired so the second argument is of type Q event args and encapsulates relevant information about the relevant event so let's write code to check if the sender object which is an object of type custom queue contains any items so to do this we can use an if statement to check the Q length property of the custom queue class so if the Q length property is greater than zero let's write the properties of the items stored within the queue to the console screen let's create a private method named write values in queue to screen that contains a parameter of type custom queue which is strongly typed with the abstract class Hardware item let's write a for each Loop to Traverse the items in the queue and write each item's properties to the console screen so these items will be written to the screen in a tabular format so I've made sure that each column is set to a specific length let's call this method from the custom queue underscore custom queue event method I.E the event handler method so let's go to the main method create 10 Hardware items and add them to the custom queue I'm actually going to change the name of the variable we are using to reference the custom queue object to a more specific name let's change the name of this variable from Custom queue to Hardware item queue so I've already uploaded the code for this example to GitHub in the interests of time let's copy the code that adds Hardware item objects to the relevant queue from the code I have already uploaded to a GitHub repository so let's navigate to this web page from within our browsers and copy the relevant code foreign and then appropriately paste this code into the main method so this code which adds Hardware items to the custom queue simulates items entering the warehouse to give this example a more real world feeling to simulate that these items are entering the warehouse at random times I'm using the system.threading.thread.sleep method to add a time delay between the lines of code that add items to the queue so for example here we are delaying the main thread for 2 000 milliseconds which equates to a two second delay let's go back to the custom queue underscore custom queue event method and add an else part to the Top If statement so if the queue does not contain any items we want to Output status information to the user let's output the following text to the user when the queue does not contain any items status all items have been processed so let's run the code and you can see that each time an item is added to the queue an event is raised and our calling client code writes the details of the item to the console screen great so let's create the code for when items in the queue are processed for the sake of keeping this example simple let's say that when the queue contains five items we want the items in the queue to be processed so let's define a constant as an integer and let's name this constant batch size let's set this constant to a value of 5. so we can now write a nested if statement in our custom queue underscore customqueue event method that checks if the queue has five items in it if the queue has five items in it we want code to execute that simulates the processing of each of the items in the queue so let's write a private method named process items it contains one parameter of type custom queue that is strongly typed with the hardware item user-defined abstract type let's write code to Simply Traverse the items in the queue through the use of a while loop the condition of the while loop is that iterations of the loop must continue while the queue is not empty so we want to de-queue each of the items in the queue meaning that the item has been processed remember that when the get item method is called the DQ method on the underlying queue data structure is called which means the item at the front of the queue is removed from the queue let's add a three second delay before each item is removed from the queue to simulate that the item is being processed let's go to the custom queue underscore custom queue event method and write code to call the process items method let's run the code now you can see that when the queue is populated with five items the items are processed and each item is removed from the queue once the relevant item has been processed when the queue is empty the next five items are added to the queue and once five items have entered the queue the items are processed one by one until the queue is empty great so to further clarify to the user the status of each item in the queue let's write the message property of the event args object to the console screen this message property contains a narrative describing the relevant item and the event pertaining to the item let's run the code excellent the supervisor can see relevant information about the item as well as the event the supervisor can see status output for each item as it enters the warehouse and is processed the final thing to do is enhance the formatting of the output in the interests of time let's copy and paste relevant formatting functionality from GitHub so let's navigate to this location in our browsers and please feel free to copy my actions here let's copy the code situated between the two comments that have the text headings let's then paste the code into our code editors we can then write the code to call these output formatting related Methods at appropriate points within the custom queue underscore customque event method foreign let's run the code foreign thanks so lastly I'm going to put a few break points in the code to clarify the execution path of the code so in the calling client code when the code adds an item to the custom queue you can see the event that resides in the custom queue class in the warehouse management system API component is raised and the code in the calling client handles the event through a method that was designated to handle the event when the calling client code subscribed to the relevant event when the predefined batch size of five has been reached I.E when the custom queue contains five items each item is processed once an item has been processed it is removed from the queue the event is raised to the client and the client method that has been designated to handle the event is executed when the calling client subscribed to the event in the custom queue class a method that resides in the calling client code was designated to handle the event when the event is raised the relevant event handler method is executed in this event handler method we are writing status information to the screen so that this information is available to for example a supervisor in real time I hope you've enjoyed this video which demonstrates the use of the c-sharp generic built-in Q data type a generic class with constraints and the use of a generic delegate used to define an event for more videos on advanced c-sharp concepts and much more please consider subscribing and please ring the bell so that you'll be notified of future content released from this channel if you feel you have gained value from viewing this video please hit the like button it'll be greatly appreciated please feel free to share any of the videos released from this Channel with anyone you feel May benefit from their content your comments are of course always welcome the code created in this tutorial can be downloaded from GitHub please see a link to the relevant repository Below in the description [Music] hi and welcome this video is the fourth and final part in a video series on c-sharp generics [Music] shop generics video series is the fifth part of a course on advanced c-sharp concepts in this video we are going to first look at how in terms of generics the msil code or Microsoft Intermediate Language code is handled by the common language runtime under the hood as it were if you stick around till the end I'll show you how a utility that ships with Visual Studio for Windows named Intermediate Language disassembler can be used to disassemble an assembly whereby the msil code can be extracted from the.net assembly and inspected we'll then look at a basic code example whereby the factory design pattern is implemented and generic supplied to our Factory class so that this class can be reused to instantiate multiple types we'll apply multiple constraints to our Factory class to enforce design rules driven by the requirement for our code example for more videos on advanced c-sharp concepts and much more please consider subscribing and please ring the bell so that you'll be notified of future releases from this channel so let's briefly look at how generics in the msil code or Microsoft Intermediate Language code is handled by the common language runtime I'm not going to go into a lot of detail in this regard but please check out this Microsoft document for a more detailed description regarding how generics is handled by the.net runtime this document explains how generics is handled differently for Value types and reference types by the.net runtime let's look at a few excerpts from this document specialized generic types are created one time for each unique value type that is used as a parameter this means conversions are no longer necessary because each specialized generic class natively contains the value type generics Works somewhat differently for reference types the first time a generic type is constructed with any reference type the runtime creates a specialized generic type with object references substituted for the parameters in the msil then every time that a constructed type is instantiated with a reference type as its parameter regardless of what type it is the runtime reuses the previously created specialized version of the generic type this is possible because all references are the same size because the number of reference types can vary wildly from program to program the c-sharp implementation of generics greatly reduces the amount of Code by reducing to one the number of specialized classes created by the compiler for generic classes of reference types so two benefits are highlighted in this document with regards to value types and reference types in terms of generics conversions are no longer necessary because each specialized generic class natively contains the value type generics greatly reduces the amount of Code by reducing to 1 the number of specialized classes created by the compiler for generic classes of reference types my goal here was only to draw your attention to the extra information regarding how the.net runtime implements generics and c-sharp under the hood as it were please read this document to gain a better understanding in this regard so let's Implement our code example where we'll implement the factory design pattern and use generics so that the object instantiation code is abstracted and can be used to instantiate multiple types we'll use multiple constraints appropriate to our requirement so that special rules at compile time are enforced let's create a.net core console app and let's name it digital product inventory application so in this very basic example we're going to create classes for representing specific types of digital products we'll also create classes for encapsulating data associated with the various categories of digital products we are going to create a factory class used to abstract and centralize the construction of these different types into objects we'll then copy code from a GitHub repository and this code will serve as the calling client code this client code includes a link query used to compile a report containing digital product information and their Associated digital product category information code is also included to Output the results of this link query to the console screen this example is more about understanding the application of generics than understanding link please don't worry if you don't fully understand the link aspect of this tutorial link will be discussed in detail in upcoming tutorials so let's create our Factory class this tutorial is not about design patterns but the factory design pattern is used in this example as a device to show how generics and constraints can be implemented to abstract the construction of objects of varying types special rules will also be applied through the use of constraints let's name this class Factory pattern so this class contains two generic types so let's include the constraints for the type T parameter and our definition of the factory pattern class as we know from our previous tutorials constraints enforce compile time rules on our type parameters so this constraint is enforcing a compile time rule that type T must be a reference type denoted by the class constraint must inherit from Type U I.E the other generic type parameter and the type T argument must also contain a public parameterless Constructor this is denoted by the new constraint note that when the new constraint is used with other constraints the new constraint must be specified last in our code we are going to instantiate an object of type t note that a generic type cannot be instantiated if the new constraint is not specified for the type that must be instantiated we'll prove this in a bit so let's also add a constraint to our u-type parameter we can do this by including another where keyword followed by the relevant constraint or constraints for the U data type note that this class constraint for this example is in fact redundant for the U parameter and I will remove this from the relevant GitHub repository I'm applying this constraint at this point in the tutorial to show how we are able to apply constraints to multiple type parameters thank you so let's add a method to our class and name it get instance so the code Logic for this method is instantiating an object of type T which is derived from Type U the instantiated object is then returned to the calling code so now just to show you that we cannot instantiate an object of type T unless the new constraint has been appropriately applied to the relevant class definition let's comment out the new constraint and you can see that the c-sharp compiler immediately complains we must ensure that we have appropriately applied the new constraint in order to be able to create an instance of type T so let's now create an interface named I primary properties let's add two property definitions to our interface ID as int and title as string so now let's go back to the factory pattern class let's add a constraint to enforce a rule that Type U must implement the I primary properties interface so we can do this by adding a constraint like this remember the class constraint can be removed from the U type parameter the code will still work as expected with it there but for this example it is redundant so let's add an abstract class name to product base that implements the I primary properties interface let's implement the properties defined in the I primary properties interface as Auto implemented properties let's create an abstract class named category base that also implements the I primary properties interface let's extend the product based class by adding an auto implemented property named category ID the category ID property will be included within our link query to join the data stored in a list containing objects of type category base to relevant product objects stored in a list containing objects of type product base we'll look at the link query in a bit let's extend the category-based abstract class and add an autoimplemented property named description so let's create our category classes let's create our digital product classes so our category classes inherit from the category-based abstract class and our product classes inherit from the product base abstract class note that both the product-based abstract class and the category base abstract class both implement the I primary properties interface notice I am extending these classes with additional properties just for demonstration purposes these additional properties won't be used further than this in this example so I'm going to create a class named product view model and this class will be used as a template to centralize information from the product related classes with information from their relevant category related classes so we want our calling code which we'll copy from GitHub to create several product objects and related category objects then using link we'll return a collection of objects of type product view model to the calling code this collection will be the result of a join operation joining objects of type product base with the relevant objects of type category base link is not the focus of this tutorial but I thought I'd include the link functionality to make our example more interesting as stated earlier we'll discuss Link in detail in upcoming tutorials so don't worry if you don't understand the link related code so I've already uploaded the code for this example to GitHub so let's copy the code which will serve as our calling client code from the relevant GitHub repository which can be found at this location this URL has also been included Below in the description let's copy all the code from within the program class like this and let's select the main method within our program class and our code editors and paste the code we have copied from GitHub over the main method in our code editors like this and you can see that we have red squiggly lines under our code relating to our generic lists so to fix this let's add a directive to the system.collections.generic namespace and in our get products method where we are executing a link query we have a red squiggly line here so to fix this we need to add a directive to the system.link namespace great so let's look at the calling client code we have just copied from GitHub the add properties to product method encapsulates functionality to add values to the properties of an object of type product base the add properties to category method encapsulates functionality to add values to the properties of an object of type category base you can see that these methods are currently public methods but they don't need to be public so we can change these methods to private I'll update the relevant GitHub repository with this change you can see here that our link query is encapsulated in a method named get products the link query is selecting all product related objects in the products list and joining each product with its relevant category each product is joined to its relevant category through the category ID property the result of the link query is a collection of objects of type product view model which appropriately combines product information with relevant category information as stated earlier link will be discussed in detail in upcoming tutorials so let's look at the code in the main method so notice how the factory pattern generic class is being used to instantiate each object of type product base for example we are instantiating an object here which represents a digital book entitled The Old Man and the Sea we are instantiating an object here representing a movie entitled Shawshank Redemption the factory patent generic class is then reused to instantiate several objects of type category base for example we are instantiating an object representing the category with the title of movie here and we are instantiating an object representing the product category here with the title of music so the factory pattern class has been implemented to abstract the object creation functionality for this code example we have adapted the factory design pattern to our requirements by imposing rules on the instantiation process through the use of constraints so in the main method we are instantiating our product related objects appropriately adding values to the relevant object's properties then adding the objects to a list of product related objects we are doing the same thing for our category related objects we are then appropriately amalgamating information from the product related objects with relevant information from the category related objects into an object of type product view model through the use of a link query we are then looping through the items returned from the link query and writing each item's properties to the console screen so let's run the code great I want to draw your attention back to the constraints in our Factory pattern class note that we have implemented a constraint that the U argument must implement the I primary properties interface so if for example we were to comment out the code in our class definition for the category-based abstract class that indicates that this class implements the I primary properties interface look at how the c-sharp compiler responds note how the constraint imposes a rule at compile time that the U argument must implement the I primary properties interface for more detailed information on constraints please navigate to this URL so we were discussing earlier how the.net runtime handles generics based on the msil code we are able to examine the msil code for an assembly by using a utility like for example the IL disassembler utility so now if we wanted to look at the msil code for this project we can use this utility this utility ships with the visual Studio for Windows IDE so let's run our developer command prompt for visual studio let's make the directory where our Target assembly file resides our current directory we can then type the following command this command generates a file containing the msil code within the directory of the relevant assembly this is the msil code that resides within the target assembly created when we built our c-sharp project so now we can open the file we have just created in a text editor like notepad and look at the relevant msil code great for more detail on the IL disassembler please navigate to this URL all urls mentioned in this tutorial can be found Below in the description lastly if you are interested in reading about generics and reflection please navigate to this URL if you are interested in reading about generics and attributes please navigate to this URL reflection can be used to inspect generic types in c-sharp at runtime and this will be discussed in later videos created on c-sharp reflection generics used with attributes will be covered in future videos created on c-sharp attributes in this video series we discussed that generics was introduced in c-sharp version 2. we looked at why it is better to use the strongly typed generic list to store a collection of items rather than an arraylist for this purpose we discuss the benefits of generics generic classes and methods combine reusability type safety and efficiency in a way that their non-generic counterparts cannot we looked at how constraints can be applied to generic type parameters in order to enforce compiled time rules on generic type parameters we created a code example representing a warehouse management system in this example we used the built-in c-sharp generic Q collection type to store objects representing various Hardware items that enter the warehouse and are subsequently processed generic delegates and events were instrumental in this real-time monitoring system lastly in this video we briefly looked at how the msil code or Microsoft Intermediate Language code is used by the.net runtime to efficiently handle both value types and reference types in terms of generics we also implemented a generic version of the factory design pattern and a basic code example to demonstrate how the use of multiple constraints can be applied to generic types in order to enforce special requirement-driven compile time rules I hope you have enjoyed this video series on c-sharp generics for more videos on advanced c-sharp concepts and much more please consider subscribing and please ring the bell so that you'll be notified of future content released from this channel if you feel you have gained value from viewing this video please hit the like button it will be greatly appreciated please feel free to share any of the videos released from this Channel with anyone you feel May benefit from their content your comments are of course welcome the code created in this tutorial can be downloaded from GitHub please see a link to the relevant repository Below in the description [Music] hi and welcome this is the sixth tutorial in an advanced c-sharp course and this is the first part of a video series on asynchronous programming using the c-sharp programming language in this video we'll look at an overview of asynchronous programming in c-sharp with a particular emphasis on Microsoft's recommended approach to using asynchronous programming for new development Microsoft's recommended approach to including asynchronous behavior in new applications is to use the task-based asynchronous pattern tab the two Legacy methods for providing asynchronous Behavior are event-based asynchronous pattern EAP and asynchronous programming model APM the event-based asynchronous pattern will not be discussed in this video series but if you wish to learn more about this Legacy pattern please navigate to this URL we have already covered the asynchronous programming model APM and the advanced course in part 3.5 of this course we looked at using a callback method and a built-in delegate to implement asynchronous Behavior please navigate to this URL to view a video released on this channel that covers the asynchronous programming model APM as always all links mentioned in this video can be found Below in the description later on in this tutorial we'll look closer at how using the task-based asynchronous pattern can result in asynchronous behavior for our applications and ultimately ensure that our users have a smooth user experience when using our applications for more videos on Advanced t-sharp topics and much more please consider subscribing and please ring the bell so that you'll be notified for future videos released from this channel right so tab or task-based asynchronous pattern is the recommended design pattern for creating asynchronous behavior for new development c-sharp version 5 produced a simplified approach to asynchronous programming that leverages asynchronous support in the.net framework 4.5 and higher.net core and the windows runtime dotnet framework 4.5 or higher and net core contain many members that work with async and await these members can be identified by their names which contain an async suffix so what gave rise to the task-based asynchronous pattern we live in an age where our applications should not only run on desktop computers and notebook computers our applications in a lot of cases will also need to run on smaller devices for example handheld devices like tablets and mobile phones these smaller devices may not have the powerful resources that desktop computers and notebook computers have to handle resource intensive operations so an operation like for example downloading a large document from a remote server May ultimately result in poor performance of our applications a poor ux or user experience with our applications can cause user frustration and cause our users to take a dim view of our applications thank you implementing this pattern in our code can result in a smoother ux user experience the code is easy to implement and even though the code results in asynchronous Behavior the code can be written in a synchronous way we'll look at a code example to further elucidate this point in a bit the c-sharp compiler makes it very difficult for a developer to implement the task-based asynchronous pattern incorrectly for example in an IDE like Visual Studio red squiggly lines will appear in appropriate regions of code if the relevant asynchronous code has been written incorrectly messages will also be made available to the developer from the c-sharp compiler in Visual Studio to guide the developer on how to fix the incorrect code so how can long-running operations result in a poor user experience with our applications say for example a button is clicked and within the event handler method of the relevant button click event a long running operation is invoked if this operation were to be invoked synchronously the threat of execution on which the relevant time-consuming operation is running is blocked until this long-running operation has completed while the relevant thread is blocked the application is unresponsive meaning the user cannot perform other operations with the application until the long-running operation completes so this ultimately results in poor user experience with our application there are two kinds of blocking operations CPU bound operations and I O bound operations so let's look at CPU bound operations this occurs when an intensive computation needs to be carried out by the device's CPU for example you might have a game running and a single action from the user may cause multiple characters in the game to incur damages the calculations of these damages may be CPU intensive an operation like this if done synchronously can result in the UI to freeze or stutter running the calculations in parallel across multiple cores can alleviate this and make the UI or user interface perform smoothly and responsively so the developer could use the task.run method to run calculations in parallel to alleviate the effects that handling these computations synchronously could have on the user's experience other examples of applications that may need to run intensive CPU bound operations could be Financial or scientific applications so let's look at i o bound operations i o bound operations are performed when requesting data from a network accessing a database or reading and writing to a file system the blocking effect during an i o bound operation causes the CPU to wait for the relevant i o bound operation to complete so the CPU will need to wait basically light dormant while for example information is retrieved from an Azure SQL database that resides in the cloud once the information is retrieved and for example appears in local memory the information can then be processed by the CPU the CPU can only then continue processing other instructions while the i o bound operation is running the CPU is blocked from running any other operations performance will not be optimal for our applications when the code for these relatively long running operations are handled synchronously i o bound operations are the most common encountered blocking operations so we are going to focus on resolving the blocking effect of i o bound operations through the implementation of the task-based asynchronous pattern in this video note that generally speaking io-bound operations are far slower than CPU bound operations in business applications i o bound operations will be far more common operations that will be encountered and should be handled asynchronously and let me emphasize i o bound processing is far slower than CPU processing so let's look at a basic code example we won't implement this particular code in Visual Studio this code serves to give us a general idea of what the task-based asynchronous pattern looks like in c-sharp code and we'll also get an idea of how it works let's first look at the synchronous version of this code example we'll then modify the code so that it is implemented using the task-based asynchronous pattern so in this synchronous version of the code example we have a higher level button click event handler named button underscore click when the user clicks the button that invokes code within this event handler method a call to a method named get document content is made this method accepts an argument which is the name of the remote file that our code needs to retrieve and process so let's say that the path of the remote document is handled under the hood as it were a relatively long running operation is encapsulated within a method named get document content as string which is invoked within the get document content method the long-running operation in this case is downloading a document from a remote server after the long-running operation completes a string is returned from the get document content as string method containing the relevant document content a method named save document locally is then called which as the name suggests saves the content returned from the get document content as string method to a local file store as a new file the document content is then returned to the calling code from the get document content method once the get document content method completes and Returns the content to the button-click event handler method the content is subsequently displayed to the user this is denoted by a call to a method named display content so while the code is performing the relatively long-running operation executed by the get document content as string method the thread of execution on which this operation is running will be blocked leaving the CPU idle until the get document content as string method completes and returns a value so let's say that we are in luck and there is an asynchronous version of the get document content as string method available to us named get document content as string async note that this version of the method has the same name as the synchronous version with the exception of the async suffix added to the end of the method's name adding the async suffix to the end of an asynchronous method's name is a naming convention used for asynchronous methods that are part of the implementation of the task-based asynchronous pattern so the method we want to call is named get document content as string async so we need to use the await operator preceding the method called to the get document content as string async method like this this is telling the c-sharp compiler that we wish to call this method asynchronously if any of our method calls within the get document content method are awaitable as is now the case here where we are using the await operator we need to include the async modifier in the method signature of the method where one or more asynchronous method calls are invoked which as stated is denoted by the await operator preceding the relevant asynchronous method being called so let's include the async modifier in the method signature for the get document content method let's also adhere to the correct naming convention so let's rename the get document content method to get document content async like this the get document content async method will return a string value once the async method has completed but when it is first called and hasn't necessarily completed a generic task object will be returned I'll elaborate on what the task object and the generic task object is in a bit so we must include the relevant generic task type in the method signature of the get document content async method like this we are calling an asynchronous method from the button click event handler named button underscore click so we need to include the await operator preceding a call to the get document content async method like this we are now calling an awaitable method within the button underscore click event handler method so we need to include the async modifier within the method signature of the button underscore click event handler method like this we don't need to include a task type in the button underscore click event handler method signature because it is a high level event handler all asynchronous methods that are not high level event handlers like the button underscore click event handler will return a task object if the relevant method does not return a value or a generic task object if the relevant method does return a value as is the case with our get document content async method which returns a string so for example the get document content async method returns a string value once it has completed so to reflect that this method is an async method that returns a string value we include the generic task type in its method signature and this generic task type accepts the string data type as its argument so basically the new asynchronous implementation of this example code means that when asynchronous methods are called with the await operator the control is immediately returned to the calling code meaning that the thread of execution on which it is executed is free to process other operations while the asynchronous method is running so the CPU is not left idle while an i o bound operation is underway as is the case in this example where a file is retrieved from a remote server in this asynchronous implementation the CPU thread of execution on which the relevant relatively long running operation was invoked can be used to perform other operations while the remote file is being retrieved from the remote server in this case the UI thread is the thread of execution so if for example the user needed to execute a different button click event another operation could run concurrently to the long-running operation and vote by the get document content as string async method this means the user's experience with the application will not be negatively impacted by this relatively long-running operation the user experience is not adversely affected by the relatively long-running operation performed by the get document content as string async method so when the get document content has string async method is called a generic task object is returned immediately to the calling code the string value that is returned only once the get document content has string async method completes is returned at that point of execution in the code but at a later time while the relatively long operation invoked by the get document content as string async method is running other operations can be performed by the user without negatively impacting the user's experience with the relevant application basically the task object is a state machine if you'd like a comprehensive explanation of what a state machine is please navigate to this URL the task object encapsulates information about the asynchronous process and either delivers the final result back once the asynchronous method completes or throws an exception if an exception occurs within the asynchronous method so we can put traditional try catch code around the call to our asynchronous methods as if the methods were synchronous to handle exceptions that may occur in our asynchronous methods so when the awaitable method is executed a task object is immediately returned to the calling code the string value is only returned later once the awaitable method completes when the task object is returned the relevant thread of execution is then immediately released to the caller the thread of execution is not blocked while the asynchronous operation is running so the async method first Returns the task object in this case a generic task object that promises to return a string value at this point in the code once the operation performed within the relevant async method has completed this model is known as the promise model of asynchrony if you wish to read more about the promise model of asynchrony please navigate to this URL on the c-sharp side of things the c-sharp compiler transforms your code into a state machine that keeps track of things like yielding execution when an await is reached and resuming execution when a background job has finished the async modifier is doing two things number one it is a message to the c-sharp compiler that this method can use the await operator inside it the await operator designates the suspension points in the execution number two the method itself can be awaited by methods that are calling it the async modifier also is a message to the c-sharp compiler that the method can be called asynchronously using the await operator the await operator is telling the compiler that the execution of code cannot continue past this point until the awaited method has completed so in the meantime control returns to the caller of the method which is the UI thread in this case which allows for example the user to click other buttons while the incomplete asynchronous task is still running under the hood as it were when you compile your code through Visual Studio the c-sharp compiler rewrites your code into Intermediate Language splitting apart your async method calls into lots of callback methods so we as coders don't need to worry about the complexity of implementing callback methods ourselves with this explanation I'm admittedly in the interests of brevity glossing over a mass of complexity involved in making this asynchronous abstraction model work for more detail and a comprehensive diagram of how the underlying framework is handling the asynchronous code please navigate to this URL note that the line of code that includes the await operator is in fact doing two things it is returning a task object when it is first invoked and then later when the asynchronous operation completes it is returning the value returned by the relevant method in this case a string value so we can write the code like this to make this clearer we could first assign the task object returned by the relevant asynchronous method to a variable of type task this is done without the await operator we can then call the relevant task object with the await operator later in the code in this case the string value will be returned from the task object when the relevant operation completes in this particular example we can write what is achieved by two lines of code here in one line of code like this so let's put the code back to how we originally had it so let's create a code example we are going to create two.net projects one project will represent the calling client code I.E the code that will contain the user interface the other project will represent the server-side code the calling client will be implemented as a uwp project or universal windows platform project the server-side code will be implemented as a web API project this example is very basic we'll Implement a button click event handler on the user interface which will be included within the uwp project code within the relevant button click event handler will asynchronously call a method included within the web API server side component in the relevant web API action method we'll deliberately Implement a delay to represent a task that is relatively time consuming and should be awaited by our client code IE should be called asynchronously we'll Implement another button-click operation on the uwp projects user interface which will Implement code that runs a much faster local operation we'll run the code and demonstrate that when clicking the button that kicks off the time consuming operation implemented in the web API code that this does not impede the user's experience and the user is able to click the second button which carries out a much faster local operation perhaps the user can click this several times while the application is awaiting for the more time consuming operation carried out on the server side to complete and return a value to the calling client code will prove that the fast local operations can run concurrently while longer asynchronous operations are running in the background and because we have written the long running operation to run asynchronously that the user's experience is not adversely affected by running the relatively long operation so let's create a web API project and let's name this project test time consuming operation web API note that when the web API project is created a controller class is automatically included in the web API project this automatically included class is named weather forecast controller code within this controller simply outputs made up data representing a weather forecast we'll come back to this web API project in a bit and create our own controller class let's create a uwp project and let's name this project test client async uwp okay so let's go back to the web API project and let's create a web API controller class foreign and let's name this controller test long operation controller so the code in this method is faking a relatively long running operation that needs to be performed before returning a value to the client code the call to the server-side component's relevant action method will be handled through an HTTP get request from our uwp project we'll write the code for this in a bit please note that this tutorial is not about uwp or web API so I'm not going to go into detail explaining these two types of projects the focus is on writing code using the task-based asynchronous pattern in c-sharp to ensure that the user's experience is not adversely affected by long-running operations perhaps being run remotely through a web API call so note that we are not only going to use the task-based asynchronous pattern on the client side we are also using the task-based asynchronous pattern for this action method in the server-side code we have discussed how client-side UI synchronous code can negatively affect the user's experience and that implementing the task-based asynchronous pattern on the client side can make the user's experience much smoother the task-based asynchronous pattern can also be implemented for server-side components like for example a web API component or an asp.net MVC component this creates better performance on the server side which ultimately can affect client-side UI responsiveness on the server side it means for example that the thread of execution on which a relatively time-consuming method runs will not be blocked while the relevant time-consuming operation is performed and the relevant thread can handle other requests while the relatively time consuming operation is running in terms of the user's experience if a time-consuming operation blocks the threat of execution because of synchronous code this could tie up server-side resources causing a delay in performance on the server side and at worst could cause for example a client's HTTP request to time out so server-side synchronous code can also adversely affect the user's experience so in order to fake the long-running operation I'm simply going to create an await statement and use the task classes delay method to pause the method at this point for 5 000 milliseconds in other words it will cause a delay of 5 Seconds once the five second delay representing our long operation is finished the code returns a string value so let's return the text web API long running operation completed to the calling client code so let's test the code and you can see that the output from the weather forecast controller code is written to the browser window let's change the URI in our browsers to point to the controller code that we have just created so let's make a get request to our test long operation controller great there is a clear delay of 5 Seconds before the expected string results is written to our browser windows okay let's write the calling client code in our uwp project so we are going to drag two buttons onto the design surface from our list of xaml controls let's drag our first button onto the design surface foreign a bit let's name this button BTN local operation let's label this button local operation so let's zoom in a bit so we can have a clearer view of our button let's drag our second button onto the design surface so let's enlarge this button a bit let's name this button BTN web API call let's label this button web API call so let's drag a list view component onto our design surface you can see the list view is currently the same size as our design surface and is covering the whole design surface let's resize it so its contents will appear to the right of our buttons let's name our list view component lvw output you may have noticed that creating a beautiful design for our UI here is not a concern for this video but in the interests of Saving Time this design will be adequate for what we are demonstrating here it might be a good time to make the point that ux is not just about Aesthetics which of course is very important but it is also about performance we are focusing on how we can write asynchronous code to drastically improve the user's experience so let's go to the code behind our design surface and let's write a private method named add list item and here we are writing a piece of reusable code for adding a string value to our list view component within each of our two button click event handlers we want to add relevant string results to our list view component we'll write the code for the two button click event handlers in a bit let's create two integer member variables one named underscore local operation counter and the other named underscore web API operation counter let's write the code that executes when the button that performs the fast local operation is executed so we can Auto generate the method signature for the relevant button-click event handler method by double clicking on the relevant button on our design surface like this so when this button is clicked we want to increment the underscore local operation counter integer member variable by a value of 1. and append this integer value to the literal text fast local operation completed we are adding this string value to the list view component that we named lvw output through a call to a private method named add list item so let's implement the code to call the web API method that implements the long running operation and we want this code to fire when we click the button we have named BTN web API call so let's double click the relevant button on our design surface to Auto generate the relevant button click event handler method like this so the code share is a little bit more involved than the code that runs when the user clicks the button we have named BTN local operation let's first write the code to increment the underscore web API counter integer member variable by a value of 1. so we are going to use the HTTP client built-in class to make a HTTP get request to the relevant web API action method so let's instantiate a HTTP client object like this the HTTP class is a member of the system.net.http namespace so let's ensure we include the relevant directive let's use a HTTP response message object to encapsulate The Returned value returned from our web API components relevant action method so we need to run this line of code asynchronously which means we need to include the await operator before calling the get async method note the get async method has the async suffix so we know that this is an asynchronous method note the red squiggly line here because in order to run this code asynchronously we need to include the async modifier within our BTN web API call underscore click event handler methods method signature note that we don't need to return a task object from this button-click event handler method because this method is a high level event handler so we need to pass the URI of our web API action method to the get async method so that the relevant action method is invoked on the server when the user clicks the button named BTN web API call so let's run our web API component by running the relevant web API project so a get request is made to the weather forecast controller by default remember this code was Auto generated when we created our web API project let's change the URI within our browsers so that a get request is made to the get action method within our test long operation controller class let's refresh our browsers and note a five second delay before the expected result is written to the browser window so let's copy the URI that our browser is currently pointing to let's go to our uwp project and let's paste the URI here as a string argument to the HTTP client.getasync awaitable method let's call an awaitable method named read as string async to retrieve a Content returned from our call to the web API component then let's write code to add The Returned string to the list view component that we named lvw output we can do this through a call to our private method named add list item so let's move the code that increments the underscore web API counter variable to just above where we have added our string results to the list view component so we need to ensure that our web API project is first running before we run our uwp client code so let's do that let's run the uwp project so we can test the performance of our user interface let's first test that we are able to get a result back from our web API component so let's click the button labeled web API call great the result appears on the list view as expected the result is added to the list View and we can see it as output on the client side displayed within the list view component notice that there was a delay before the result appeared in the list view because we want this call to emulate awaiting a long-running operation now let's test that when we execute this long-running operation that the UI thread is not blocked the UI thread should not be blocked because we are making our get request to the web API component asynchronously so let's once again click the button to make our web API request and now let's click the other button several times to run our fast local operation several times great and you can see that the local task is running even while awaiting the result from our remote long running server-side operation the UI thread is not being blocked and our asynchronous code is working as expected you can see that when the asynchronous operation completes the appropriate result is added to the list view component and while we were waiting for the relatively long-running asynchronous operation to complete we were able to run several local fast operations so the fast local operations are running concurrently with the long-running asynchronous operation so let's make several requests to our web API component and let's also run our fast local operation concurrently several times great and you can see by the output appearing in our list view component that the user's experience is smooth the user's experience is not adversely affected when the long-running web API operation is executed the user is able to perform other operations using our application without the user's experience being impeded by other incomplete long-running operations this is why the task-based asynchronous pattern is so powerful this in my opinion is one of the reasons why the c-sharp language is so powerful because a lot of the complexity in making a long-running operation run asynchronously is hidden from the developer this complexity is abstracted the c-sharp language makes the inclusion of asynchronous behavior in our applications easy to implement please download the code for yourself and play around with the code so you can experience how the relevant asynchronous code results in a far smoother user experience than if the same code were implemented synchronously the links to the relevant GitHub repositories have been included Below in the description I hope you have enjoyed this video on using the task-based asynchronous pattern in our code to include asynchronous behavior in our applications in my opinion this is one of the most important Concepts in c-sharp programming in an age where smaller devices are used to perform relatively long-running operations we need to ensure that our users experience with our applications are not adversely affected by poor performance of our applications caused by synchronous code implementations of relatively long-running operations we can drastically improve the performance of our applications by running these relatively long-running operations asynchronously this is now easy to achieve using the c-sharp programming language please consider subscribing for more content on advanced c-sharp concepts and much more and please ring the bell so that you'll be notified of future content released from this channel if you feel you've gained value from viewing this video please hit the like button it will be greatly appreciated please feel free to share any of the videos released on this channel with anyone you feel May benefit from their content I of course love reading your comments so please feel free to share your thoughts with me in the comments section as always the code examples that were created in this video can be downloaded from GitHub a link to the relevant GitHub repositories can be found Below in the description thank you and take care [Music] [Music] hi and welcome to the second part of a tutorial on asynchronous programming using the c-sharp programming language this video is also the second part of the sixth tutorial in an advanced c-sharp course in the first part of this video series on asynchronous programming using c-sharp we specifically focused on the async modifier the await operator and the task object [Music] we discussed that there are essentially two CPU blocking operations that we may encounter When developing our applications namely i o bound operations and CPU bound operations these CPU blocking operations can result in poor performance of our applications and ultimately result in a poor user experience ux with our applications [Music] with the increased use of smaller devices that may not have the capabilities of say for example a notebook or desktop computer to handle resource intensive operations it is essential that we apply coding methodologies in our applications to ensure that the users are not negatively impacted by potentially resource intensive CPU bound or i o bound long-running operations the way c-sharp developers can solve these ux issues is through the implementation of asynchronous code the c-sharp programming language makes available several methodologies that can be implemented in our code to achieve asynchronous Behavior namely asynchronous programming model APM this was covered in part 3.5 of this Advanced c-sharp course event-based asynchronous pattern EAP and the task-based asynchronous pattern tab Microsoft's recommended approach to implementing asynchronous behavior in our c-sharp code is to use the task-based asynchronous pattern I recommend that you watch the first part of this video series before watching this video for more videos on advanced c-sharp concepts and much more please consider subscribing and please ring the bell so that you'll be notified of future content released from this channel so in the first part of this video series on asynchronous programming in c-sharp we focused on how to apply the task-based asynchronous pattern to handle the negative ux effects that can be caused by long-running i o bound operations in this video we'll focus on how to apply the task-based asynchronous pattern to handle the negative impact on the user's ux that can be caused by long-running CPU bound operations so let's start by briefly going over what is meant by i o bound operations and CPU bound operations io-bound tasks are delegated to the i o subsystem and while the relevant i o bound operation is handled the CPU thread on which the i o bound operation was invoked is blocked from running any other operations so while the relevant i o bound operation is running the CPU is idle all other operations are blocked from being processed by the CPU this can mean that if the relevant operation runs for a relatively long period of time that a delay in the user's interface or responsiveness can be noticed by the user this means the user's experience is negatively impacted by the relevant relatively long-running i o bound operation so the characteristic of non-cpu-bound processes is that they don't occupy the CPU when they are performing other operations like I O bound operations i o bound operations include tasks such as writing to your hard disk drive waiting for a response from the network or querying a database these operations cannot be sped up by fast local processing as performance is constrained by the i o subsystems hardware and performance the hardware drive's write speed will dictate how long something takes to be written the third-party server response time will determine how quickly you can process a request CPU bound means the limiting factor in a particular task or algorithm is doing calculations the only way to speed up the relevant CPU bound operation is increased CPU power adding more memory a faster i o for example will not help examples of CPU bound tasks are video audio content conversion compression algorithms search algorithms Graphics processing rendering games or videos heavy mathematical computations like calculating factorials matrix multiplication finding prime numbers Etc encryption decryption operations so basically tasks that require the CPU to perform computations so tasks that perform particularly intensive calculations may cause performance issues and ultimately ux issues when a user runs our applications the asynchronous handling of CPU bound operations are implemented differently than the way I O bound operations are implemented for a comprehensive explanation of how we can handle i o bound operations asynchronously in c-sharp code please view the first part of this video series in this video we'll focus on handling CPU bound operations asynchronously so let's look at a code example where we'll run a number of CPU bound operations in parallel to one another so let's look at a code example where we'll run a number of CPU bound operations in parallel to one another which as we'll demonstrate will result in an overall performance advantage over running the same CPU bound operations synchronously so let's create a console application and name it Financial trading platform application so the theme of this code example is a trading platform the user of this application can analyze stock market charts that will include technical indicators to help the user decide to open or close a position regarding a particular stock I'm going to drastically simplify this code example so that we can focus on the principles involved in running multiple computational operations asynchronously the technical indicator information that will be presented with the relevant stock chart will be calculated on the Fly so in this example the technical indicators that will be calculated on the Fly and presented to the user with the relevant stock chart or for example stochastics fast moving average slow moving average and Bollinger Bands I'm not going to go into detail regarding the meaning of these technical indicators basically they aid the trader in deciding whether a stock is overbought or oversold or whether it has growing price momentum or losing price momentum ultimately these technical indicators Aid the trader and the Trader's decision to buy or sell a quantity of a particular stock so for example the stochastics the fast moving average the slow moving average and the Bollinger Bands can all be calculated in parallel to one another these calculations can be coded to run concurrently rather than consecutively so let's create a public class named stock market technical analysis data let's create a Constructor in our new class just for the sake of making this example feel more authentic let's add three parameters to this Constructor we are going to keep this example very simple and these parameters will not actually be utilized the arguments passed into these parameters would be used as query criteria when getting the raw stock market data from a remote source so the first parameter is stock symbol AS string representing a particular stock that the user wishes to analyze for example Apple Amazon Tesla Anglo gold whatever it might be the second parameter represents the start date and is defined as date time the third parameter represents the end date and is also defined as date time so the date time arguments passed into the second and third parameters will represent time period criteria pertaining to the time period over which the relevant stock market data was captured in the interests of keeping this example simple and in the interests of time we are not going to include any code within this Constructor let's simply comment that code would go here for retrieving data from a remote server so let's use our imaginations and say that an i o bound asynchronous HTTP request is made to a web API component to download the relevant raw stock market data within this Constructor this data will be used to calculate relevant technical indicator information so that the user can glean meaningful information from the downloaded raw stock market related data so let's create a few methods the first four methods won't be all that computationally intensive the first four methods will be responsible for getting the daily opening closing high and low prices for the relevant stock we'll then include the more computationally intensive methods in this class I.E the methods used for calculating the relevant technical indicator information for example the stochastics fast moving average slow moving average Etc so the first method will be responsible for performing an operation to get the daily opening prices for the relevant stock from the raw data that is retrieved within the Constructor so this method is appropriately named get opening prices so The Returned values for all of these methods defined within this class will be an array of values of type decimal this method will return an array of decimal values representing the opening prices for the relevant stock so in each of the methods we'll create for this class we'll write the method's name and the thread ID representing the thread on which the method will run to the console screen we are going to run multiple methods in this class on multiple threads concurrently so let's write code to Output a narrative to the screen which will serve as a substitute for presenting the actual data that would be required in a real world application foreign to represent the duration of time the operation performed by the relevant method could take let's make the thread on which the method will run sleep for a specified amount of time so for this method which won't require much computation we'll make the threat of execution sleep for a thousand milliseconds which is one second and then let's just return an empty decimal array the data in this example is not important in this example we want to focus on the asynchronous principles rather than the real world trading platform example that this code represents okay and the other methods can be implemented in much the same way let's copy this method and let's paste it eight times then let's modify the code appropriately for each method so the next method is named get closing prices and is responsible for retrieving the daily closing prices of the relevant stock from the raw downloaded stock market data let's say it runs for a thousand milliseconds the next method is named get price highs this method is responsible for getting the daily highs for the relevant stock this operation also runs for a thousand milliseconds the next method is named get price lows this method is responsible for getting the daily lows for the relevant stock let's say this method runs for a thousand milliseconds so all of the methods that we have added so far run for a thousand milliseconds now we are getting to the methods that are more computationally intensive this method is named calculate stochastics this method is responsible for calculating technical indicator information to help a Trader decide whether a stock is overbought or oversold which ultimately AIDS the trader with the decision to buy or sell a quantity of a particular stock at the current stock price so let's say that this may be a particularly computationally intensive operation so let's say this operation takes 10 seconds to complete so let's pass in an argument of 10 000 milliseconds to the thread.sleep method the next method is named calculate fast moving average let's say that this operation is also computationally intensive so let's put the relevant thread to sleep for six seconds the next method is named calculate slow moving average let's put the relevant thread to sleep for 7 Seconds the next method is named calculate upper bound Bollinger band the next method is named calculate lower bound Bollinger band let's put the relevant thread to sleep for 5 seconds let's put the thread on which this method runs to sleep for five seconds the Bollinger Bands can also be used by Traders to ascertain whether the relevant stock is overbought or oversold which ultimately AIDS the Trader's decision to buy or sell a quantity of the relevant stock so you can see that the last five methods in this class could potentially be computationally intensive as these methods perform the operations of calculating technical indicator information from potentially large amounts of raw stock market data so let's go to the main method where we'll write code to call the methods that we have just created in our stock market technical analysis data class so let's first route to the console screen that the main method is being called in this output to the screen let's include the ID of the thread on which the main method will run we can get the thread ID from the thread.current thread dot managed thread ID property and we also want to include the thread name which of course is the main method so let's first demonstrate running the first four methods in the stock market technical analysis data class synchronously so that we can later run these methods asynchronously and then compare the performance difference so let's instantiate a new object from our stock market technical analysis data user-defined type let's say we want to download raw stock market data relating to the fictional stock represented by the symbol of stkza for data captured between the dates first of January 2010 and 1st of January 2020 so we want the specified stock market data for a particular stock captured over a specified 10-year period let's write code to run these methods synchronously so let's call the get opening prices method then the get closing prices method then the get price highs method and lastly the get price lows method so in order to see how long it takes for all four methods to complete let's capture and store the current date time value captured before we call the relevant for methods then let's subtract the date time value captured before the four methods are run from the date time value captured after our four methods have completed we are doing this so that we can see how many seconds have elapsed between the time we started to run our four methods and the time the operations carried out within these methods completed so each of these methods have been coded to take one thousand milliseconds or one second to complete let's add a method that denotes adding the relevant data to the stock chart that will be displayed to the trader let's name this method display data on chart to keep things simple we can simply write a message to the screen representing that this method has displayed the chart with all the requested data including relevant technical indicator information to the trader so let's run the code and we can see from the results that all of these methods are running synchronously on the main thread the thread ID of all of these methods is one we can see that each method ran consecutively we can see this because each of the four methods ran for one second and a total of four seconds was taken for all four methods to complete so now let's run these methods asynchronously using the task.run method so let's create a generic list to store the generic tasks that accept an array of decimals as the generic argument remember each of our methods within the stock market technical analysis data class return an array of decimal values let's ensure that we include the relevant directives so we need to include the system.threading.tasks directive and we also need to include the system.collections.genericdirective to be explicit let's first create our generic task objects and appropriately encapsulate the four method calls and note that the generic argument for each of the generic task objects is an array of decimal values because each of the relevant methods that the task objects encapsulate returns an array of decimal values foreign thank you right let's write the code to add each of the methods encapsulated within the task objects to our list now we can use the task.weight all method to block the main thread until all the tasks have completed so all of our tasks will run in parallel on background threads and the main thread will be blocked by the task.weight all method until all four methods have completed for more information on the task.weight all method please navigate to this URL so we need to pass our list of tasks to the task.weight or method but the task.waitol method expects an array so let's use the two array method to explicitly cast our list of generic task objects to an array of generic task objects so at this point in the code I.E after the task.weight or method call we know that all of our tasks have completed so we can get the results of each of our tasks like this great let's run the code if we look at the output we can see that the threads on which each of these methods ran have different thread IDs behind the scenes our code has run these methods on different threads when we ran these methods synchronously these methods ran consecutively and ran on one thread the main thread so I've noticed there's a little problem with the text output it says one seconds and should say one second so let's add a ternary operator to our code so that when one second has elapsed our code outputs one second rather than one seconds foreign we only want to Output seconds if the time that is elapsed is greater than one second let's run the code to check our fix great so let's write code to run all nine methods synchronously and after this we'll run all nine of these same methods asynchronously so we'll now be running some of the more computationally intensive methods within our stock market technical analysis data class in this demonstration foreign let's run the code and you can see that there is a significant time lag when running this code synchronously before all our methods complete and output is presented to the screen yeah let's write the code to run our methods asynchronously using the task.run method foreign thank you right let's run the code you can see by the thread IDs outputted to the screen that our methods are not running on the main thread and are running concurrently on background threads so in this video we have covered the basics of running multiple CPU bound operations asynchronously in this video series on asynchronous programming in c-sharp we have covered the basics of how we can improve performance of our applications through asynchronous programming when encountering either of the two types of blocking operations namely i o bound operations and CPU bound operations in the next video we'll look at the best practices and caveats of which we must be cognizant when running i o bound and CPU bound operations asynchronously for more content like this and much more please consider subscribing and please ring the bell so that you'll be notified of future content released from this channel if you feel you've gained value from viewing this video please smash the like button it will be greatly appreciated please feel free to share any of the videos created by this Channel with anyone you feel May benefit from their content I love reading your comments so please feel free to share your thoughts with me in the comment section all code created in these videos can be downloaded from GitHub please see below in the description links to the appropriate GitHub repositories [Music] hi and welcome to the third part of a tutorial on asynchronous programming using the c-sharp programming language this video is also the third part of the sixth tutorial in an advanced c-sharp course in the first and second parts of this video series we looked at how to apply asynchronous code so as to alleviate the negative effects of blocking operations on an application's ux user experience certain long-running operations performed by our applications can be the source of poor performance of our applications for example long-running operations perform from WPF uwp or xamarin applications can cause the UI user interface to be periodically unresponsive this can be frustrating for the user of our applications the user will have a sub-optimal user experience C sharp provides us as developers with appropriate tools to handle these long-running operations asynchronously with relative ease so let's discuss the difference between i o bound operations and CPU bound operations and this will set us up for later when we create a code example to help us understand best practices when applying asynchronous code to handle i o bound or CPU bound operations so in this video series we have already discussed that the two kinds of CPU blocking operations are CPU bound operations and I O bound operations CPU bound operations operations that perform computations that need to be handled by the CPU for example mathematical operations encryption decryption operations Graphics related operations Financial calculations Etc basically computational operations i o bound operations or operations that are delegated to the i o subsystem to perform tasks such as writing to a hard disk drive engaging the i o subsystem to perform requests across the network file handling operations Etc we discussed that I O bound operations are more commonly encountered than CPU bound operations io-bound operations are also generally a lot slower than CPU bound operations so this video is about best practices when applying asynchronous code in our applications please view the first and second parts of this video series on asynchronous programming for a foundational understanding of i o bound operations and CPU bound operations in the context of asynchronous programming in c-sharp the recommended coding methodology provided by Microsoft in the c-sharp language to create asynchronous behavior in our applications is known as the task-based asynchronous pattern tap over the last two videos in this series we have discussed why we should Implement asynchronous code the simple answer is to improve the performance of our applications in this video Let's clarify the best practices when applying writing code to run the relevant code asynchronously let's start with i o bound operations as we have discussed io-bound operations refer to operations like for example file handling operations making requests across a network writing data to a database reading data from a database Etc operations that Engage The i o subsystem we can handle io-bound operations asynchronously both on the client side for example in WPF uwp winforms or xamarin applications we can also handle i o bound operations asynchronously on the server side and for example web API or asp.net MVC applications I have bound operations can be handled using async await in simple terms an asynchronous method that returns a task object can be preceded with the await operator which means we can run the operation asynchronously using async await so for example for a.net client application a button is clicked within the button-click event handler method an asynchronous method is invoked so the asynchronous method is invoked on the UI thread this means that immediately after the asynchronous method is invoked the UI thread is free to be utilized to process other operations the user interface UI does not freeze while the asynchronous method is running the user is able to for example click other buttons and invoke other operations that can be invoked on the UI thread when an asynchronous method is called to perform the relevant i o bound operation the task is immediately delegated to the i o subsystem and instead of blocking the CPU as would be the case if we were running the i o bound operation synchronously the async modifier and await operator instruct the.net runtime to ensure that the CPU is not blocked during the running of the i o bound operation this means that other operations can utilize the CPU even while the i o bound operation is running very briefly what is happening is that when the.net runtime encounters the await operator as discussed the thread on which the operation is invoked on the client this would be the UI thread for example is immediately released so at this time code in the relevant method is suspended I.E the lines of code that follow the line of code that contains the await operator and the relevant method will not be executed until the asynchronous i o bound operation completes while the asynchronous i o bound operation is running however the UI thread can be used to process other operations for example invoked from clicking another button on the UI But A promise is returned to the line of code containing the await operator is made so when the relevant asynchronous operation completes the dotnet runtime returns to the line of code containing the await operator returns a value if required and continues to execute the lines of code from that point in the relevant method so the key point of this explanation is that unlike for CPU bound operations i o bound operations generally don't require additional background threads in this example the.net runtime is delegating the i o bound operation to the i o subsystem and not to a new thread required from the thread pool so I think before we continue let's ensure that we have a clear understanding of what is meant by the following terms thread and thread pool let's start with the term thread a thread in computer science is short for a thread of execution threads are a way for a program to divide itself into two or more simultaneously or pseudo-simultaneously running tasks thread pool a thread pull is a group of pre-instantiated idle threads which stand ready to be given work so a thread pool is created so that threads are readily available to a program which means when a program requires a thread the program can acquire the thread from the thread pool rather than incur the overhead of instantiating a new thread so let's go back to the example demonstrated in the second part of this video series where the task.run method was used to run CPU bound operations we demonstrated how each method that was run through the implementation of the task.run method was run on its own dedicated background thread so each time the task.run method is invoked a new thread is taken from the thread pool and used to run the relevant CPU bound operation so this resulted in the methods that encapsulate the CPU bound operations running concurrently I.E asynchronously rather than running one after the other I.E synchronously if you haven't yet viewed the second part of this video series please view this video for a foundational understanding of running multiple CPU bound operations concurrently on multiple background threads so the key takeaway here is that when an i o bound operation is run using the async modifier and the await operator a background thread is not required to handle the operation the operation is delegated by the.net runtime to the i o subsystem when a CPU bound operation is run using the task.run method a background thread is used to run the operation in the background concurrently with the main thread of execution so now with a foundational understanding of the differences of how i o bound and CPU bound operations are handled asynchronously let's look at Best Practices regarding implementing each of these types of operations asynchronously so with running i o bound operations asynchronously there's less to be concerned about simply because of the way the i o bound operations are handled under the hood i o bound operations can be delegated to the i o subsystem and the need to use additional background threads is not necessary with running CPU bound operations asynchronously under the hood the.net runtime employs additional background threads to run the CPU bound operations this for example means that multiple tasks can run on the additional background threads concurrently there may be times where using multiple threads is undesirable and may not result in the desired performance benefit there are times when running multiple threads to perform tasks in parallel may result in an overall poorer performance an example of this is running CPU bound operations from within server-side code for example code implemented for asp.net MVC applications or code implemented for web API components we'll discuss why CPU bound operations should be run synchronously under these scenarios a bit later in this video so let's create a code example to help us understand best practices when confronted with issues relating to asynchronous programming in c-sharp the theme of this client application will be the same as the theme we used in the previous video in this series I.E a financial trading platform so in the last video we created a console application to get a general idea of running CPU bound operations in this video Let's create a new blank uwp project uwp stands for universal windows platform let's name this project Financial trading platform uwp thank you let's set up a basic UI user interface let's drag a button onto the designer surface let's enlarge this button a bit foreign TN fast local operation let's label this button fast local operation let's drag another button onto the designer's surface just below the button we have just added let's name this button BTN CPU bound operations let's label this button CPU bound operations and lastly let's drag a list view control onto the designer surface and position this control to the right of our buttons like this foreign let's name this list view control lvw output so before we add code directly to this file let's add another project to the solution we want our code to be reusable across both server-side and client-side projects so let's create a standard Library project to our solution and let's name this project stock market component let's add a reference to the stock market component standard Library project from our uwp client project foreign let's delete the class file that has been generated in our standard Library project and let's add a class named stock market data to our project let's add a method named get data async this method represents retrieving relevant stock market data from a server so it is an i o bound operation the method will return a string to the calling client code so let's include the async modifier in the method definition as well as a generic task type that accepts a string as the data type argument notice that we have included the async suffix in our method name this lets the developer know that this is code that should be called asynchronously so when the calling client code writes code to call this method the developer should include the await operator preceding the method call as well as include the async modifier in the method definition of the method where the relevant async call resides so in the interests of time we'll simply include placeholder code for this method so let's use the task.delay method to represent the time that the work could take to carry out our relevant i o bound task so let's say this process takes 5 seconds so let's pass 5000 milliseconds to the task.delay method let's then simply return a string value representing the stock market data that has been retrieved from the remote server so let's simply return the literal text stock market data from this method we must also include the await operator preceding our call to the task.delay method let's add a new class and let's name this class stock market data analysis so let's add a Constructor that contains a parameter named data which will represent the downloaded stock market data for the purposes of this example we don't need to include any code within the Constructor so very much like the code example in the previous video of this video series let's include methods that calculate the technical indicators that the user of our application can use to Aid the user's decision to buy or sell a quantity of a particular stock the technical indicators that we'll refer to in this example will be the fast moving average the slow moving average stochastics and Bollinger Bands if you are not familiar with these terms don't worry the only thing that you need to know to follow along with this example is that calculating the data for these Financial trading related technical indicators are CPU intensive they are CPU bound operations this is why I've chosen these technical indicators for this example IE to serve as intensive long-running CPU bound operations so let's include a method to calculate the fast moving average so for these methods that represent CPU bound operations we can simply put the current thread to sleep for a specified amount of time representing the time that the relevant operation may take to complete so for this method let's put the thread to sleep for six seconds then for the purposes of this demonstration let's simply return the method name and the thread ID to the calling code foreign let's duplicate this method three times these additional three methods represent the calculation of other technical indicators so we can maintain the general structure of the methods that we have just created as they are and simply change the method names and the time durations that represent the time the method takes to complete please note that the time durations that are being specified here are completely arbitrary and have been chosen only for demonstration purposes so this method represents calculating the slow moving average let's name this method calculate slow moving average let's put the relevant thread to sleep for seven seconds this method represents calculating the stochastics let's name this method calculate stochastics let's put the relevant thread to sleep for 10 seconds this method represents calculating the Bollinger Bands let's name this method calculate Bollinger Bands let's put the relevant thread to sleep for five seconds great so let's say that we now have a reusable standard Library component for calculating stock market technical indicator information completed so just to confirm that we have already referenced this reusable component from our uwp client application great so let's add some code to add the output of our methods to our list view control that we named lvw output so let's create a private method named add list item so you're of course welcome to follow me as I create the code for this method or you can of course copy the code from GitHub a link to the relevant GitHub repository is available Below in the description great so let's include code within our button click event handlers to create a button click event handler definition we can simply go to our designer surface and double click on the relevant button like this so we are first going to create code for the fast local operation foreign so let's create the button click event handling method definition for the method that will execute our CPU bound operations these CPU bound operations are encapsulated within the methods in our stock market data analysis class that reside in our standard Library project let's ensure that we have a directive to the stock market component namespace so let's instantiate an object from our stock market data analysis class which resides in our stock market component standard Library project for now let's simply pass in the literal Text data to the Constructor of the stock market data analysis class to represent the raw stock market data downloaded from a remote server so let's write code first to run all of these CPU bound operations in parallel to one another in much the same way as we demonstrated in the code example in the previous part of this video series so firstly let's create a list of generic task objects that accept the string data type as their data type arguments so we know that the task.run method returns a task object or generic task object the methods we wish to call all return strings so each item in the relevant list must be strongly typed with a generic task object that accepts the string data type as an argument right so let's add the tasks we wish to run to our list like this then we can call the task.weight all method and in a bit I'll explain why the task.weight or method is not the best method to call in this context foreign the code following the task.weight all method we know that the relevant methods that have run asynchronously have completed so we can add The Returned values from our methods to our lvw output list view control let's write the code to do this right let's run the code so now when I press the button marked CPU bound operations notice that our UI is unresponsive when we try to perform any other operations so I'm attempting to click the button marked fast local operation the button cannot be clicked because the screen is frozen and therefore the output from this action is not presented to the screen in our list view component the UI is unresponsive when I click the button labeled fast local operation because the UI thread is blocked we have written our code to run a batch of methods asynchronously but we have also written code to block the UI thread while our CPU bound operations are running the weight all method blocks the UI thread until all the relevant tasks have completed so even though the CPU bound operations like for example calculate stochastics calculate fast moving average Etc or running in parallel to one another on background threads which will give us a performance Advantage the UI thread is being blocked while the CPU bound operations are running this is not ideal so we can solve this issue because we can in fact use the await operator when running a batch of CPU bound operations we can achieve this by using the when all method instead of using the UI blocking weight all method for running a batch of CPU bound operations on background threads so let's replace the weight all method with the when all method for more information on the when all method please navigate to this URL so please note that the weight all method does not return a task object or generic task object so this means we cannot call this method using async await the weight all method blocks the UI thread until the tasks within the relevant batch have completed the tasks will be run concurrently on separate background threads but the UI thread will be blocked while the tasks are running the when all method however does return a task object or generic task object this means we can call the when all method using async await which means that we can call the when or method to run our tasks concurrently without blocking the UI thread the UI will still be responsive even while we are running a batch of CPU bound operations when we are using the when all method so let's proceed our call to the win or method with the await operator like this we of course need to also include the async modifier in the relevant button click event handler method signature like this let's run the code let's click the button marked CPU bound operations and now when we run the code the UI thread is not blocked and we are able to perform the fast local operation while the CPU bound operations are running in the background we can perform other operations concurrently while the relevant CPU bound operations are running so the task.run method returns a task object or generic task object this means we can use the await operator when we call a CPU bound operation in this way so to prove this rather than calling a batch of CPU bound operations as we are doing here let's run just one of the CPU bound operations using the task.run method so let's run the calculate stochastics method using the task.run method so we can call this method on a background thread asynchronously like this let's run the code let's click the CPU bound operations button and you can see that while the calculate stochastics method is running we are able to click the fast local operation button the fast local operation button can run concurrently with the operation performed by the calculate stochastics method and as we have already proven we can also run a batch of CPU bound operations on background threads without blocking the UI thread using the when all method so let's change the code back to the way it was so that we can call a batch of CPU bound operations using task.run async await and win all then we could reuse this functionality because we have written our CPU bound operations in a reusable Library component this brings us to an important best practice when implementing asynchronous code for CPU bound operations the developer should never include the task.run method within reusable components always let the developer decide whether to run an operation synchronously or asynchronously so the consumer of the component should always have the choice to run an operation contained within for example a library component synchronously or asynchronously in our example we have chosen to run our operations encapsulated within the stock market data analysis component project asynchronously but we could have chosen to run them synchronously we have proven in our demonstration that running the CPU bound operations asynchronously gives us a huge performance Advantage we did however have the choice to run these operations synchronously or asynchronously because the operations are not implemented to run asynchronously within any of the methods of the component itself I.E we have not implemented the task.run method within the stock market data analysis component project so in the stock market data class we have written an i o bound operation that is responsible for downloading the raw stock market data from a remote server this is different to a CPU bound operation because it engages the i o subsystem and not the thread pool to acquire a background thread so let's write code to run this i o bound operation in order to download the relevant raw stock market Data before calculations are performed from the raw stock market data so we could invoke the i o bound method lazily like this so let's create a member variable named underscore data then within the relevant button click event handler we can check to see if the underscore data variable is null if it is null we can then run the i o bound operation if the underscore data variable is not null then it means we have the data and can pass it into the stock market data analysis classes Constructor when instantiating the relevant object it is best to include the task.run method close to the relevant event handler method as we have done here we have control over whether we want to run these operations using the task.run method on background threads or run them synchronously so calling the task.run method directly from the relevant event handler method like for example a button-click event handler is a best practice another best practice is that if the relevant methods code doesn't need to run on the original thread once the CPU bound operations have completed then we can in fact gain a bit of a performance boost by not returning to the main thread the rule of thumb here is don't run code on the main UI thread unless you have to so we can achieve this performance boost by using the configure await method so the when all method returns a task object which implements the configure await method this means we can call the configure await method like this notice we are passing in false as the parameter to this method we are saying that after the calculations are performed by the CPU bound operations don't return to the main thread so for example a context where this would be appropriate would be once the calculations are completed we want to save the calculated data to a file so in this scenario we don't want to display the data on for example a stock market chart we only want to save the data locally in this context there is no reason to return to the main thread however in a context where we need to display the information on a chart we of course would need to return to the main thread the last best practice I would like to include in this video is that we should avoid including the task.run method within methods implemented in server-side components if for example we implemented our trading platform calculation functionality as a software as a service application for the purpose of providing calculated technical indicator information to web-based client trading platforms we should not implement the CPU bound operations using the task.run method on the surface it may seem like this would give us a performance Advantage but in reality this puts an unnecessary strain on server resources and ultimately can adversely affect performance the reason for this is that with a server-side component say for example implemented as an asp.net web API component you may have thousands of HTTP requests coming in to the relevant web API component each HTTP request requires a thread from the server's thread pool if the code within the relevant server-side method is coded to run four operations asynchronously through the use of the task.run method then your web API component needs to acquire an additional four threads to carry out the instructions implemented in the relevant method this could cause an unacceptably high use of server resources which could adversely affect the overall performance of the relevant server and ultimately negatively impact the user's experience with the relevant application so the moral of this story is avoid running additional background threads on the server side rather run CPU bound operations synchronously on the server side you can still ensure that the client-side UI is responsive by calling the server side code using async await remember an HTTP request from the client's perspective is an i o bound operation note that running i o bound operations on the server is different to running CPU bound operations on the server an example would be downloading the raw stock market data from the server perhaps the server-side code simply retrieves the raw stock market data from a database before returning the relevant data to the client this i o bound operation can be written on the server using async await the i o bound code does not require additional threads and therefore additional server-side resources when a client request is made to run the method responsible for running the relevant i o bound operation on the server the thread used for processing the request can be released to handle other requests while the relevant i o bound operation is being performed CPU bound operations that are invoked using task.run will require additional threads which means additional server resources will be required in summary when it comes to best practices in terms of asynchronous programming in c-sharp know the nature of your asynchronous code ask the question is the operation CPU bound or i o bound and then apply the relevant asynchronous code appropriately avoid writing CPU bound operations within reusable Library components using the task.run method [Music] let the consumer of the library component choose whether to run the CPU bound operations synchronously or asynchronously methods that run i o bound operations asynchronously included within reusable Library components should include the async suffix as part of the relevant method's name this will let the consumer of your library know that the relevant method should be run asynchronously using async await on the client side run CPU bound operations close to the relevant UI event handler method for example use the task.run method directly within the relevant button click event handler method if for example a button-click event handler method needs to perform a CPU bound operation asynchronously on a background thread and subsequently code within that method does not require a return to the UI thread explicitly let the.net runtime know that it is unnecessary to return to the UI thread once the CPU bound operation has completed by appropriately calling the configure await method this can result in a performance boost avoid running CPU bound operations on the server side using the task.run method these operations require additional threads which can result in a strain on server-side resources and the issue will be compounded if the server is handling hundreds or thousands of HTTP requests running i o bound operations for example retrieving information from a web API component reading data from a database or routing data to a database on the server side using async await it's good practice because the main thread of execution is free to handle other client requests while the relevant i o bound operation is running so in this video we covered how to implement best practices in our code when running code asynchronously in C sharp for more content on advanced c-sharp concepts and much more please consider subscribing and please ring the bell so that you'll be notified of future videos released from this channel if you feel you've gained value from viewing this video please smash the like button it will be greatly appreciated please feel free to share any of the videos created by this Channel with anyone you feel May benefit from their content I love reading your comments so please feel free to share your thoughts with me in the comments section all code created in these videos can be downloaded from GitHub please see below in the description links to the appropriate GitHub repository [Music] hi and welcome to the fourth and final video in a video series on asynchronous programming in c sharp this video is also part of the sixth tutorial in an advanced c-sharp course this video is a continuation of the last three videos in this video series on asynchronous programming so please view each of the preceding videos in this video series before viewing this video [Music] in this video we are going to look at how to use a cancellation token Source object to explicitly cancel an asynchronous task or many asynchronous tasks encode before the relevant tasks or tasks have completed using one cancellation token Source object for more content on advanced c-sharp concepts and much more please consider subscribing and please ring the bell so that you'll be notified of future content released from this channel right so to gain an understanding of how we are able to implement code to cancel one asynchronous operation or multiple asynchronous operations using one cancellation token Source object let's look at a practical code example so I'm going to base this code example on an example included in the Microsoft Docs so please navigate to this URL a link to this URL has been included Below in the description you can see that this webpage is entitled cancel a list of tasks in Brackets C sharp so let's first look at the prerequisites section of this document I want to draw your attention to the first prerequisite so this tutorial requires the following dotnet 5 SDK I'm actually not going to install the.net 5 SDK on my windows platform at this time and we'll be creating this example using the.net core version 3.1 runtime we are able to run this example using the.net core version 3.1 runtime but we will need to make a small modification to the code to get this working if you do decide to install the.net 5 SDK know that the version available at the time of writing this tutorial is not yet the official release it is an RC release which stands for recommended candidate so if you install Net 5 SDK I recommend reading all Associated content that can be found at this URL that we can navigate to when we click the link here marked dot Net 5 or later SDK this content can guide us in for example which version of Visual Studio should be installed to support the current RC version of.net 5. I also recommend reading this blog post posted by Richard Lander this blog post can be found at this URL for a foundational understanding of.net 5 I recommend viewing a video created by this channel which can be found at this URL as always I have included all relevant links Below in the description I'll demonstrate how we are able to implement and run this code example so even if you decide not to install.net 5 SDK at this time and your latest version of the.net runtime is.net core version 3.1 you're still able to follow along with the implementation of this example to enable running this code using the.net core 3.1 runtime we only need to apply one simple code modification we'll apply this modification when appropriate let's look at the first paragraph on this webpage in the first paragraph on this webpage it states you can cancel an asynchronous console application if you don't want to wait for it to finish by following the example in this topic you can add a cancellation to an application that downloads the contents of a list of websites you can cancel many tasks by associating the cancellation token Source instance with each task if you select the enter key you cancel all tasks that aren't yet complete so we are going to base our practical code example on the example here provided in this webpage in the Microsoft Docs however we are going to implement our code example as a uwp universal windows platform project instead of how it is implemented in this Microsoft example as a net core console application we are going to copy aspects of the code provided in the Microsoft code example over to our code editor in a step-by-step fashion so let's create a uwp project [Music] and let's name our project can cancel download async operations uwp let's set up a basic UI user interface so let's start by dragging a button onto our designer surface let's name this button BTN cancel download and let's label this button cancel download let's drag another button onto the designer surface just below the button we have just added let's name this button BTN download content let's label this button download content let's drag a list view control onto the designer surface and position it so that the contents of the list view control will appear to the right of our buttons let's name this list view control lvw output so let's access the main page.examl.cs file to add the relevant functionality for our UI firstly let's ensure that we include all the relevant using directives let's copy them from the relevant section of the relevant Microsoft web page and paste them into our code editor like this okay let's then copy and paste the relevant Fields like this these fields contain an object reference variable of type cancellation token source that will be used to cancel the relevant asynchronous tasks a collection of URLs of type I enumerable that will store the addresses of the web pages that will be downloaded by the relevant asynchronous operations and an object reference variable of type HTTP client that will handle the connection to the relevant web pages and also handle the download functionality so in our application these fields don't need to be static so let's remove the static keywords let's read the explanation provided under the relevant code fragment containing the fields we have just copied the cancellation token source is used to Signal a requested cancellation to a cancellation token the HTTP client exposes the ability to send HTTP requests and receive HTTP responses the S underscore URL list holds all the URLs that the application plans to process so the next section of the Microsoft web page there's an explanation of the code within the entry point of the application I.E the main method as discussed the Microsoft code example is based on the.net core console project template we are basing our application on the uwp universal windows platform project template so our code implementation will be slightly different so the main difference between our code and the Microsoft example is that the Microsoft example is implemented so that when a user presses the enter key this action will trigger the cancellation of the relevant operations I.E the operations responsible for downloading the contents of a collection of web pages the uwp project template makes our code implementation simpler because we can leverage a button-click event handler for this purpose so in this Microsoft example the tasks responsible for downloading the content and outputting the relevant information about the content are invoked through a call to the method named sum page sizes async the cancellation functionality is handled in the code above this method call the method is implemented through a Lambda expression here code is implemented here using the when any method the when any method basically accepts an array of task objects so the sum page sizes async method returns a task and the relevant Lambda expression responsible for the cancellation functionality is run using the task.run method which also returns a task object then an array containing a task object encapsulating the cancellation operation as discussed this is implemented as an asynchronous method in the form of a Lambda expression and the download operation which is implemented as a named method are passed into the when any method the task dot when any method will complete when any one of the operations passed within the relevant array argument completes this means that if the user presses the enter key before the download operation IE which is invoked by the call to the sum page sizes async method completes this will effectively cancel the asynchronous web page download operations and Associated functionality for example summing up the number of bytes downloaded Etc so we use the when all method in the previous video which allowed us to run a collection of tasks in parallel without blocking the main thread the when any method is similar but the differences that the when all method completes when all the relevant operations have completed the when any method completes when any one of the relevant operations have completed like the when all method the when any method does not block the main thread so this means that in the context of the Microsoft example here if the user presses the enter key before the operations invoked by the sum page sizes async method complete this will result in the downloading operations being canceled the cancellation operation will complete before the download operations complete resulting in the download operations being canceled so we are going to implement similar code within our example the differences that we'll Implement a cancellation button to enable the user to cancel the download operations by pressing the cancellation button rather than implementing code to allow the user to press the enter key for this purpose with our uwp project we have the benefit of a rich user interface so let's go to our code behind class I.E the mainpage.xaml.cis file and write a private method that will encapsulate the functionality to add a list item to our list view control I.E the control we have named lvw output we have already written a private method encapsulating this functionality in our previous example so let's navigate to the relevant GitHub repository and copy this private method this URL has been included Below in the description so here we can see the relevant method named add list item let's copy this method to our clipboards and appropriately paste this method within our main page.xaml.cs file so we can now write the codes to handle the button click events let's start with the download functionality first let's create two private methods that are responsible for downloading the relevant content calculating the size of the relevant content and outputting Status information to the user regarding the relevant downloaded content so in the Microsoft docs webpage let's look at the section entitled create the asynchronous some pages sizes method let's copy this method and appropriately paste the method within our mainpage.xaml.cs file in our example this method does not need to be static so let's remove the static keyword from the method definition of the sum page sizes async method and let's include the private access modifier within the sum page sizes async methods method definition the next thing we need to modify in our example for the sum page sizes async method is where the code writes text to the console screen our output will be added to the list view control that we named lvw output so let's replace the console.write methods with a call to our private method named add list item we can remove the backslash n character sequences from the relevant text because we don't need a line feed due to the fact that we are adding each item of text as its own item within the list view control let's read the brief description of this method provided within the relevant Microsoft web page the method starts by instantiating the starting of a stopwatch it then Loops through each URL in the S underscore URL list and calls process URL async with each iteration the S underscore CTS dot token is passed into the process URL async method and the code returns a generic task where T result is an integer So within the relevant Microsoft web page let's look at the section entitled add process method so the first line in this section reads adds the following process URL async method below the sum page sizes async method so let's copy the process URL async method to our clipboards like this and appropriately paste it within the main page.xaml dot CS file like this let's remove the static keyword from the process URL async methods method definition let's include the private access modifier within the process URL async methods method definition let's replace the console.write method with the add list item method like this and if you'll remember before we started implementing this example I spoke about one of the prerequisites for creating this code example the prerequisite being the installation of the.net 5 SDK so this is the only line of code that doesn't work if we do not have the.net 5 SDK installed and if we are running this example using the.net core 3.1 runtime so if you're running this project using the.net core 3.1 runtime simply remove the argument named token from the line of code that calls the response.content dot read as byte array async method so let me just say that it is preferable to pass in the token argument to this method but if you don't wish to install the.net 5 SDK at this time we are still able to run The Code by removing the token argument this is not ideal but we are still able to gain an understanding of the cancellation token Source object and how we are able to cancel one or more asynchronous operations using one cancel token Source object let's read the explanation of this method in the relevant Microsoft web page for any given URL the method will use the client instance provided to get the response as a byte array the cancellation token instance is passed into the HTTP client dot get async and HTTP content dot read as byte array async methods the token is used to register for requested cancellation the length is returned after the URL and length is written to the console so obviously where it says the URL and length is written to the console in our example we are instead adding the relevant text to our list view control okay so let's implement the code for the button that invokes the download operations let's go to our designer surface and double click on the button labeled download content let's implement the code that calls the awaitable some page sizes async method to perform the downloading of the relevant content the calculation of the size of the content as well as the outputting of the relevant information about the content to our list view control so in order to call this method asynchronously we need to include the await operator we also need to include the async modifier within the method definition of the relevant button-click event handler let's implement the cancellation functionality let's go to our designer surface and double click on the button marked cancel download within the relevant button click event handler let's implement the cancellation functionality to add the operation we can simply call the cancel method on the relevant cancellation token Source object like this okay let's run the code firstly let's demonstrate what happens when we click the download content button so let's allow the operations to complete so we can see what happens when we don't cancel the operations we can see that the appropriate output is presented to us as each operation completes when the content for a particular web page has been downloaded the web page URL followed by the number of bytes downloaded is presented on our list view control and then once all the operations have completed we are presented with the total number of bytes downloaded as well as the time that has elapsed between the time when we started to download the content and the time that the relevant download operations completed great so let's run the code again let's click the download content button and we are presented with the relevant output in our list view control as expected right let's see what happens when we press the cancel button and a runtime error occurs so in order to handle the cancellation operation appropriately we need to handle a particular type of exception so when the cancel method is called while the asynchronous operations are running an exception of type task canceled exception is thrown so we can simply include our code that calls the sum page sizes async method within try catch code like this and handle the task canceled exception appropriately so we could access the throne exception object to access details about the exception but in this case we only want to Output status information to the user that the operations have been canceled so let's do this let's simply add the literal text download operations canceled so remember we are passing a token object as an argument to the get async method here in the process URL async method the process URL async method is called within a loop from within the sum page sizes async method this token object allows us to trigger a cancellation of all running asynchronous tasks that reference this token object when the cancel method is invoked on the relevant cancellation token Source object an exception of type task canceled exception is thrown and we can appropriately handle this exception in our code right let's run the code so let's click the download content button and we are presented with the relevant output as expected so let's see what happens when we cancel these operations and there we have it the task canceled exception is thrown when the cancel method on the cancellation token Source object is invoked and we are handling the throne exception in our custom way I.E in a way that suits our application so we can see the output text download operations canceled which is an expected result okay so we are also able to automatically cancel the operations after a predefined duration of time so let's say we wanted our download operations to be canceled if they haven't completed within a specific time duration the way we can do this is by calling the cancel after method on the relevant cancellation token Source object we can call this method before the relevant operations are invoked like this we need to pass in the duration of time in milliseconds to the cancel after method this number represents the time elapsed from the moment the relevant operations are invoked so let's specify 3500 milliseconds or three and a half seconds let's run the code and you can see that after three and a half seconds the relevant operations are automatically canceled so you can see how this functionality can be useful when we want to automatically cancel an operation or operations after a specified amount of time great for further information about asynchronous programming in c-sharp I recommend reading relevant content provided in the Microsoft Docs foreign so to summarize in this video series we looked at Microsoft's recommended approach for implementing code to run an operation or multiple operations asynchronously namely the task-based asynchronous pattern we discussed that running certain relatively long-running CPU blocking operations can adversely affect the performance of our applications to alleviate these negative effects on user experience ux we can run these relatively long-running CPU blocking operations asynchronously in order to implement the asynchronous code correctly we first need to know the nature of the operations that we wish to run asynchronously we need to first ask the question is the relevant operation a cpu-bound operation or is the relevant operation an i o bound operation in the first part of this video series we focused on running i o bound operations asynchronously using the async modifier the await operator and the task or generic task object in the second part of this video series we looked at running CPU bound operations asynchronously using the task.run method to run operations on background threads we also looked at the task.weight all method in the third part of this video series we looked at Best Practices when implementing operations in c-sharp to run asynchronously we also looked at the task dot when all method and how it differs from the task.weight all method in this video which is the final part of this video series we looked at how we can provide the user with the ability to cancel one or more running asynchronous operations before the relevant operations have completed using one cancellation token Source object we also demonstrated how we can automate the cancellation of running asynchronous operations after a specified amount of time by calling the cancel after method on the relevant cancellation token Source object I hope you have enjoyed the final video in this video series on asynchronous programming in c sharp the next Topic in this Advanced c-sharp course will be link language integrated query for more content on advanced c-sharp concepts and much more please consider subscribing and please ring the bell so that you'll be notified of future content released from this channel if you feel you've gained value from this video please hit the like button it will be greatly appreciated please feel free to share any videos released from this Channel with anyone you feel May benefit from their content I really enjoy reading your comments so please feel free to share your thoughts with me in the comment section as always the code in this tutorial can be downloaded from GitHub a link to the relevant GitHub repository has been included Below in the description foreign [Music] to the first part of a video series on link this video is also the first part of the seventh tutorial in an advanced c-sharp course later in this tutorial we'll look at a code example to help with our understanding of Link but let's first answer the question what is link link stands for language integrated query link is defined in the Microsoft docs as the name for a set of Technologies based on the integration of query capabilities directly into the c-sharp language link was originally released as a major part of NET Framework 3.5 in 2007 here is a paragraph from the Microsoft docs which provides an excellent overview of what link is language integrated query link is the name for a set of Technologies based on the integration of query capabilities directly into the c-sharp language traditionally queries against data are expressed as simple strings without type checking at compile time or intellisense support furthermore you have to learn a different query language for each type of data source SQL databases XML documents various web services and so on with link a query is a first class language construct just like classes methods events you write queries against strongly typed collections of objects by using language keywords and familiar operators the link family of Technologies provides a consistent query experience for objects link to objects relational databases linked to SQL and XML link to XML note that you can write link queries in c-sharp for SQL Server databases XML documents ado.net datasets and any collection of objects that support the I enumerable interface or the generic I enumerable interface so for example you can perform link queries against collection types like an array generic list generic dictionary generic Q generic stack Etc basically any collection type that implements the I enumerable interface or the generic I enumerable interface link support is also provided by Third parties for many web services and other database implementations you can create custom providers using I queryable custom providers will not be discussed in detail in this video series if you would like to learn more about implementing your own custom provider please navigate to this URL in this video series we'll primarily focus on link to objects and link to entities link to entities provides language integrated query link support that enables developers to write queries Against The Entity framework conceptual model using either Visual Basic or visual c-sharp so Entity framework core is a modern object database mapper for net it supports link queries change tracking updates and schema migrations Entity framework core or EF core can be used to work with many databases including SQL databases on-premises and Azure sqlite MySQL postgres and Azure Cosmos DB in this video series we won't look at the link to data set or link to XML please navigate to this URL for more information on linked dataset and please navigate to this URL for more information on linked to XML to get started with link in this video we'll focus on link to objects so that we can first get a basic idea of what the implementation of Link looks like in code and how it can be used for querying c-sharp collections so in the spirit of cross-platform Development I've decided to demonstrate this code example on my Mac platform using visual studio 2019 for Mac Community Edition if you have a Mac platform and wish to follow along on your Mac and you don't yet have Visual Studio installed you are able to download and install Visual Studio Community Edition 2019 free of charge from this location all links mentioned in this video are available Below in the description if you are using a Windows OS please don't let the fact that I'm using a Mac platform put you off following along with this tutorial in terms of the code example that we'll create in this video the coding experience using visual studio for Mac is almost exactly the same as the coding experience using visual Studio for Windows so this should not be a barrier for a learner to follow along with this demonstration if you haven't yet installed Visual Studio 2019 on your windows platform please view a video created by this channel which provides a guide to installing Visual Studio 2019 Community Edition free of charge so firstly let's create a.net core console application let's name this project the pretend company application before we write calling client code in the main method we are going to add two standard Library projects let's first add a standard Library project named TCP data let's then add another standard Library project named TCP extensions so let's now go to our project that we named TCP data let's delete the class that has been automatically generated for the TCP data project let's add a new class named employee let's add six Auto implemented properties to the employee class ID as int first name as string last name as string annual salary as decimal is manager as Boolean and lastly Department ID as int let's add another class to the TCP data project let's name this class Department let's add three Auto implemented properties to our department class ID as int short name as string and long name as string let's add a class named data to our TCP data project let's make this class a static class so let's add two public static methods to the data class let's first create a static method named get employees which returns a generic list strongly typed as employee let's ensure that we include the appropriate using directive for the use of generic list objects at the top of our code editor so let's include a using directive to the system.collections.generic namespace like this let's write the code to add some made up employee records to a generic list that is strongly typed with the user defined type employee foreign foreign let's write code to return the list of employee records to the calling client code let's add another static method and let's name this method get departments this method also returns a generic list object but this generic list object is strongly typed as Department let's write the codes to add some made up Department Records to a generic list that is strongly typed with the user-defined type Department foreign let's write code to return the list of Department Records to the calling client code so as you can see the get employees method returns a list of employee records and the get departments method returns a list of Department Records so in order to gain an understanding for how Link Works let's ensure that we properly understand two fundamental concepts I.E the concept of extension methods and the concept of Lambda expressions so let's go to our TCP extensions project let's delete the class that was auto-generated by Visual Studio when we created the project let's add a class named extension so in order for our extension method to work we must make the extension class a static class so we are going to add a method named filter the idea here is we want a way where we can extend the functionality of any generic list that is strongly typed with any c-sharp data type including user-defined types we can achieve this by creating our own extension method so for example if we want to filter employee records by criteria that we are able to specify through a Lambda expression on a generic list that is strongly typed as the employee we can do this through our filter extension method this will be demonstrated in the calling client code in a bit so how do we create our own custom extension method so I'll first create the method signature for the filter extension method first notice that our method like the class in which it resides must be static which is achieved by including the static keyword in the relevant extension methods method signature so if we look at the first parameter in the filter methods method signature we can see that we are using for this keyword preceding the data type of the first parameter which is a generic list of type t but this keyword in this context indicates to the compiler that the relevant method can be called on an object of the data type of the relevant parameter in this example that is a generic list which contains a type T placeholder as we know from the video series on c-sharp generics a developer is able to pass a data type argument to the parameter of type T which can be any c-sharp data type including user-defined types the data type specified will be chosen depending on the requirement that needs to be met by The Calling client code we'll demonstrate the consumption of client-side code for the filter extension method in a bit so let's look at the second parameter which is of the delegate type func for more information about the funk delegate type please view a video created by this channel on this topic a link to this video is available Below in the description the first data type parameter passed to the funk delegate type represents the first data type of the first parameter of the method referenced by the relevant argument passed into this parameter the last parameter in the funk delegate type definition is the return type of the method referenced by the argument passed into this parameter so the first parameter passed into the funk delegate is of type T and the second parameter is of type bull note that a predicate delegate type can be used to define method definitions for a method that returns a Boolean value so we could replace the func delegate type with a predicate delegate type let's use the funk delegate type but please note that we could also achieve the same end using the predicate delegate type and as you can see this method will return a list of objects of type t to the calling client code so let's complete the logic for this method let's implement the code for the filter method so basically we are looping through the list on which the filter extension method is invoked we are then adding its elements to a new generic list also of type T whether or not we add this list item is based on the Boolean value returned by a method reference passed into the second parameter of the filter method so the relevant method reference is stored in the argument passed to the parameter named funk as you can see the method that the variable named func references accepts an argument of type t so we are passing in each item stored in the calling clients list which is the generic list on which calling client code will invoke the filter extension method if the method that the func variable references returns true the items stored in the iterated list is added to a new list we then return the new list containing the filtered items to the calling client code so this effectively means that the calling client code is able to use our filter method to filter any generic list based on a method created in the calling client code this method created in the calling client code will contain the logic for filtering the relevant generic list a reference to this method will be passed into the second parameter of our filter extension method and must adhere to the method definition represented in the second parameter of the filter method I.E the definition represented in the func delegate type so we are now going to implement the calling client code and you'll see that the method passed into the second parameter of our filter method will be an anonymous method I.E a method that is not named this method will be expressed as a Lambda expression we'll now see how we are able to filter a generic list using our filter extension method through calling client code in the main method of our application right so let's go to the.net core console project and write the calling client code in our main method firstly let's reference our two standard Library projects from our.net core console project so let's right click the dependencies node in the.net core console project and tick TCP data as well as TCP extensions so let's test our filter extension method in a bit I'll further elucidate why it is important to understand extension methods and Lambda expressions with regards to link through the magic of how extension methods work in c-sharp we should be able to call the extension method on any generic list object so let's define a generic list that is strongly typed as the employee user defines type so we have a red squiggly line under our generic list type definition so to fix this we need to include a directive at the top of our code to the system.collections.generic namespace we can see that there is a red squiggly line under the code that strongly types our generic list as the user's defined type employee so to fix this let's include a directive at the top of our code to the TCP data namespace great so through the magic of extension methods we should see the filter method appear in the intellisense drop-down list when we add a DOT after the employee list variable okay so why are we not seeing the filter method appearing in our intellisense drop-down list the reason for this is because we haven't included a using directive to the appropriate namespace so let's include a using directive at the top of our code to the appropriate namespace IE TCP extensions so now if we add a DOT immediately after the employee list variable the magic of extension methods is revealed to us and we can see our filter method in the intellisense drop-down list so note that when we Open brackets to pass in appropriate arguments to the filter method we see that only one parameter is required this parameter was the second parameter we defined for this method so why is the first parameter in the filter method not listed when we open the brackets in this way well the answer to that question is this is how extension methods work the consumer of the code IE the calling client code does not need to pass in the first parameter this is automatically handled behind the scenes as it were by default the first parameter is the object on which the relevant extension method is invoked so in this case the list of employees stored in the employee list variable is passed into the filter method into this parameter automatically so if we look at the filter extension method we can see that this keyword precedes the definition of the first parameter that this keyword in this context is telling the c-sharp compiler that the argument passed into this parameter is the object on which the relevant extension method is invoked so we have access to the argument passed into the first parameter automatically okay so the second parameter accepts a delegate object that points to a method that needs to be created on the calling client so this method that we'll create essentially tells the filter method how we want our list filtered so we are able to Define this method and the calling client code through the use of a Lambda expression a Lambda expression is a concise way to represent an anonymous method if we look at the definition of the relevant delegate parameter we need to define a method that accepts an argument of type T and returns a Boolean value so the c-sharp compiler has enough information to infer that the intended type for type T is employee in this context we are calling the filter extension method on a strongly typed generic list the generic list is strongly typed with the employee user defined type so say we want to filter our employee list based on the value of each relevant employee items is manager property we want to filter the list where we only want to return those employee records where is manager is true so we want to return all the records from our list where the relevant employees are managers so to achieve this we can pass in this Lambda expression here we are telling the filter method how we want our list filtered let's write code to print the results to the console screen right let's run the code okay so we have no data ah we of course need to populate our employee list with data so let's assign the value returned from data.get employees to the employees list variable right let's run the code great and you can see that only the employee records where the relevant is manager property value is set to true or returned to the calling client code great and we can of course inject the converse of this logic into our filter method through the relevant Lambda expression like this so we are now saying we only want to bring back our employees who are not managers let's run the code great and for good measure let's modify our Lambda expression so that the filter method only returns employees that earn less than 50 000 a year great and because we have used generics for our filter method we can call the filter method on a list of various c-sharp types including user-defined types so let's prove this and call our filter extension method on a list of departments foreign let's filter the Departments based on the Department's short name so let's bring back the finance department and the human resources department great let's bring back only those departments with IDs greater than one so the point of this is to show you the flexibility that the combination of extension methods and Lambda Expressions create when writing the calling client code the combination of extension methods and Lambda Expressions not only provide this flexibility but at the same time ensure that the calling client code is clean and concise once we understand how extension methods and Lambda Expressions work they are incredibly powerful tools so how do extension methods and Lambda Expressions work in relation to the topic of this video link language integrated query extension methods and Lambda expressions are fundamental to how link is implemented in C sharp the innumerable class and the queryable class are two static classes that contain extension methods the enumerable class and the queryable class are both members of the system.link namespace so to gain access to the extension methods provided through link we can simply include a using directive to the system.link namespace without including a using directive to the system.link namespace you can see that we are not able to access the where extension method provided by link to perform our filtering operation on a collection that implements the I enumerable interface so let's include the system.link namespace we now have access to Links where extension method so we can now replace our custom filter extension method with the where link extension method like this we don't need to create our own filter extension methods to perform such queries on our data link has got us covered for this foreign link also provides us with a SQL like query syntax so for example if we wanted to produce a query result by joining selected fields from data selected from our collection of employee objects with selected fields or field in this case from data in our collection of Department objects we can use Link query syntax to perform our inner join operation on these two collections of data like this and the link query we want to include the department long name field so that we can have a descriptive name for our department in our results set rather than displaying a result that only contains the department ID which is available in the employee type so we can achieve this result by using the join clause in a link query to perform our inner join on our collection of employee objects with our collection of Department objects we have the department ID property in the employee type so we can join using this department ID property in the employee type to the ID property which is a member of the department type so say we were to write the equivalent query using transact SQL against the SQL Server database that contained an employee table with the same data schema as our employee type and a department table that contains the same schema as our department type the transact SQL query syntax would look something like this we are using an inner join to join data in an employee table with data in a department table we are able to make the join because the employee table contains the department ID which can be joined in our query the ID of the department table so you can see the similarities and syntax between the transact SQL syntax and the link query syntax the link query is dealing with objects encapsulating the employee and Department Records the employee list collection is like the employee table and the department list is like the department table in this particular context we have a select Clause a from clause and a join clause in the Syntax for both the link query and the transact SQL query however the from clause in the link query appears at the beginning of the query and the select clause in the link query appears at the end of the query so there are differences in The Ordering of the Clauses When comparing the syntax of the transact SQL query with the syntax of the relevant link query an advantage of link is that can be leveraged in our c-sharp code to query data in a standardized way that is independent from the format of the underlying data source the data source could be a mongodb database a sqlite database a SQL Server database Etc this will not affect the syntax of our link queries so the object layer provided by link can be used for abstracting our queries of the data from the underlying data source and by using link we also have the added advantage of compile time strong typing and the type checking provided by the c-sharp compiler let me draw your attention to the select clause we are able to return the data as an i enumerable collection of anonymous types we are assigning The Collection returned by the link query to a variable preceded by the VAR keyword beginning with c-sharp version 3 variables that are declared at method scope can have an implicit type VAR through the use of the VAR keyword the c-sharp compiler is able to infer the types included in the collection returned from the query so we are able to return a collection of objects that are of an anonymous type that we have defined directly within the link query Anonymous types provide a convenient way to encapsulate a set of read-only properties into a single object without having to explicitly Define a type first you can see how the use of anonymous types can provide the developer with flexibility and convenience when constructing relatively complex queries foreign foreign note that Microsoft recommends using the query syntax where possible as opposed to using relevant extension methods for the same purpose this is because of the readability Advantage provided in the relevant query syntax there are however times where you'll need to use appropriate extension methods included within the link namespace because some functionality in link does not have a query syntax counterpart for example if we wanted to calculate the average salary for all employees we would need to use the average extension method like this the same applies if we wish to query for the highest salary from a list of employee records we would need to use the max extension method like this this functionality cannot be performed through the use of query syntax but where possible query syntax is preferable due to the code readability advantage that this syntax provides I hope you've enjoyed this video which provides an introduction to link this video was created to help with the understanding of the fundamentals of Link the advantages that link provides and how we are able to implement basic link queries in code link provides us with an integration of query capabilities directly into the c-sharp language it is a very powerful technology that decouples query logic from relevant types of underlying data formats link provides a layer of abstraction that provides the developer with easy to implement Syntax for querying collections of objects the relevant collection types must implement the I queryable or generic I queryable interface or the I enumerable or generic I.E numerable interface note that the I queryable interface inherits from the I enumerable interface and the generic I queryable interface inherits from both the I enumerable interface and the generic I enumerable interface a suite of extension methods and query syntax are made available to c-sharp developers which provide flexibility when constructing powerful readable queries against data encapsulated with an appropriate c-sharp collections this video is a basic introduction to leveraging link in the c-sharp language and the next tutorial we'll delve deeper into the subject matter [Music] hi and welcome to the second part of a video series on link this video is also the second part of the seventh tutorial in an advanced c-sharp course link stands for language integrated query in the first part of this video series we looked at an overview of Link we discussed that link is the name for a set of Technologies based on the integration of query capabilities directly into the c-sharp language in this video we'll demonstrate examples where we'll create link queries using method syntax and subsequently show how we can express the same link query using query syntax as discussed in the previous video in this series query syntax is recommended because the logic within the query syntax is easier to read in this video we'll look at code examples using the following link operators select where join and group join we'll discuss what is meant by Method chaining and demonstrate an example that makes use of method chaining in the context of a link query we'll look at what is meant by deferred execution of Link queries and what is meant by immediate execution of Link queries we'll discuss the inherent advantages of the third execution in the context of Link to further clarify our understanding of deferred execution we'll create a code example where we'll Implement deferred execution for our own custom extension method for an I enumerable type we'll demonstrate how the c-sharp yield keyword is implemented in the relevant code example as part of code to implement deferred execution at the end of the tutorial we'll look at the join operator and the group join operator we'll create code examples to help clarify our understanding of these two link operators in the first part of this video series we discussed that extension methods and Lambda expressions are fundamental to how Link Works we created our own extension method for filtering a generic list that can be strongly typed with any c-sharp type including user-defined types we then demonstrated how a Lambda expression can be created and calling client code which enables the calling client code to determine how the relevant list of data must be filtered the reason we created our own filter extension method was to help us understand the fundamentals of Link Link functionality is encapsulated in two static classes that are members of the system.link namespace these two static classes are named queryable and enumerable these classes mostly contain extension methods as with the previous video in this series I'm going to demonstrate the code examples in this video on my Mac platform if you are using a Windows platform the fact that I'm using visual studio for Mac should not be a barrier to follow along with these code examples the code creation process is almost exactly the same experience when compared to implementing the same code using visual Studio for Windows so let's create a net core console project let's name this project link examples underscore one so to save time let's copy data related code that we created in the previous video of this series from the appropriate GitHub repository so please navigate to this URL in your browser to access the relevant GitHub repository as always all urls referred to in these videos can be accessed through appropriate links included Below in the description so let's copy the data related functionality from this repository to the project we have just created so in your browser window click the directory icon labeled TCP data like this click the class icon labeled employee let's copy the code for the employee class from this page to our clipboards like this and simply paste the contents of the clipboard below the program class in our new project let's also copy the code for the Department class like this to our clipboards and paste the contents of our clipboards below the employee class within our new project let's then copy the code in the data class to our clipboards then paste the contents of our clipboards below the department class in our new project like this so we have some red Squiggy Lines within our data class to fix this let's include a directive to the system.collections dot generic namespace at the top of our code like this we are just creating throwaway code in this video to help us understand the relevant topics discussed in this video so we are not too concerned with code neatness in this video in our main method let's create a strongly typed generic list that is strongly typed with the employee user-defined type let's name our generic list variable employee list let's assign the value returned from the data.get employees method to the variable we have just named employee list this line of code will populate the employee list collection with made up data that was hard-coded in the data class in the previous video of this series let's define a generic list that is strongly typed with our department user-defined type let's name our variable for this list Department list let's assign the value returned from the data.get Departments method to the variable we have just named Department list this will populate the department list collection with made up data that was hard-coded in the data class in the previous video of this series so let's create a link query that makes use of the select link operator in order to use a link operator we of course need to include a using directive to the system.link namespace for this query we want to select everything from the data stored in our employee list collection we can do this by simply invoking the select method on the employee list object like this the select method is an extension method provided to us through link we can shape our data through the use of a Lambda expression like this we discussed Anonymous types in the previous video of this video series so the select operator returns an i enumerable collection of objects the Lambda expression passed into the select extension method provides an instruction on how we wish to shape each item of data within the returned I enumerable collection this is specifically expressed through this Anonymous type Anonymous types provide a convenient way to encapsulate a set of read-only properties into a single object without having to explicitly Define a type first you can see how the use of anonymous types can provide the developer with flexibility and convenience when constructing queries so here we are providing an instruction that we want each item of data in The Returned I enumerable collection to contain a full name property which is a concatenation of the first name and the last name properties of the relevant employee record and a property containing the employee's annual salary so let's write the code to Output the results of this query to the console screen let's see the code in action great so if we want to filter this data we can do this by chaining the where extension method to our select operator like this method chaining is a common Syntax for invoking multiple method calls in C sharp each method returns an object allowing calls to be changed together in a single statement without requiring variables to store the intermediate results so the select operation will return an innumerable collection object we can filter this returned inumerable collection within the same link query by chaining the where extension method to the select extension method the where extension method filters the data stored in the innumerable object returned from the select method through a Lambda expression passed to the where extension method the Lambda expression provides instructions to the where extension method on how the data must be filtered once the data has been filtered through the wear extension method and I enumerable collection of results is assigned to our results variable we are then traversing our results using a for each Loop and displaying each item in the I enumerable collection to the console screen we discussed the VAR keyword which allows for local implicit typing within methods in the previous video of this series please view the previous video in this series for more details so here we are implementing link explicitly using the extension methods provided by link we are using the select operator and the where operator in a link query implemented using method syntax let's run the code great we can execute the same functionality using query syntax so let's comment out the previous code and include a comment to label this code so that we are able to refer to this code later if need be so let's first implement the link query using query syntax without the where clause okay let's run the code great let's implement the link query implemented using query syntax and this time include the where Clause within the link query using query syntax let's run the code excellent and we get exactly the same result when compared to running the query that we implemented using method syntax but we have constructed our link code using link query syntax as opposed to using relevant extension methods the query syntax is more readable and we don't need to chain our extension methods as we did in the previous example where we changed the where extension method to the select extension method let's take a closer look at our query where we used method syntax versus the same query where we used query syntax note that standard query operators in our query syntax are converted into extension Methods at compile time so standard query operators are essentially the same as their counterpart extension methods Microsoft recommends using query syntax as opposed to directly implementing the relevant extension methods where possible as discussed this is due to the readability Advantage inherent in the query syntax there are times when you will need to use extension methods directly where equivalent query syntax is not available we looked at a few examples of this in the previous video of this series for example using aggregate functionality like for example finding the average Min or Max annual salary for a collection of employee records we would need to use the respective average Min or Max extension methods to calculate and return the relevant values the developer is able to execute link queries with deferred execution or immediate execution so let's first understand what is meant by deferred execution the third execution means that the evaluation of an expression is delayed until its value is required this improves performance because only necessary executions are carried out I.E at the point where the relevant value is required let's use our last query example to illustrate this point so when we first assign the value returned by our query to our results variable the query is not executed it is only when we Traverse the items in our results variable that the actual execution takes place I.E with each iteration of the for each Loop an execution is performed whereby the relevant item is evaluated and returned from the collection another advantage of deferred execution is that an update to the relevant data collection will immediately be reflected in the results so for example let's add a record to our employee collection note the salary for this new employee is above 50 000. so this employee should appear within our results let's run the code and you can see that this is proof that the results are evaluated within the for each Loop and the query itself is not executed at the line of code where the relevant query is located the execution of the query is deferred until the results are traversed within the relevant for each Loop to further understand the concept of deferred execution let's create a code example where we'll Implement deferred execution for our own custom extension method for an innumerable type that is strongly typed as the employee user-defined type foreign let's create a static class named innumerable collection extension methods let's create a static method within the static class that we have just created and let's name this method get high salaried employees we discussed extension methods in the previous video for this video series for more information on extension methods please access a link to this video as discussed a link to this video is available Below in the description so let's implement the code for the get high salaried employees extension method like this note the use of the yield keyword you can use a yield return statement to return each element one at a time the sequence returned from an iterator method can be consumed by using a for each statement or link query each iteration of the for each Loop calls the iterator method when a yield return statement is reached in the iterator method the relevant value in the I enumerable collection is returned and the current location in code is retained execution is restarted from that location the next time that the iterator function is called let's go to our main method and Implement a query that calls our extension method on the employee list collection let's copy and paste the code that we have already written to Traverse the results and output the relevant data and let's add another employee records to the employee list collection as we did before let's run the code and you can see that the new employee record is reflected in the results the results are kept up to date due to deferred execution note that the third execution reevaluates on each execution which is known as lazy evaluation the converse of deferred execution is immediate execution immediate execution means the relevant query is executed immediately to execute a query immediately we need to apply an appropriate two conversion method to the query so let's copy the previous code example let's uncomment the relevant code let's change this code so that the query executes immediately we can use the two list conversion method for this purpose we are using query syntax here so in order for us to use the to list conversion method we first need to wrap the relevant query in Brackets add a DOT and then the to list conversion method we are explicitly typecasting the I enumerable value returned from the query to the list type through the implementation of the to list conversion method we are also executing the query immediately let's uncomment the rest of the relevant code for this example and let's run the code you can see that the execution of our query is immediate because this time after we've added a new employee the query has not been evaluated again to include the new employee record in the results this is of course why the new employee does not appear within the results output to the screen this proves that our query has executed immediately at the line of code where the query is located and remember that query syntax does not support two operators so we need to wrap our query in Brackets as we have done here and call whichever two method is appropriate for example to list two array or two dictionary by calling the relevant to method in this case the two list method we are causing our query to execute immediately without the two conversion method the relevant query execution would be deferred until the relevant results are iterated so let's move on to the join operator and then we'll look at the group join operator and highlight the difference between these two join operations in the previous video in this series we looked at the join operator and discussed how we can perform an inner join on two inumerable collections using a link query so here we have two collections that we wish to join in this specific use case we need to include a descriptive Department name in our results displayed to the user we only have a department ID field in our employee type so in order to merge the properties from our employee type with the relevant property from our department type we need to join records of type Department that reside within our department list collection with records of type employee that reside within our employee list collection we can do this by matching the ID field in the department records that reside in the department list collection with the Department ID property of employee records that reside in the employee list collection we can do this through link by using the join operator later we'll demonstrate a join operation but using the group join operator we'll also discuss the differences between the join operator and the group join operator let's look at the relationship between the collection of Department Records with the collection of employee Records Department Records have a one-to-many relationship with employee records a specific Department can have many employees as members a specific employee cannot belong to more than one department at a point in time data collections can also have one-to-one relationships with one another or many too many relationships with one another so in this example we are going to look at how we can use Link to implement a join operation between two collections of records that have a one-to-many relationship with one another I.E one Department to many employees so let's Implement a query that joins the department list collection with the employee list collection where the ID property of the relevant objects of type Department match the department ID property of the relevant objects of type employee so the Syntax for this link query would look like this when we implement the join operation using method syntax so to join Department Records to appropriate employee records we can use the join extension method and invoke the extension method on the department list collection the first argument we need to pass into the join method is the collection on which we want to join the department list collection so we pass in the employee collection object here the second argument is the key from the outer collection the department list collection so the outer join key is the ID property that resides in the department type we can express this argument as a Lambda expression like this the third argument is the inner join key which is the department ID property which is a member of the employee type we can express this argument as a Lambda expression like this so we are joining on the ID property which is a member of the department type with the Department ID property which is a member of the employee type we can define an anonymous type where we are able to shape the data for each item in an i enumerable collection that we want returned from the relevant query here we are defining an anonymous type within our link query that includes the employee full name which is a concatenation of the employee's first name and last name the employee's annual salary as well as the relevant Department objects long name property the long name property will give us a descriptive Department name in our results we are including the department types long name property and the relevant Anonymous type this is the whole point of joining the department list collection with the employee collection so that we are able to include a descriptive Department name within our results we only have the department ID as a member of our employee type so if we only return to results from the employee list and wanted to include Department information we would be restricted to the department ID property which is an integer value and is unlikely to be meaningful to a user thank you let's run the code great but as discussed where it is possible to use Query syntax rather than method Syntax for our link queries we should use Query syntax because the logic expressed and the relevant query is far easier to read so let's write the same query using query syntax as you can see it is far easier to read and it is also similar to query languages with which we may already be familiar for example transact SQL let's Express what a similar query and transact SQL might look like so let's imagine that we have a table in a SQL Server database that could map to our employee type let's say this table has the same name as our employee type let's also imagine that we have a table in the same SQL Server database that contains a table schema that could map to our department type let's say this table has the same name as our department type so the transact SQL would look something like this you can see how the from Clause the join clause and the select Clause are implemented in both the link query syntax and the transact SQL syntax even though the link query contains the same Clauses in a different order to the comparative Clauses in the transact SQL query for someone who is familiar with transact SQL and not necessarily familiar with link query syntax this link query syntax at a glance should be fairly easy to understand so the point share is that link query syntax is similar to query syntax with which many of us will already be familiar so this makes the implementation of Link queries using query syntax more intuitive as discussed the link query syntax is also more readable than the equivalent link query implemented using method syntax so the key takeaway here is to use Link query syntax rather than method syntax where possible because it is more intuitive to implement and easier to read let's run the code great so let's look at the group join link operator and while we might want to use the group join operator in our link queries we have just performed an inner join using the join operator this query will only return those records based on the ID property of relevant objects of the department type in the department list collection matching with the Department ID property of relevant objects of the employee type in the employee list collection diagrammatically an inner join query can be represented like this what if we wanted to return through a link query all the Department Records in our department list collection and only employee records where the department ID property of employee objects and the employee list collection match the ID property of Department Records in the department list collection so if we were to write to the transact SQL version of this query it would look something like this we would use a left outer join to achieve the desired result this query would bring back all Department Records but only those employee records where the relevant employee records department ID values match the ID property of the relevant Department Records so diagrammatically we can represent a left outer join query like this so let's look at the diagram representing an inner join operation and compare the diagram to the diagram representing the left outer join operation so let's use our group join operator in a link query to return all Department Records from the Department list collection but only the employee records from the employee list collection with a department ID property that matches an ID property of a department record in the department list collection so here we are implementing our query using method syntax you can see the implementation of the group join operation using method syntax is very similar to The Way We implemented the join operation in the previous example foreign the code note the way we have structured our output is clearly different when outputting the results of our group join query when compared to the way we structured our output of the results of our join query but note that at the moment the same join between Department Records and employee records has occurred the reason for this is not because the group joined and the join operators perform the same type of join operation it is because currently each of the records in the employee list collection match with a department record in our department list collection let's change our data to highlight a key difference in the join operation and the group join operation let's do this by going to the code where we have hard-coded made up employee and Department Records and added these records to their respective collections let's ensure that the technology department which has an ID of three does not match with a department ID property of any of the employee objects in our employee list collection we only currently have one employee that is in the technology department according to our data let's change the relevant Department ID so that there are no employees that are members of the technology department so let's change this department ID property now no employees are members of the technology department according to our data let's run the code so you can see our technology department record is being returned along with all the other department records in the department list collection even though its ID property doesn't match the department ID property of any employee records stored in the employee list collection so simply put Department information for departments that contain employees are included in the query results and departments that don't contain any employees are also included in the query results in this example the technology department has returned even though it contains no matching employee records so here we have performed a left outer join query using links group join operator so let's rewrite this link query using query syntax you can see here that the group join extension method does not get explicitly called when we Implement our query using query syntax the into keyword is used within the query to create a group of employees for each department so as discussed link query syntax does not match exactly when comparing link query syntax to familiar query languages like transact SQL but in many ways it does resemble a language like transact SQL in this sense link query syntax is more intuitive to implement than method syntax when implementing link queries and just to labor the point as discussed it is also better to implement link query Syntax for our link queries then implementing method Syntax for the same purpose because of better readability let's run the code great and we get the exact same result as when we ran the same query that was implemented using method syntax now that we have changed the data so that the technology department does not match with any employee records let's run our join operation that we created earlier notice that the results of the join operation doesn't include the technology department this is because the join operation performs an inner join and with the group join operation we are able to perform a left outer join operation so let's comment out our join query and uncomment our group join query and for good measure let's run the code again and as you can see the technology department is now included in the results displayed to the screen even though the technology department does not have any matching employee records great so the left outer join operation returns all records from the outer left collection in the query but does not return records from the inner collection where the inner collection records do not match any of the outer collection records so if there were employee records in the employee list collection that did not match any of the Department Records in the department list collection these employees would not appear in the results outputted to the screen we can prove this let's change the department ID of this employee record where the first name property is Bob and the last name properties Jones we have changed the department ID property for this record to six and there's no matching Department record I.E no Department record has an ID of six let's run the code and you can see that the employee record with first name Bob and last name Jones does not appear within the results however even though the human resources department has no matching employee records it is still included in the results output to the screen great let's add Bob Jones back into the human resources department like this and let's run the code excellent so hopefully this made it clear how we are able through link to use the join operator to perform inner join queries between two object Collections and how we are also able to perform left outer join queries using the group join operator [Music] hi and welcome to the third part of a video series on the link technology using c-sharp this video is also part of the seventh tutorial in an advanced c-sharp course link was introduced with c-sharp version 3 which was released on the 19th of November 2007. link stands for language integrated query in this video we are going to focus on code examples that make use of several link operators the code examples demonstrated in this video will hopefully help us gain an understanding of a broad array of operators that are made available to us through link we'll learn how we can use these operators to query and transform data this quote from the Microsoft docs provides a basic definition of standard query operators and can be found at this URL standard query operators are the methods that form the link pattern most of these methods operate on sequences whereas sequence is an object whose type implements the generic I.E numerable interface or the generic I queryable interface a lot of the more frequently used query operators have dedicated c-sharp keyword syntax that enables them to be called as part of a query expression as discussed in the previous video in this video series it is advantageous to use Query syntax rather than method syntax where possible because query syntax is more readable note that query expression Clauses are translated into calls to query Methods at compile time for a useful tabular representation of standard query operators that have equivalent query expression Clauses please navigate to this URL we discussed what is meant by deferred execution and immediate execution in the previous part of this video series for a useful tabular classification of operators in terms of deferred execution or immediate execution please navigate to this URL for additional information on deferred execution versus immediate execution and Method syntax versus query syntax please View the second part of this video series so to gain an understanding of several useful link operators let's create a few code examples as with the previous video in this series I'll be demonstrating these code examples on my Mac platform using visual studio for Mac the code creation process for these code examples is almost exactly the same process as creating the equivalent code examples on a Windows platform using visual Studio for Windows the fact that I'm using visual studio for Mac should not be a barrier for a learner to follow along with the creation of these code examples let's start by creating a.net core console project we created a project in the previous video named link examples underscore one let's name this project link examples underscore 2. in order to save time let's copy data related classes that have already been created in the previous videos of this series and incorporate these classes into our new project these classes contain class definitions for an employee and a department record as well as code that adds several made up objects of type employee and Department to their respective collections as in the previous parts of this video series we can then use these collections of strongly typed objects in our link query examples so to copy the relevant code let's navigate to this URL IE to a GitHub repository that was created in the previous video let's click on the directory icon labeled link examples underscore one then let's click on the file icon labeled program.cs let's copy the employee class to our clipboards and paste the contents of our clipboards within the new project that we have just created let's copy the department class to our clipboards and paste the contents of our clipboards below the employee class within our new project lastly let's copy the data class to our clipboards and paste the contents of our clipboards below the department class within our project so in the previous video we looked at the following operators the select projection operator the where filter operator the join and group join join operators in this video we'll create code examples that implement the following operators we'll start by looking at the following sorting operators order by order by descending then by and then by descending we'll then look at these grouping operators Group by and to lookup we'll then look at these quantifier operators or any and contains we'll then look at the following filtering operator of type note that another example of a filtering operator is the where operator we have looked at the where filter operator in the previous parts of this video series lastly we'll look at the following element operators element at element at or default first first or default last last or default single and single or default we'll look at even more link operators and create code examples in the next video the next video will be the final video in this video series on link right let's get started so let's start by looking at the data related classes that we copied from GitHub we have the employee class which provides a definition for an employee record we have the department class which provides a definition for a department record we have the data class that contains code where lists of hard-coded made up employee and Department objects are added to their respective collections within their respective methods and returned from their respective methods in the previous video in this series we looked at join operators namely the join operator and the group join operator so in the context of join operations the department collection has a one-to-many relationship with the employee records in the employee collection this simply means that one or many employees can be members of a specific Department a specific employee can be a member of only one department at a point in time so let's go to our main method we can use the data dot get employees method to return a collection of made up employee records let's use this method to assign the relevant collection of employee records to a local variable named employee list the employee list variable is defined as a generic list that is strongly typed as employee so here we have red squiggly lines because we need to include a using directive to the system.collections.generic namespace let's use the data dot get departments method to return a collection of made-up Department Records that have a one-to-many relationship with the relevant collection of employee records and let's assign the relevant return collection of Department Records to a variable named Department list the department list variable is defined as a generic list that is strongly typed as Department so let's get into the creation of our examples sorting operators order by so let's create an example for the order by operator in this example we want to return all employee records from the employee list collection and order by Department ID to make things a little bit more interesting let's say we want to include the department name within our outputted results the problem here is that the department name does not exist in the employee type so we need to join the employee list collection to the department list collection so that we can include the department name in our results we can do this by using the join operator so let's write this query using method syntax so that we can see all the link extension methods used in the relevant query so we first need to make sure that we include a using directive to the system.link namespace this directive will give us access to the relevant link operators that we will be implementing in our code examples we know that the system.link namespace contains two static classes namely innumerable and queryable and these static classes mostly contain extension methods our link operators which are implemented in the form of extension methods are implemented within the enumerable and queryable static classes so this link query joins the employee list collection to the department list collection on the department ID property of each of the relevant employee records with the ID property of relevant Department Records foreign this query let's alter the data a bit let's make the employee record pertaining to Sarah Jameson a member of the technology department by changing the relevance Department ID property from two to three let's also change the department for the employee record pertaining to Jane Stevens to the technology department by changing the relevant Department ID from 2 to 3. this change to the data will make the effects of our sorting operators more apparent when we view our results so if we run the query first without the use of any order by operators note that the data appears to us in the same order as it was added to the employee list but now let's say there is a requirement to order our results by the department ID property in ascending order we can do this by chaining the order by extension method to the end of the query like this for more information on method chaining please view the previous video in this series so we can pass in a Lambda expression to the order by extension method to indicate that we wish to order the results by the department ID property let's run the code and you can see that the results are now ordered in ascending order by Department ID if we look at the code that added each department to the department collection we can see that the human resources department has an ID of one the finance department has an ID of two and the technology department has an ID of three our results have been ordered in ascending order based on the department ID property of the employee record so we can clearly see the effects of the order by operator on our results great if the requirement changed such that we needed to order our results by the department ID property in descending order we can chain the order by descending extension method instead of the order by extension method for this purpose our results are now ordered by Department ID in the reverse order when compared to the previous output great so let's say that we want to order our results by the department ID property in ascending order and then by the annual salary property also in ascending order so let's replace the order by descending extension method with the order by extension method in our results like this then let's chain the then buy extension method to the query like this we can then pass a Lambda expression to indicate that we wish to further order our results by the annual salary property the then by extension method will order the results produced by the order by sorting operator in ascending order great and if we want to order by the annual salary property in descending order we can replace the then buy extension method with the then by descending extension method for this purpose excellent foreign we can represent sorting operations within link queries that are represented using query syntax like this note the order by and descending keywords in the query syntax version of the relevant query we use the order by keyword within our query to order by our first specified property if we want to subsequently sort on other properties instead of chaining the then by extension method to our query and query syntax subsequent Properties by which we wish to sort are separated by commas the descending keyword can follow any of the properties that we wish to sort in descending order the default order is ascending order so let's look at the group by and to lookup grouping operators let's start with the group by operator so this operator is akin to the group by Clause we would apply in a transact SQL query so we can implement the group by operator using the group by extension method or the group and the buy keywords within query syntax to perform the same operation so let's say we wish to query the employee list collection and group our results by the department ID property the query using query syntax would look like this this query is simply grouping our results by the department ID property using method syntax this query would look like this in all of the link query examples using query syntax that we have looked at up till this point in this video series we have ended all our queries with a select operator notice that this query does not end with a select operator it is important to note that a link query implemented in query syntax must either end with a select operator or a grouping operator notice how this query does not end with a select operator but a grouping operation is being performed at the end of this query so we can Traverse the results of this grouping operation using nested for each Loops the outer loop traverses each group that has been created based on the department ID property the inner loop traverses the item members within each of the groups that have been created in our query based on the department ID property great we could also include the order by operator within our query like this let's run the code great we can implement the same query using methods syntax using the two lookup extension method like this great we can also include sorting functionality through the order by operator through the implementation of method chaining like this great note that the two lookup method performs the same operation as the group by operator the only difference is the execution of the group by operation is deferred whereas the execution of the two lookup operation is executed immediately we discussed deferred execution and immediate execution in the previous part of this video series for more information on deferred execution and immediate execution please View the second part of this video series the link to this video has been included Below in the description note that the results returned from a group by operation and a two lookup operation return a group contained in a special type of collection that implements an eye grouping generic interface so let's look at the all any and contains quantifier operators let's first look at the all and any operators let's create a variable named annual salary compare and assign it with a value of 20 000. let's Implement a block of code related to the all operator let's Implement a similar block of code related to the any operator so the all and any operators return a Boolean value the return value will equal true if the elements in the relevant collection satisfy a condition passed to the relevant method this condition can be passed in the form of a Lambda expression this query will return true if all employee records have annual salary property values that are greater than twenty thousand this query will return true if one or more employee records have an annual salary property value that is greater than twenty thousand let's run the code foreign this is an expected result let's change the annual salary compare variable to a hundred thousand great and let's change the annual salary compare variable to 40 000. so let's move on to the contains operator so we want to be able to assess whether an employee record exists within our collection of employee records the contains operator will return true if we pass in an object that is equal in value to an object within the relevant collection to understand how the contains operator Works let's create an employee record that we know matches an employee record within the employee list collection let's copy this record for the employee named Douglas Roberts that is a member of the relevant employee collection and paste it in our main method let's name the variable that stores a reference to the employee record we wish to find within the employee list collection search employee so how can we assess whether the employee record pertaining to Douglas Roberts exists within the employee list collection we can use the contains extension method we can simply pass the variable we named search employee to the contains extension method which we have invoked on our employee list collection object so the contains method returns true if the search employee object matches any of the objects within the employee list collection and false if the search employee object does not match with any of the objects stored within the employee list collection so let's write code to write an appropriate narrative to the screen based on the Boolean value returned by our query foreign let's run the code and this is not the result we expected because we literally copied and pasted the code representing one of the employee objects that has been added to the employee list collection from our data class to the main method as our search object so why is our output indicating that the search employee object does not match any of the objects stored within our employee list collection this result is unexpected the answer is that the compiler knows how to compare built-in c-sharp types like for example integer or bull the employee type is a user-defined type or custom type we need to tell the compiler how we wish to compare two objects of type employee to establish where the two employee objects are equal so we can do this by creating a class that implements the generic I equality comparer interface the eye equality compare interface is a member of the system.collections.generic namespace we have already included a using directive to this namespace within our code so let's create a class named employee comparer and let's indicate that we want the employee comparer class to implement the I equality compare a generic class that is strongly typed with the employee user-defined type so let's hover our Mouse pointers over the red squiggly line and create the stubs for the methods that we need to implement like this so two method stubs have been generated one named equals and the other named get hash code so the get hash code method is used for the purpose of uniquely identifying an object we can implement the code for the get hashed code method by returning the hash code of the ID property of the relevant employee object like this the equals method must be implemented in a way that establishes how we wish employee objects to be compared when determining whether two employee objects are of equal value so let's say that we are satisfied with comparing the relevant employee objects based on their ID first name and last name properties to establish equality between the relevant employee objects so we can achieve this with the following code if the relevant properties are equal return true else return false so we are already passing in the search employee object to the contains method let's also pass a newly instantiated object of type employee comparer to an overload version of the contains method like this and now we are telling the compiler how we want to compare our employees search object with the objects stored within the employee list collection let's run the code and this is an expected result the contains method now returns true as expected because our search record matches the employee record for Douglas Roberts within the collection on which we are performing our search great so now let's look at the of type filter operator so before we use the of type filter operator in our code examples let's create a method named get heterogeneous data collection heterogeneous in this context of course is referring to the storage of objects of multiple different data types within the same collection so we can store objects of multiple different data types in an arraylist note that Microsoft does not recommend using arraylists for new development it is far better to use strongly typed lists to store collections of data for more detail as to why strongly typed lists are recommended please view a video on generics created by this channel a link to this video has been included Below in the description so a use case where we could apply a link query on an arraylist could be perhaps we have a legacy piece of code that includes an arraylist containing objects of multiple types and we need to filter the relevant arraylist based on specific types we can achieve this using the of type link operator we'll look at how we can do this in a bit let's first add some made up data to an arraylist so the arraylist stores integers strings objects of the employee user defined type and objects of the department user-defined type excuse me let's go to our main method and write code to use the of type operator to query this arraylist based on specified data types let's query for all string values in our arraylist great so let's query all integer values in our array list great let's query for all objects of the employee user defines type great let's query for all objects of the department user defines type excellent so you can see how we can query an arraylist for objects of a specified type using generics and the of type Operator by passing in the relevant type between angle brackets like this this will return those objects within the arraylist that are of the specified type let's move on to the element operators let's look at the element at element at or default first first or default last last or default single and single or default element operators so let's first look at the element at operator so the element at operator is used for querying for an item in a collection that resides at a specified ordinal location within the relevant collection so we can pass an integer value representing the relevant elements location in the relevant collection into the element add method to return the desired items value from the relevant collection like this great and our query has returned the value for the relevant element foreign but what happens if we pass in a value representing a position in the relevant collection where an element does not exist so let's try this let's pass in a value of 8. right so it is important to note that no item exists within the relevant collection at ordinal position 8. so in this case an argument out of range exception is thrown this brings us to an important point about the difference between the element at and the element at or default method if we replace the element at method with the element at or default method and we query the relevant collection for an item at a position where the desired item does not exist within the relevant collection the element at or default method does not throw an exception but rather Returns the default value for the desired items relevant data type let's briefly discuss what we mean by default value for a particular data type the c-sharp language Associates default values for c-sharp data types so if for example we are querying a collection of integers using the element at or default method for a value that did not exist at the specified location in the relevant collection the element at or default method would return the default value for the integer data type which is a value of zero the integer value of 0 is the default value for the integer data type in C sharp if however we are querying a collection containing a reference type object like an object of our user-defined type employee the default value returned by the element at or default method would be null null is the default value for reference type data types like user-defined types or the string data type for more detail regarding default values in c-sharp please navigate to this URL so let's use the element at or default method to query the relevant collection of employees for a value at position 8. I.E where no employee object is present within the relevant collection we can then write code to check if the returned value is null and you can see that an exception is not thrown and no results are outputted to the screen which is an expected result because the query returned a null value let's pass in a value of 2 foreign and then one and in both cases the appropriate result is outputted to the screen so let's write code to Output an appropriate narrative to the user based on the value returned from the element at or default method so let's pass in a value of 12. the output indicating that the return value is null I.E the employee object does not exist in the collection as output to the screen this is an expected result great so the first operator Returns the first element in a collection if no condition is specified we have the option of passing a condition to the first method or we can leave the brackets following the first method empty if we do not specify a condition the query will return the first element in the relevant collection if a condition is specified the first operator will return the first element in the collection that satisfies the specified condition we can specify a condition in the form of a Lambda expression right to prove this let's first create a strongly typed list of integer values foreign this collection using the first operator and don't provide a condition passed as an argument to the first method the query Returns the first item in the collection as expected so let's pass a condition in the form of a Lambda expression to the first extension method so this condition is simply querying the collection for the first even number in the collection let's run the code great but now what happens if we alter the collection of values so that no value satisfies the condition I.E no even numbers exist within the relevant collection an invalid operation exception is thrown so if we don't want an exception to be thrown we can replace the first operator with the first or default operator as you may have guessed where no items in the relevant collection satisfy the relevant condition this method will not throw an exception but will rather return the default value of the relevant data type we know that the default value for the integer dates type is zero let's write code to Output an appropriate narrative to the screen if the relevant condition is not satisfied let's run the code and this is an expected result so let's include an element in the relevant list that does satisfy the condition excellent so the last and last or default operators work in much the same way as the first and the first or default operators the only difference is that the last item in the collection is returned where no condition is specified the last item that satisfies a specified condition and the collection is returned when a condition is specified the last method will throw an exception if an appropriate element is not present within the relevant list we can use the last or default method rather than the last method to return the default value for the relevant data type in the case where an appropriate element in the relevant collection is not present great so let's move on to the single and single or default element operators the single operator Returns the only element in a collection or one element that satisfies a specified condition from a collection we have the option of passing a condition into the single method through the use of a method overload or we can leave the brackets following the single method empty which means we have chosen not to pass in a condition into the single method if we choose not to pass in a condition into the single method and there's more than one element or zero elements in the collection and invalid operation exception will be thrown if however there is only a single element in the collection the value for this element will be returned by the query if we do choose to pass in a condition and zero or more than one element satisfies the condition an invalid operation exception will be thrown if we pass in a condition to the single method and only a single element satisfies the condition the value for this single element will be returned from the relevant single operation let's apply the single operator to a collection of employees let's first modify the data for our list of employees so that only one employee element exists within the relevant employee collection foreign let's write code using the single operator to query the relevant employee list foreign this is an expected result let's now include the employees that we just commented out back within the relevant employee list let's run the code and an invalid operation exception is thrown as expected this is because more than one employee resides in the list if there is only one item in the relevant collection the value for this item is returned if there are zero items or more than one item in the collection and the condition is not specified for the single operator and invalid operation exception is thrown so let's test the single method and this time specify a condition where one item within the relevant collection satisfies the specified condition great let's specify a condition where more than one item in the relevant collection satisfies the specified condition as you can see an invalid operation exception is thrown so let's test the same scenario I.E more than one element in the relevant collection satisfies the specified condition but this time let's use the single or default method that's interesting so note where more than one element satisfies the specified condition when the single or default method is applied and the relevant query an invalid operation exception is thrown just like when the single method is applied to perform the same operation so we can use the single or default method instead of the single method if we don't want an exception to be thrown under the scenario where no elements exist within the collection the default value for the data type will instead be returned by the query if a condition is specified for the single or default method and no elements satisfy the condition the same result will be produced I.E the default value for the data type of the elements stored in the collection will be returned by the query if a single item is present within the relevant collection and the single or default method is applied to perform a query against the relevant collection the single elements value that exists within the relevant collection will be returned by the query [Music] hi and welcome to the fourth and final part in this video series on the link technology using C sharp this video is also part of the seventh tutorial in an advanced c-sharp course this video is a continuation of the previous three videos in this video series on link so I recommend viewing the previous three videos in this video series before viewing this video in the previous video in this series we looked at code examples where certain link operators were implemented to query and transform data this video is a continuation of the previous video in this series where we'll create code examples using some of the other link operators to gain a broader understanding of what can be accomplished using the Link Technology in c-sharp so in the previous videos in this series we have created code examples using the following link operators the Sorting operators order by order by descending then buy and then by descending the grouping operators Group by and to lookup The quantifier Operators all any and contains the filter operators of type and where the element operators element at element at or default first first or default last last or default single and single or default the join operators join and group join we have already looked at the select projection operator and we'll also look at the select operator in this video and in addition to this we'll also look at the select many projection operator so in this video we'll look at the following link operators the equality operator sequence equal the concatenation operator concat the set operators distinct except intersect and Union the generation operators the fault of empty empty range and repeat operators the aggregate operators aggregate average count sum and Max the petitioning operators skip skip while take and take while the conversion operators to list two dictionary and two array and lastly the projection operators select and select many we'll also look at the following keywords that are useful when used in queries implemented in query syntax namely the let and into keywords we have looked at the select projection operator already in previous videos but we'll look at this operator again in this video as well as look at the select many projection operator we'll then be able to gain an understanding of the difference between the select and the select many projection operators as in the previous videos I'll be demonstrating the code examples on my Mac platform if you are using a Windows platform to follow along the experience of creating these code examples will be almost exactly the same so the fact that I'm using visual studio for Mac should not be a barrier for a learner using visual Studio for Windows to follow along with the creation of these code examples okay so let's create a.net core console project thank you so the official release of.net 5 has now been released so I'll be running this project using the new.net5.net runtime for more information on the significance of the.net 5 runtime please View the second part of this Advanced c-sharp course I've included a link to this video Below in the description the project we created in the last video was named link examples underscore 2. let's name this project link examples underscore 3. so as we did in the previous video let's navigate to this URL where we can access code on GitHub for the project that was created in the previous video of this series here we can copy the data related code that we created in our previous project so that we can reuse these data related classes in this project let's click the directory icon labeled link examples underscore 2. let's then click the file icon labeled program.cs let's copy the class named employee and paste the contents of our clipboards to our new project let's do the same for the Department class and the data class okay so we won't be using the get heterogeneous data collection method that resides in the data class in this video so let's delete this method let's refresh our memories about the classes we have just copied and pasted from GitHub the employee class contains a definition for an employee record the department class contains a definition for a department record the data class contains hard-coded made up data for employee records and Department Records the employee records are stored in a generic list strongly typed as employee the Department Records are stored in a generic list that is strongly typed as Department we can access the data stored in the employee list collection from calling client code in this case this will be the main method by calling the static method named get employees we can access the data stored in the department list collection by calling the static method named get departments note that the data class in which these methods reside is a static class let's navigate to the main method and before we create our example code let's add the appropriate using directives first let's add a using directive to the system.collections.generic namespace the generic list type is a member of this namespace let's also add a using directive to the system.link namespace once we have added our system.link using directive we can access our link operators on collection types that implement the I enumerable interface so for example list types implement the I enumerable generic interface so we are able to access extension methods stored within the innumerable static class which is a member of the system.link namespace by including a using directive to the system dot link namespace the queryable static class also includes link extension methods and is a member of the system.link namespace for more information on how extension methods work in c-sharp please view the first video in this video series a link to this video has been included Below in the description before we get started creating our code examples I want to draw your attention to what might be an issue for visual studio for Mac users when we run our code interactively through Visual Studio for Mac by default the output may appear in the terminal console window within visual studio for Mac like this this is absolutely fine for testing code but you may prefer to present the output externally I.E in a terminal console window outside of visual studio for Mac if you'd prefer to present your output externally I.E outside of visual studio for Mac please navigate to visual studio format preferences then Under The Heading marked other select the item labeled terminal in the right pane of the relevant dialog box ensure that the enable integrated terminal checkbox is unchecked this is obviously not a functional issue it really comes down to personal preference let's define a generic list variable named employee list that is strongly typed as employee and let's assign the collection of employee records returned by the data dot get employees static method to the employee list variable let's define a generic list variable named Department list that is strongly typed as department and let's assign the collection of Department Records returned by the data.get department static method to the department list variable okay so we are now ready to query and transform data using link so let's start with the equality operator sequence equal so the use case here is we want to compare two lists of data and we want to know if these two lists contain elements of equal value and each element in each of the relevant lists are stored in the same order if each item in each list matches in terms of value and order the sequence equal method will return true if any of the items in each of the relevant lists does not match in terms of value and order the sequence equal method returns false let's create a generic list named integer list one that are strongly typed as integer let's copy and paste this line of code to the next line let's change the name of the second list to integer list 2. let's run the code and the sequence equal method returns true because the values and sequence of elements in integer list 1 is identical to the values and sequence of elements in integer list 2. let's change the order of the items in integer list two so this sequence of values is not equal to the sequence of values stored in the list named integer list one let's run the code and this is an expected result let's change integer list to once again for good measure and this is an expected result great so let's change the data in integer list 2 so that the order and values in the lists are equal and now the result is true which is an expected result that was pretty straightforward I.E comparing two sequences of values of a primitive data type IE the integer data tab but what if we want to test this type of equality between two lists that are strongly typed with a complex type like for example our employee uses defined type so let's Define a variable named employee list compare as a generic list type that is strongly typed as employee and let's assign The Collection returned from the data dot get employee's static method to our employee list compare variable let's run a sequence equal operation and compare the values stored within our employee list compare collection with the values stored within the employee list collection so one would expect the result of the sequence equal operation to return true because both collections contain exactly the same data let's see what happens oh and false is returned the reason why false is returned is because we need to tell the compiler how to establish equality between objects of the relevant complex type IE in this case the employee type so we achieved this in the previous video in this series by implementing the built-in I equality comparer generic interface so let's copy the relevant code for this that we implemented in the previous video in the series let's navigate to the GitHub repository at this URL that contains the code we created in the previous video in this series let's copy the class named employee comparer to our clipboards and paste the contents of our clipboards to our projects like this we have red squiggly lines so let's fix this by bringing in the appropriate using directive so here we have implemented a class named employee comparer that implements the generic I equality compare interface that is strongly typed as employee this gives us a way of telling the compiler how we want objects in our lists of type employee to be compared when determining equality between the relevant objects so we are explicitly doing this here in the equals method where we are comparing the ID first name and last name properties between two employee objects we are returning true if the relevant properties of the relevant two objects are equal and false is returned if any of the relevant properties of our two objects are not equal within the get hash code method we are returning the hash code of the ID property of the relevant employee objects for more information on hash codes please navigate to this URL so now let's go to our main method and we can pass in a new instance of the employee comparer class to an overloaded version of the sequence equal method this object will tell the compiler explicitly how we want our employee objects to be compared let's run the code and now the sequence SQL operator works as expected so note that we need to tell the compiler how we want objects that are defined as complex types to be compared when determining equality between the relevant objects we can do this by creating a class that appropriately implements the I equality comparer generic interface great let's move on to the concatenation operator named concat we can use the concat operator to append one collection of data to another collection of data so let's see the concat operator in action let's create a collection of integer values let's then create another collection of integer values let's append the second collection of integer values with the first collection of integer values using the concat operator let's write code to Output the results of this concatenation operation to the screen let's run the code great let's do another example but this time let's append a collection that contains a collection of objects of a complex type to another collection of objects of the same complex type the complex type we'll use in this example will be our employee user defined type once again we can use the concat operator to achieve what we want here let's run the code great let's move on to the aggregate operators let's first look at the aggregate operator using the aggregate operator we can perform a custom operation on values within a collection let's say we have a requirement where we need to provide a total for the annual salaries of our employee records we also need to include the addition of an appropriate annual salary bonus in the final result let's say a manager gets a bonus of four percent and employees that aren't managers get a bonus of two percent so let's say we have a use case where we need a result that is a total of all employee annual salaries which must include each employee's bonus we can take this added complexity into account when totaling up our employee annual salaries through the use of the aggregate operator so the first argument is the seed value so let's provide zero for this argument using this argument we are initializing the value that will be returned by our aggregate operator the next argument is of a delegate type where we can include the logic for our aggregation functionality in the form of a Lambda expression so as you can see in our Logic for the relevant Lambda expression argument we are checking to see if the relevant employee is a manager whereby we need to add a bonus of four percent to the relevant employees annual salary if the employee is not a manager we need to add a bonus of two percent to the relevant employees annual salary we can then include the appropriate bonus amount in our calculation so we are adding up all employee annual salaries which includes each employee's appropriate bonus let's run the code great say we want to Output a comma delimited string from our employee list collection each delimited item containing the employee full name a dash then the employee annual salary each annual salary must include the appropriate bonus we also want to include a label preceding the comma delimited string we can achieve this using the aggregate operator like this the first argument is the label where an appropriate value could be something like employee annual salaries including bonus then the logic of our aggregation functionality can be expressed in a Lambda expression for the second argument like this we can apply the same logic to include appropriate bonuses from our previous example let's run the code great but we have a slight issue where a comma is presented at the end of our string we don't want this comma in our final result we can express this by passing a Lambda expression as our third argument to an overloaded version of the aggregate operator this argument allows us to perform a final operation on the results produced by the Lambda expression passed in as the second argument we first need to include another data type argument with an angle brackets following the aggregate method to declare the data type of the final output I.E provided by the Lambda expression we are passing in to the last parameter of this overloaded version of the aggregate method in the Lambda expression passed in as our final argument we are using the substring method to remove two characters from the end of the result which means a comma and a space will be removed this result is what we want excellent so let's move on to the average aggregate operator so to find the average annual salary for a list of employees we can apply this code great if we want to find the average salary for all employees in the technology department we can use method chaining and the where operator to achieve this like this great for more information on method chaining please View the second part of this video series let's move on to the count aggregate operator so if we want to know how many employee records we have in our collection of employee records we can apply the count operator like this great if we want to know how many employees or members of the technology department we can pass in a condition as an argument to the count operator the condition that is passed in as an argument to the count method can be expressed in the form of a Lambda expression great let's move on to the sum aggregate operator so let's keep this simple we just want the sum total of all annual salaries of all employee records stored in our employee list collection we can apply the sum operator to achieve this great let's move on to the max aggregate operator so if we want to return the highest annual salary property of all employee records stored in our employee list collection we can apply the max aggregate operator in a link query like this great let's move on to the generation operators namely default of empty empty range and repeat let's first look at the default fmt operator so we can use the default if empty operator to return a new I enumerable collection that when for example we apply the element at method on the new collection to check if the new collection is empty the operation will return the default value for the relevant type used to strongly type the relevant collection a query using for example the element at method against a collection returned from a default of empty operation will not throw an exception if the collection is empty the default value of the type with which the relevant collection is strongly typed will instead be returned for more information on default values for C sharp dates types please navigate to this URL we'll see later how we can pass in a value to the default of empty method to specify our own default value that we'd prefer to be returned when for example the element at method is used to check if the relevant collection is empty rather than the default c-sharp value for the relevant data type let's look at an example using the default fmt method so let's create an empty list of integer values let's perform a default fmt operation on this collection of integer values and assign The Returned collection to a new collection of integer values let's use the element at operator and pass in 0 to the element at method to check if the collection is empty you can see that the element at operator Returns the default value for the integer data type which is zero this is an expected result let's create another example but this time let's use the employee data type to strongly type our collections as discussed the default value for a reference type in c-sharp is null but as discussed we can pass in a default value that we would prefer to be returned by for example the element at operator when the relevant collection is empty so let's person an employee object where the ID property of the relevant employee object is set to zero null is not returned as would be the case if we hadn't passed in a value to the default fmt method because we have specified our own default value where the ID property of the default employee object is zero great similarly we could have set the default value for our integer collection example by for example passing in 999 999 to the default if empty method instead of returning the default c-sharp value for an integer which is 0 99999 is returned this is an expected result excellent right let's look at the empty method so we can use the empty method to generate a new empty collection so for example we want to create a new innumerable generic collection of employee records we can do this by using the empty operator like this note the empty method is not an extension method of innumerable or I queryable like other link methods it is a static method included in the enumerable static class so for example we could instantiate a new empty generic list strongly typed with the employee user defined type through the use of the empty method we can then chain the two list conversion operator to this operation and return an empty generic list we are using the two list operator to convert an i enumerable generic collection that is strongly typed with the employee data type to a generic list that is strongly typed as employee so for good measure let's add a new employee item to our new list that we have generated through the use of the empty method and the use of the two list conversion operator let's write code to write the items or in this case one item stored in our new list to the screen great let's move on to the range generation operator we can use the range operator to return a collection of values that are within a specified range so let's clarify this with an example we want to return a range of integer values in a collection where the first item in the range has a value of 25 and each subsequent item is incremented by a value of 1 until there are a total of 20 values in the relevant collection we can achieve this by using the range method like this in this example the first argument specified is 25. this is the value of the first element and the second argument specifies the number of elements to include in the relevant generated collection when each item is added to the collection It Is incremented by a value of one so the second item will be 26 the third item will be 27 the fourth item will be 28 and so on let's run the code great so using the range operator we have generated a collection of integer values that fall within a specified range excellent let's say we want to generate a collection of a specified amount of elements where a value for each element in the collection is repeated we can use the repeat operator for this purpose like this great let's move on to the set operators namely distinct except intersect and Union let's start with distinct so let's say we have a strongly typed generic list that contains a list of integer values some of which are repeating values we want to perform a query against this list of integer values where we only want distinct values returned we can achieve this by applying the distinct operator to our query like this great let's say that we have two collection of a specific type and we want to return elements with values in our first collection that are not equal to any of the values of the elements in our second collection we can achieve this by using the accept operator let's look at an example of using the accept operator applied to two collections of integer values so one and two are returned in our results collection because these values exist in our first collection and don't exist in the second collection the values 3 and 4 exist in our first collection and also exist in our second collection the values five and six exist in our second collection and even though these items don't exist in our first collection the accept operator does not return these items as part of the results collection because in this example the accept operator returns values that exist in the first collection and don't exist in the second collection let's try an example using complex types let's use our employee type let's create a generic list strongly typed as employee let's copy data that we know will exist within our employee list collection and add these items to the list we have named employee list 2. let's add some additional items to the employee list to collection let's then call the accept method on the employee list collection and pass in the employee list 2 collection as an argument to the accept method then let's assign the results of this operation to an implicitly typed variable named results we have of course used the VAR keyword to implicitly type our results variable let's write code to Traverse the results and output the results to the screen let's run the code and see what happens and this result is not expected the output contains all items within the employee list collection I would have expected that the items that were copied from the data class and added to the employee list 2 collection as well as the other items that we added to the employee list collection would be excluded from the results the reason for the unexpected results is because we have not told the compiler how to compare employee objects when determining if one employee object is equal to another employee object so how can we let the compiler know how we want one employee to be compared to another employee within our collections when determining equality between the two relevant objects you may have guessed already how we can achieve this we first need to create a class that implements the eye equality comparer generic interface we can then write code to establish how one employee object should be compared to another employee object when determining equality between the relevant objects we have already included the code for this which we applied when we created code to perform a sequence equal operation on two lists that were strongly typed as an employee so we have our class named employee comparer that implements the IE quality comparer generic interface so we can reuse this class for our example that performs an accept operation on two generic lists that are strongly typed as employee so all we need to do is create a new object of type employee comparer and pass this object into an overloaded version of the accept method like this let's run the code great this is now an expected result let's move on to the intersect operator so we can use the intersect set operator to return a collection containing only those items that exist in the employee list collection that are equal to the items that exist within the employee list 2 collection and now that we know we are comparing elements in two collections that are strongly typed with the employee complex type we need to pass in a new object of the employee comparer type I.E a type that appropriately implements the generic IE quality comparer interface this tells the compiler how to compare two objects of type employee when determining if the relevant employee objects are equal let's run the code and this is an expected result great let's move on to the union operator the union extension method requires two Collections and returns a new collection that includes distinct elements from both the collections we can again use the same data we have used in the previous two examples to test the union operator right let's write the code for this you will notice we are also passing in an object of type employee comparer to the union method Let's test the code great so let's see what happens in this example when we don't pass in an object of type employee comparer to the union method you can see that duplicate records are included in the results as a consequence of not passing in an object derived from a class that appropriately implements the generic IE quality comparer interface and of course we know we have already created such a class so let's ensure that we pass in our object of type employee comparer to the union method so that only distinct employee objects are included within our results excellent so let's move on to the partitioning operators these partitioning operators include the skip skip while take and take while operators let's first look at the skip operator use the skip operator to skip over a given number of elements in a sequence and then return the remainder so let's query our employee list collection using the skip operator let's skip over two of the elements stored in our employee list collection and return the remainder of the elements using the skip operator great this is an expected result let's look at the skip wow operator using the skip while operator bypasses elements in a sequence as long as a specified condition is true and then Returns the remaining elements let's see this operator in action so the condition here is Skip elements in our sequence of employee objects in the employee list collection while the relevant employee object's annual salaries are above 50 000. great this is an expected result just to make things a little bit more clear on how this operator Works let's add a new employee record to the employee list collection this employee record has an annual salary of one hundred thousand which of course is above fifty thousand let's run the code and you can see that while the condition is true the items in the relevant collection are skipped I.E will not be returned from the query however all subsequent elements in the sequence will be returned once the condition returns false even though the last element in the relevant sequence has an annual salary property greater than fifty thousand it is still returned because the third element in the sequence caused the condition to return false the fact that the last element has an annual salary above 50 000 and therefore causes the condition to be true doesn't mean that the last item will be returned by our query note that once the condition returns false all items from that point will be returned from our query right let's move on to the take partition operator the take operator is used to return a specified number of contiguous elements from the start of a sequence let's see this operator in action this is an expected result great the first two elements in the relevant sequence of elements in our employee list collection are returned by our query so let's move on to the take while partitioning operator the take while operator returns elements from a sequence as long as a specified condition is true and then skips the remaining elements so let's use the same condition that we used in the skip while operator example so here we are using the take while operator to return elements from the relevant sequence that have an annual salary above 50 000. so the first two elements in the sequence are returned by our query as soon as the third element is evaluated and the condition returns false the elements from that point onwards in the relevant sequence will not be returned by our query so for example the fact that the fifth element in the employee list collection has an annual salary property that is greater than 50 000 is irrelevant because when the third element causes the condition to return false and in terms of the take while operator this means that from that point onwards the rest of the elements and the relevance sequence will not be returned by our query great let's look at the conversion operators to list two dictionary and two array so let's look at the two list conversion operator a query written and query syntax will return an i enumerable collection containing the results of the query what if we need our results to be returned as a generic list we can achieve this using the two list conversion operator let's create an example to clarify this point so for this example let's query our employee list collection for employee records that have an annual salary property greater than 50 000 using query syntax note the red squiggly lines here this is because we are attempting to assign an inumerable collection to a variable of type generic list the compiler is telling us that we have created a type mismatch so we can use the two list operator to convert the I enumerable collection returned by our query to a generic list by wrapping the relevant query in Brackets adding a DOT after the last bracket and applying the two list operator like this so now you can see the red squiggly lines disappear because we have removed the type mismatch let's run the code excellent as discussed earlier in this video series wherever a two conversion operator is applied to a query as we have done here this causes the query to execute immediately I.E query execution is not deferred it is executed immediately so if we want to convert an innumerable collection returned from a query to a dictionary object we can apply the two dictionary operator to the query let's create an example to clarify what is meant by this so as in the previous example here we have a standard query written in query syntax to query our employee list collection for all elements where the relevant elements have annual salary properties that have values greater than fifty thousand so this is a basic query that will return an i enumerable collection but what if we want to return a collection where each element has a unique key associated with the relevant element we can do this by converting the query result to a dictionary generic collection type so let's alter our code so that the innumerable collection returned by our query is converted into a generic dictionary collection So within angle brackets after two dictionary we need to pass in two data types the first data type declares the data type of the values stored in the dictionary the second data type declares the data type of the key that will be used to uniquely identify each element in the collection so the First Dates type is of type employee and the second data type is of type int note that we want each element to be keyed on the employee ID property we can express this by passing in an appropriate Lambda expression to the two dictionary method like this so let's Traverse the key values stored in our dictionary object using a for each Loop note how we are able to use the key values to retrieve the values of each element stored in the dictionary we are doing this by passing in the relevant key within square brackets to the dictionary object here we are outputting the key as well as each employee's first name and last name to the screen and as you can see we have each employee's ID which we have designated as our key value followed by the corresponding employees first name and last name properties excellent we have successfully converted a query result from an innumerable collection to a dictionary object as discussed when we call any of the two conversion operators on a query result this causes our query to execute immediately for more information on deferred execution versus immediate execution please View the second part of this video series for good measure let's also create a result using the two array conversion method so if we try to assign the results of this query to a variable defined as an array of employees the compiler complains of a type mismatch the query result is returned as an innumerable collection and not an array of employee objects to remove the tap mismatch we can apply the two array method like this great so let's discuss the let and the intu Clauses that can be applied when using query syntax to represent a link query let's look at the Microsoft docs for an overview of the let Clause this overview of the let Clause can be found at this URL in a query expression it is sometimes useful to store the result of a sub-expression in order to use it in subsequent clauses you can do this with the let keyword which creates a new Range variable and initializes it with the result of the expression you supply once initialized with a value the range variable cannot be used to store another value however if the range variable holds a queryable type it can be queried so let's look at a basic example using the let keyword in a link query let's say we wish to query our employees based on employee initials now we don't have an initials property for an employee record but within our query using the let keyword we can extract the initials from each employee records first name and last name properties and assign the result of this extraction process to a variable named initials directly within our query using the lit keyword this allows us to use the initials variable in our where Clause as well as reuse the initials variable within our select clause through the use of the let Clause we can also apply a condition and based on the evaluation of that condition store a value in a variable that can be used later in the query like for example within aware clause here we have a condition where we need to add an appropriate bonus to the annual salary property based on whether the employee is a manager or not a manager if the employee is a manager we need to add a bonus of four percent to the relevant employee records annual salary property if the employee is not a manager we need to add a bonus of two percent to the relevant employee records annual salary property we can store the relevant annual salary plus bonus value for each employee record by assigning the value returned by a ternary operator to a variable we have named this variable annual salary plus bonus the let clause in this example enables us to reuse the annual salary plus bonus variable both within the where clause and the select Clause later in the query let's run the code excellent let's look at the into keyword we can use the into keyword in a link query to collate data within a group and then after this operation we are able to perform a filter operation within the same query if required on the grouped data through the use of aware clause so for example let's use a link query to First create a group of high earning employees based on a condition let's say that the employee must earn above 50 000 to fit into the relevant group we can use the where Clause at this point in the query to appropriately filter the relevant employee records and the into keyword to put the filtered data into the relevant group of high earning employees so we can use the into keyword to group The High earning employees into a group named High earners let's say we then want to further filter this group of high earning employees by management status so we only want these employee records where the is manager property is set to true return from our query we want to know which of those High earning employees are managers so we can use another where Clause within our query to filter the high earner group based on the relevant condition we have used a where Clause earlier in our query to create the group of high earning employees then once the group is created through the use of the into keyword we can further filter the group of high earning employees based on each employee records is manager property so we are able to include another where clause in our query to filter the grouped data let's run the code great so lastly let's look at the select and the select many projection operators in this video series we have already looked at the select projection operator so the focus in this example is on the select many operator we want to know how it differs from the select operator and in what circumstances we may wish to apply the select many operator in a link query let's navigate to a Microsoft docs webpage to see what the Microsoft docs say about these two projection operators projection refers to the operation of transforming an object into a new form that often consists only of those properties that will be subsequently used by using projection we can construct a new type that is built from each object you can project a property and perform a mathematical function on it you can also project the original object without changing it select projects values that are based on a transform function select many projects sequences or values that are based on a transform function and then flattens them into one sequence to understand the difference between the select many operator and the select operator let's modify our department class so that it includes a property that stores a collection of employees we have already discussed that Department Records have a one-to-many relationship with employee records so each department object will now store a collection of related employee records let's also alter the get Department's static method that resides in the data static class so that the get Department's static method accepts an argument containing a collection of employee objects then for each department object added to the department list collection within the get Department static method let's include a query to return an appropriate collection of employees I.E those employee records that have a department ID property matching the ID property of the relevant Department object so let's go to the main method and pass in the collection of employees to the get Department method so now the get departments method will return a collection where each department contains a related collection of employee records so now what if we want to query the department list collection for all employees we can achieve this using the select operator but when traversing the results of the select operation we will need to use an outer and an inner for each Loop like this in this scenario the select many operator is better to use for this purpose the select many operator is better in this case because we can use one for each Loop to Traverse the results of our query unlike where we needed to use an additional nested for each Loop to Traverse the results of our query where we used the select operator behind the scenes as it were the select many operator appropriately flattens the results and this means we don't need to use a nested for each Loop to Traverse the results of our query we are able to use one for each Loop for this purpose excellent so we have covered a lot of ground in this video series on link operators I would encourage you to practice using these operators to become proficient in writing link queries this is a very powerful technology and it's used with Entity framework to perform database queries in modern.net applications Entity framework is now the recommended technology to use a.net for implementing database related functionality in.net applications if we navigate to this Microsoft docs webpage we can see this paragraph that states Entity framework core is a modern object-based mapper for net it supports link queries change tracking updates and schema migrations EF core works with many databases including SQL database on-premises and Azure sqlite MySQL postgres and Azure Cosmos DB this makes link a very important technology to learn for net Developers link enables developers to write one set of code that can be applied to handle data related functionality for multiple different data sources in link expression trees are used to represent structured queries that Target sources of data that implement the generic I queryable interface if you would like to delve deeper into expression trees please navigate to this URL so let's summarize what we have learned in our four part series on using the Link Technology in C sharp in the first part of this video series we created our own extension method to filter data we also demonstrated how a Lambda expression can be used to express a condition that can be passed into our extension method to filter the data and return the filtered results from a query the reason we created the filter extension method is because link is mostly made up of extension methods stored in two static classes namely a static class named enumerable and a static class named queryable we are able to access the extension methods Within These static classes by including a using directive to the system.link namespace the enumerable and queryable classes are both members of the system.link namespace in the second part of this series we demonstrated examples using the select where join and group join operators we also discussed the difference between when a query is executed with deferred execution or immediate execution we discussed how a link query is executed with deferred execution but we can make the link query execute immediately by applying a two conversion operator to the query for example two list two dictionary or two array in the third video in this series we demonstrated code examples using the following link operators sorting operators order by order by descending then buy and then by descending grouping operators group buy and to lookup quantifier operators or any and contains filter operators of type and where element operators element at element at or default first first or default last last or default single and single or default in the fourth and final video in this series we demonstrated code examples using the following link operators the equality operator sequence equal the concatenation operator concat the set operators distinct accept intersect and Union the generation operators default if empty empty range and repeat operators the aggregate operators aggregate average count sum and Max the partitioning operators skip skip while take and take while the conversion operators to list two dictionary and two array projection operators select and select many in this video we also looked at code examples using the let and the N2 keywords I hope you have enjoyed this video series on using the Link Technology in c-sharp [Music] hi and welcome to the eighth part of this Advanced c-sharp course in this video we'll focus on the use of attributes and c-sharp for more content on advanced c-sharp concepts and much more please consider subscribing and please ring the bell so that you'll be notified of future content if you like this video at any point please consider giving it a thumbs up it will be greatly appreciated so let's discuss attributes attributes allow the developer to add metadata in a declarative way to program elements and code for example classes methods properties parameters Etc a declared attribute is instantiated into an object at runtime and at compile time we can declare attributes against program elements to provide additional metadata to relevant program elements the developer is also able to declare Global attributes against assemblies and a doing so add or modify metadata about the relevant assembly so the developer can use attributes to add or modify metadata about a particular program element or the assembly itself in this video we'll also briefly look at reflection reflection is a technology that we can use to read the metadata provided through the use of attributes at runtime we are then able to for example Implement codelogic based on the metadata provided through the use of attributes we'll look at how we can do this later in this video there are two broad categories for attributes predefined attributes and custom attributes predefined attributes are built into the baseclass libraries and net in this video we'll look at two main types of predefined attributes Global predefined attributes and general predefined attributes Global attributes like for example assembly version attribute and assembly description attribute facilitate adding and modifying metadata for an assembly General attributes lack for example conditional attribute obsolete attribute and attribute usage can be applied to appropriate program elements we'll start by implementing a code example using the assembly version attribute and assembly description attribute which are Global attributes we'll use reflection to read the relevant assembly metadata and output the assembly metadata to the console screen we'll then Implement a code example using the following General attributes conditional attribute obsolete attribute and attribute usage the attribute usage attribute will be declared on our own custom attributes that will create a bit later in this video we'll use custom attributes and reflection to implement field validation functionality we'll demonstrate how custom attributes can be created by creating classes that inherit from the built-in system.attribute class later in this video we are going to create custom attributes as part of validation logic that imitates how the asp.net MVC framework provides flexibility to developers through the use of reusable validation related attributes this video sets us up well for the next video provided by this channel which will be a demonstration of creating a basic asp.net MVC application on.net 5. right let's create our code examples so that we can gain an understanding of attributes in C sharp let's create a.net core console application project let's name this project attributes examples let's ensure that we are using.net 5 for this project if you haven't yet installeds.net5 please see a link below in the description where you are able to download the.net5 SDK note that you'll mostly be able to follow along even using earlier versionsoft.net but it is advisable to download.net 5 to follow along with this tutorial and future tutorials one of my core aims is to keep these tutorials right up to date please view a video created for this Channel about the significance of the release of.net 5. a link to this video can be found Below in the description so let's say that we wish to declare the assembly version Global attributes in our code we are able to do this by declaring This Global attribute between the namespace Declaration and the using directives okay so why can't I see the assembly version attribute in the intellisense drop down the reason is that the assembly version attribute is part of the system.reflection namespace so let's add a using directive to the system.reflection namespace and now we are able to see the assembly version attribute along with other Global attributes in the intellisense drop down list and we can now declare the global attribute against our assembly like this so here we are attempting to set our attribute version number to 2.0.1 through the Declaration of the assembly version Global attribute great so let's see what happens when we attempt to compile the code so we have a compile time error let's look at our error list to take a look at the details of this error the description of the error is duplicate system.reflection.assembly version attribute attribute so let's double click on the error item in our list that is causing the compile time error to occur okay so a new file is open and we can see a red squiggly line under the offending code it is a file that has a name that contains the assembly name followed by the suffix dot assembly info and we are able to find this file within our projects directory structure and if we look at the comments within this file it is clear that this file has been auto-generated it's in fact being Auto generated by Ms build let's navigate to this URL to read a bit about Ms build the Microsoft build engine is a platform for building applications this engine which is also known as Ms build provides an XML schema for a project file that controls how the build platform processes and builds software Visual Studio uses Ms build but Ms build doesn't depend on Visual Studio by invoking msbill.exe on your project or solution file you can orchestrate and build products in environments where Visual Studio isn't installed Visual Studio uses Ms build to load and build managed projects the project files in visual studio.csproge.vbproj.vcx project and others contain Ms build XML code that executes when you build a project by using the IDE Visual Studio Projects import all the necessary settings and build processes to do typical development work but you can extend or modify them from within Visual Studio or by using an XML editor so the basic point I'm trying to make here is that many of these Global attributes will be automatically declared in the assembly info file when compiling your code using the visual studio IDE you can gain access to some of these Global attributes through the visual studio IDE if you try to declare a global attribute as I have attempted to here you may get a compile time error because Ms build has automatically declared the global attribute in the assembly info file as we have seen this results in the duplication of the relevant Global attribute declaration which ultimately results in a compile time error occurring you are able to declare certain Global attributes and the way we tried to declare the assembly version attribute for example let's declare the assembly description attribute let's comment out the assembly version attribute declaration let's add our own assembly description metadata to our assembly through a declaration of the assembly description Global attribute let's pass a value of my assembly description to the Constructor of the assembly description attribute note that depending on how the relevant attribute has been written when the developer declares an attribute the developer is able to provide custom metadata to the relevant attribute through the attributes exposed public Properties or the relevant attributes Constructor parameters so we know that the purpose of attributes is so that we can add or modify metadata against certain program elements or even against the assembly itself note that attributes on their own do not change application Behavior the metadata provided through attribute declarations can be read at runtime through the use of reflection relevant metadata can then be evaluated by our code and appropriate code logic can be invoked based on the declared metadata so this is how the Microsoft docs describes reflection reflection provides objects of type type that describe assemblies modules and types you can use reflection to dynamically create an instance of a type bind the types to an existing object or get the type from an existing object and invoke its methods or access its fields and properties if you are using attributes in your code reflection enables you to access them right so let's use reflection to access and read certain metadata that has been added through the use of global attributes so we need a using directive to the system.reflection namespace which has already been included in our code so let's write some code in our main method let's get a reference to the current assembly we can do this by getting a reference to the program classes type and then assigning its assembly property value to a variable we have named our variable this SM referring to the current assembly we can then get the relevant assembly Name by using the assembly reference stored in the this assemb variable and calling its get name method and we can access the assembly's version information through that version property now we want to read the assembly's description which should be the description that we included when we declared the assembly description Global attribute to get a reference to the assembly description attribute we can call the get custom attributes method under this the same object and pass in the type of the attribute of interest to us note that we are using the type of method to get a reference to the object type of the relevant attribute remember attributes and C sharp are objects at runtime an object instantiated from the assembly description attribute class should be the first item in our object array we can use the as operator to cast the object to the assembly description attribute type if the casting operation fails now will be returned if the operation succeeds an object of the assembly description attribute type is returned let's write code to write out the metadata information about the current assembly that we have been able to retrieve through reflection to the console screen let's run the code great so we have looked at examples of global predefined attributes let's look at some general predefined attributes let's start with the conditional attribute let's first add a new standard Library project to our solution and let's name our project logging component let's remove the automatically created class named class 1 and add a new class named logging to our new project let's add a public static method to the login class named log to screen it contains one parameter named MSG and is defined as a string the code for this method simply outputs the value referenced by the MSG argument to the console screen let's declare the conditional attribute against the log to screen program element we have a red squiggly line because the conditional attribute as a member of the system.diagnostics namespace so let's add a using directive to the system.diagnostics namespace and now let's pass in an argument into the Constructor of our conditional attribute let's pass in the text log underscore info so what does log underscore info mean log underscore info is a piece of text that I've made up this text represents a symbol in our code we can use the Define preprocessor directive and include the log underscore info symbol in our code if the log underscore info symbol is defined using the preprocessor defined directive within a file containing method calls to the log to screen method the code within the log to screen method will be executed at runtime however if the predefined processor directive is not used to define the log underscore info symbol in the file where the log to screen method is called its code will not be executed at runtime because we have used the conditional attribute to declare to the compiler that we would like this Behavior to occur regarding the log to screen program element so the combination of the conditional attribute and the use of the Define preprocessor directive can act like a switching mechanism I.E using this mechanism we are able to switch certain code on or off this is especially useful for debugging purposes if this is not clear don't worry we will demonstrate what is meant here through a code example we are able to Define our log underscore info symbol through the use of a preprocessor directive we are going to use the Define preprocessor director for this purpose preprocessor identifiers are used to help in conditional compilation if we navigate to this URL we can see some of the preprocessor directives available in c-sharp for more information on pre-processor directives please use this section of the Microsoft docs as your guide so here we have the hash Define preprocessor directive that we can use to define a symbol in our code so let's see how we can use a particular preprocessor directive in conjunction with the conditional attribute to conditionally output information to the console Screen through our log to screen method we must add our appropriate pre-processor directive code right at the top of our program.cs file in our code editors like this to implement the desired functionality you can see we have the Define preprocessor identifier in this line of code as well as the log underscore info symbol that we made up and passed as text to our conditional attribute which was declared against the log to screen program elements let's include a using directive to our login component namespace in our main method let's make a call to the logging.log to screen method and pass in the following text as an argument to the MSG parameter this code is testing logging functionality let's run the code and as expected the appropriate text is written to the console screen so now let's see what happens when we comment out the relevant preprocessor directive code and run the code again and you can see that nothing has been outputted to the console screen using our pre-processor directive we can switch the execution of the code against which the relevant conditional attribute is applied on and off at compile time this functionality can be very useful for debugging purposes so let's say we have a change to our login component where we want all logging to be done to a text file rather than to the console screen and we want the consumers of our code to use the method that logs the information to a text file rather than to the console screen so how can we let the consumers know to use the log to file method rather than the log to screen method we can simply declare the obsolete predefined General attribute against the log to screen method let's create a public static method named log to file in the interest of time rather than writing the code to actually log the value passed into this method to a file let's just write code to Output the value to the console screen and pretend that it's method logs relevant text to a text file okay so let's declare the obsolete attribute against the log to screen method and let's pass a meaningful message to the Constructor of the obsolete attribute so we want any calling code that is currently using the log to screen method to receive the following warning message the log to screen method has now been deprecated please use the log to file method instead so now if we go to our main method we can immediately see a green squiggly line under the code that is calling the log to screen method and if we hover our Mouse pointers over the green squiggly line we can see that the text that we passed as an argument to the obsolete attribute is presented to us and note that if we want to force the user of our code to not use the log to screen method at all we can set a second parameter in the obsolete attribute to true if this value is set to True an error is flagged when a user attempts to use the deprecated method I.E the log to screen method now you can see that the green squiggly line has turned into a red squiggly line meaning that we no longer just receive a warning message we are receiving an error message this means we won't be able to compile the code the last predefined attribute that I wish to discuss is the attribute usage attribute we are going to create our own custom attributes and use reflection to read the relevant metadata added to relevant program elements through our custom attributes so reflection and attributes will be implemented to provide flexibility to developers using our custom attributes to declare how relevant Fields should be validated this code is going to be very similar to the code that the asp.net MVC framework implements for field validation in asp.net MVC we can declare certain validation related attributes against relevant program elements and the MVC framework automatically handles validation of relevant fields for us behind the scenes as it were in this code example however we are going to create the custom attributes used for declaring how we want relevant Fields validated and we will also write code using reflection to read the attribute data declared against relevant program elements in this case the program elements will be properties we will also write the validation code related to each of our custom attributes okay so let's add a new standard Library project to our solution let's name this project validation component let's delete the class that was automatically created by Visual Studio let's create a new folder named custom attributes let's add our first custom attribute class to the custom attributes folder let's right click the custom attributes folder and add a new class let's name this class required attribute note that we must include the attribute suffix and the class name of our custom attribute however when we declare our custom attribute you'll see that in the Declaration we can omit the attribute suffix from the attribute name we are however allowed to include the attribute suffix in our attribute declaration but functionally this is unnecessary we'll demonstrate this a bit later the code for this attribute is very simple let's create a public auto implemented property of type string named error message let's add code to a parameter-less Constructor whereby the error message property is set to a default value so let's say we want to default error message of you cannot leave field and then in curly brackets we have a zero followed by the word empty so the zero and curly brackets allows the relevant field name to be inserted into the message at a later time this is achieved through the use of composite formatting if you are not familiar with composite formatting regarding string values please view a tutorial created for this channel on C sharp strings a link to this tutorial has been provided Below in the description right let's create a parameterized Constructor this will allow the developer to pass in a custom error message when declaring the required attribute against the relevant program element the Declaration of the required attribute will be demonstrated a bit later in order for our class to be recognized as a custom attribute we must ensure that our class inherits from the built-in system.attribute class a custom attribute must inherit from the system.attribute class either directly as we are doing here or indirectly for example if our class inherited from another use a defined class that inherits from the system dot attribute built-in class so now all that is left to do is apply the predefined attribute usage attribute against our required attribute class like with the obsolete predefined attribute the attribute usage predefined attribute is a member of the system namespace basically the attribute usage predefined attribute allows us to provide metadata to the compiler that will tell the compiler which elements are allowed to have our predefined attribute declared against them so we can apply rules or constraints through the use of the attribute usage predefined attribute against our custom attribute at the class level this is an example of declaring an attribute against a class so in the first argument passed into the attribute usage attribute we can declare which program elements are allowed to be decorated with our custom attribute so if we have decided that we only want our custom attribute to be declared on the following program elements Fields parameters and properties we can declare this by passing in this code to the first parameter of the attribute usage attributes Constructor like this so here we are declaring which Target program elements are able to be decorated with our required custom attribute we can optionally set a property of type Boolean named allow multiple through our declaration if we set the allow multiple property to true this means multiple instances of our custom attribute can be declared against a single program element we only want one instance of our custom attribute to be declared against a single program element so let's set the allow multiple property to false we also have a property named inherited that we can optionally set through this declaration setting this property determines whether the relevant custom attribute is inherited by a derived class in this example we won't set this property and that's it we have now created our required custom attribute so let's create our next custom attribute let's add a new class file to our custom attributes folder and let's name this class string length attribute let's add three public auto implemented properties to our string length attribute class max length for the storage of an integer value denoting the maximum number of characters that a user can enter for a field related to a property against which the string length attribute has been declared error message for the storage of a string value denoting the message outputted to the user when the user has entered an invalid value into a field related to a property against which the string length attribute has been declared men length for the storage of an integer value denoting the minimum number of characters that a user can enter for a field related to a property against twitch the string length attribute has been declared so let's create a private method named set properties that we can reuse for setting our public properties this method will be called from a number of Constructor overloads that we'll Implement in a bit for this class this method does not return a value and contains three parameters that correlate to the public properties that we have already created the first parameter is max length which is defined as int second parameter is error message defined as string the third parameter has been length defined as a nullable integer the question mark symbol following the int keyword denotes that this parameter is nullable so it is a nullable value type parameter because it's defined as an integer which is of course a value type let's also make our Min length parameter optional we can do this in C sharp by simply assigning the relevant parameter a default value within the method definition like this so if a value is not passed into this parameter by default the Min length argument will have a value of null before we move on with our example let's go to the Microsoft dots specifically to this location to read a bit about nullable value types a nullable value type T question mark represents all values of its underlying value type T and in addition of null value for example you can assign any of the following three values to a bull question mark variable true false or null an underlying value type T cannot be a nullable value type itself very basically a null value means that a value for the relevant variable has not been set adding a question mark at the end of the value type definition for a variable or a parameter means we have the option of storing a null value in the relevant variable or parameter note that optional parameters must be included at the end of the parameter list in the relevant methods method signature okay so let's implement the logic for the set properties private method so firstly let's check to see if the error message argument contains an empty string if it does we want to set a default error message value in order for our error message to contain appropriate text depending on whether the Min length value is set we can create a nested if statement so if the Min length value is null let's appropriately set our default error message if the Min length value is not now let's include appropriate text relating to the Min length value within our default error message so if the developer does not pass in an error message when declaring the string length attribute against an appropriate program element a default error message will be used for the scenario where an error message value is set when the relevant attribute is declared against a program element the error message provided must be assigned to the error message public property of the attribute then let's set the max length property this is a property value that the developer must pass in when declaring the string length attribute against an appropriate program element less than assign the appropriate value to the Min length property so let's use a ternary operator to check if the Min length argument is null IE has not been set by the developer declaring the string length attribute against an appropriate program element if the Min length argument is null let's assign 0 to the Min length property if the Min length argument contains a value let's assign the value to the Min length property so let's create our Constructor overloads firstly let's create a Constructor that contains just the max length parameter then within our Constructor let's call our private set properties method to assign values to the appropriate public properties of the string length attribute class okay I also want to make the error message parameter in the set properties method and optional parameter we can do this by simply assigning default value to the error message parameter like this note that the parameter after the error message parameter in our parameter list is also the last parameter in the parameter list and is optional so it is perfectly legal to make our error message parameter optional remember the optional parameters must be included at the end of the relevant parameter list let's create Constructor overload that contains the max length parameter and the error message parameter then let's use our private set properties method to assign values to the appropriate public properties of the string length attribute class let's create a Constructor overload that contains the max length parameter and the Min length parameter let's use our private set properties method to assign values to the appropriate public properties of the string length attribute class note how we are passing in a value to the Min length optional parameter of the set properties method we need to be specific as to what parameter is being passed an argument here because in this case we are not passing in an argument to the error message parameter the fact that the error message parameter and the Min length parameter are both optional means in cases like this we have to make it clear which parameter we want to pass our arguments to let's create one more Constructor overload this Constructor overload contains the max length parameter the error message parameter and the Min length parameter let's use our private set properties method one more time to assign values to the appropriate public properties of the string length attribute class let's ensure that we include the code whereby our class inherits from the system.attribute built-in class so now let's declare the attribute usage predefined attribute against our string length attribute class so we can copy the attribute usage declaration from our required attribute class and appropriately paste it in to declare the attribute usage attribute against our string length attribute class great so we have now completed two custom attributes the required attribute custom attribute and the string length custom attribute let's create one more custom attribute this attribute will be responsible for indicating when declared against a program element that the input Fields value related to the relevant program element should match a specified regular expression pattern so regular expressions are great for defining patterns that an input field value must match for field types that must be constrained to a particular format like for example postcodes phone numbers credit card numbers email addresses Etc so the validation code for Fields like this will be simple if the relevant input field value matches the specified regular expression pattern the user's input is deemed as valid if however the input field value does not match the specified regular expression pattern the user's input is deemed as invalid we can implement the validation logic related to our custom attributes once we have completed the code for this final custom attribute so let's add a class to our custom attributes folder and let's name this class regular expression attribute let's create two public autoimplemented properties the first property named error message is of the string data type the second property named pattern is also of the string data type the pattern property denotes the regular expression pattern that must be supplied by the developer when the regular expression custom attribute is declared against an appropriate program element let's create two Constructor overloads the first Constructor overload contains one parameter named pattern the developer is able to pass an appropriate regular expression pattern argument to this parameter when declaring the regular expression custom attribute against an appropriate program element the error message argument is not passed into this Constructor but we can provide a default error message in this Constructor and assign it to the error message property let's create a Constructor overload this Constructor contains two parameters one denoting the regular expression pattern and the other denoting the error message so this Constructor allows the developer to pass in a regular expression pattern argument as well as a custom error message to a declaration when declaring this attribute against a program element so all we need to do within the Constructor is assign the public property members of this class with the appropriate values passed into the relevant Constructor as arguments let's ensure that we include the code whereby our class inherits from the system.attribute built-in class the last step is to appropriately declare the attribute usage predefined attribute against the regular expression attribute class this declaration will be the same declaration applied against our other two custom attribute classes so let's copy the appropriate declaration from one of our other custom attribute classes and appropriately paste the contents of our clipboards into our regular expression attribute plus file so now we have created three custom attributes implemented in three separate files the first custom attribute we created is named required attribute when this attribute is declared against an appropriate program element this means that the associated input field must not be left empty if it is left empty the field value is deemed as invalid the second custom attribute we created is named string length attribute when this attribute is declared against an appropriate program element this means the associated input field must contain a character length that falls within the boundaries defined by a specified minimum value and a specified maximum value the third custom attribute we created is named regular expression attribute when this attribute is declared against an appropriate program element this means that the associated input field must contain a value that matches a specified regular expression pattern so through the Declaration of one or more of our custom attributes a developer can express how a certain input field should be validated without the logic to implement the validation rules however these attributes are useless these custom attributes perform no functionality other than to add metadata to relevant program elements so the next step is to write the validation code we must write the validation logic that correlates with each of our custom attributes through the use of reflection we'll be able to read the metadata added to the relevant program elements through the use of our custom attributes the use of our custom attributes is for the purpose of declaring how validation logic is related with relevant program Elements which are also related to relevant input fields so let's write the relevant validation logic so to do this let's first add a new class named validation directly to the project node so we want this class to be separate from our custom attribute classes we are going to implement our own validation code in this class so we first want to create the validation logic that corresponds to each of our custom attributes the required attribute the string length attribute and the regular expression attribute let's encapsulate this functionality within three private methods let's first implement the validation logic that corresponds to the required attribute so let's create a private static method named field required is valid that returns a Boolean value this method contains one parameter let's name this parameter entered value and Define it as a string the logic for this method is basic if the entered value passed into this method as an argument is not null or empty return true because this means the user has entered a value which makes the input field entry valid if the code that returns true is not executed this means the entered value is invalid and false must be returned to the calling code let's implement the validation logic that corresponds to the string length attribute the method signature for this method is the same as the field required is valid method except we need to also pass in a field of type string length attributes to this method in addition to the parameter representing the entered value this is so that we can access the Min length and max length public properties that we implemented for the string length attribute class the values stored in these two properties are integral to the validation logic performed against relevant inputted values let's name this method field string length is valid so to implement the validation code let's Implement an if statement where the condition evaluates the entered value argument to see if its character length is greater than or equal to the Min length property and is less than or equal to the max length property if the character length of the entered value argument Falls within the range defined by the Min length and back length property values the entered value is valid so we can return true to the calling code if however the character length of the entered value does not fall within the specified range we must return false because the entered value is not valid so let's now implement the validation private method that corresponds to the regular expression attribute so the method signature is almost the same as the field string length is valid methods method signature let's appropriately name this method field pattern match is valid instead of including a parameter of type string length attribute let's include a parameter of type regular expression attribute this is so that we can access the public property named pattern which is a member of the regular expression attribute class for pattern property will contain the regular expression pattern against which we need to validate the entered value so let's use the reg X class to perform our validation logic this class is a member of the system.txt dot regularexpressions namespace so let's include an appropriate using directive the reg X class contains a public static method named is match we can use this method to validate the entered value against the relevant regular expression pattern if the is match method returns true this means the entered value is valid so we must return true to the calling code if however the is match method returns false this means the entered value is not valid and we must return false to the calling code okay so we have now implemented the validation logic that corresponds to our custom attributes let's create a public static method named property value is valid that returns a Boolean value this method is responsible for calling relevant validation code that is relevant to a specific program element and a user inputted value the validation code executed is determined by the custom attributes that have been declared against the relevant program element in the interests of keeping this code simple the code will only be relevant to a program element that is a property so the first item in the parameter list for the property value is valid method is a parameter of type type this parameter represents the type that contains properties against which our custom attributes may have been declared for example a user-defined type representing an employee record the next parameter represents the value that a user enters I.E an input field which is correlated to a particular property and needs to be validated by our code this parameter is appropriately named entered value the next parameter represents the program element which will be a property in this case that is a member of the type represented in the first parameter so for example the program element could be the first name property which is a member of a user-defined type named employee the last parameter for this method represents the error message that will be displayed to the user if the user's input is deemed as invalid we want to Output the error message value so let's include the out keyword in the relevant parameter definition let's implement the logic for this method firstly let's get a reference to the relevant program element so the program element in this example will be the property on which one or more of our custom attributes has been declared so for example if we are validating the first name property on the employee user-defined type the element name argument will contain the literal text first name which is the name of the first name property to get a reference to the user-defined type in this case employee the calling code would pass in type of employee this means we can use reflection to inspect the relevant program element to ascertain which custom attributes have been declared against the relevant program element using reflection we can then ascertain how we should validate the relevant entered value so let's write code to get a reference to the relevant program element which in this case will be a property reflection can be used to get relevant information about a program element we want to know in our code what custom attributes have been declared against the relevant program element so we can use the property info type which is a member of the system.reflection namespace to gain access to the property information that we need we must include a using directive to the system.reflection namespace let's Define a variable named prop as the property info type and let's assign a value returned from a call to a method named get property which is invoked on the type argument passed into the T parameter of this method note that we need to pass the element name argument to the get property method the element name argument will store a reference to the name of the relevant property we now have a reference to the relevant property information we can use the get custom attributes method to return a collection of custom attributes that have been declared against the relevant property we can assign The Returned value to an array of type attribute the get custom attributes method is returning a collection of type I enumerable and I want to store a reference to the relevant custom attribute objects in an array so let's use links to array extension method to convert the I enumerable collection into an array let's initialize the error message output parameter to an empty string let's write code to perform a for each Loop and loop through each attribute object declared against the relevant program element then within the for each Loop let's Implement a switch statement and use pattern matching code to get a reference to the relevant custom attribute objects so that we can perform appropriate validation on the entered value so the switch statement evaluates the type of each relevant attribute object using pattern matching using pattern matching we are able to get a reference to the attribute objects that have been declared against the relevant program element this is the magic of pattern matching in action pattern matching was introduced in c-sharp version 7. it allows the developer to write code to assess whether an object type matches the object type specified in a case statement if there is a match a reference to the relevant object is made available on the same line of the code as the case statement so here we have case required attribute if the object referenced by the att-r variable is of type required attribute the ra variable is assigned the value referenced by the att-r variable we are then able to use the ra variable in our validation code that resides within the relevant case block so we can call the appropriate private method for validating required fields that we implemented earlier to validate the relevant user entered value if the entered value is deemed as invalid we can output an error message to the user through the error message output parameter which has been appropriately marked with the out keyword meaning we can output a value through this parameter to calling client code if the relevant user input fails validation we need the property value is valid method to return false so let's include the other case statements pertaining to the other two custom attributes so let's implement the case block for the string length custom attribute and lastly let's implement the case block for the regular expression custom attribute great let's write the calling client code let's go to the.net core console project let's start by creating classes that can represent data models the first model will be a class that represents an employee record so let's create a new folder and name it models let's add a new class named employee to the models folder this class contains six autoimplemented properties ID as int first name as string last name as string phone number as string email address says string and postcode as string great so we are now going to appropriately declare our custom attributes against the properties we have just added to the employee class these attribute declarations will indicate to our validation code how the input values associated with the employee classes relevant properties should be validated let's include an appropriate using directive at the top of our code to the validation component dot custom attributes namespace so let's apply the required attribute to the ID program element notice how when we declare our custom attributes we don't need to include the attribute suffix so even though the class representing the required attribute is named required attribute when we declare the attribute against the relevant program element we can omit the attribute suffix so in this case we can declare the attribute using the name required let's declare the string length attribute against the first name property let's pass appropriate values to the Constructor of the string length attribute so let's say the maximum character length for the first name input field should be 15. our next argument is the error message we wish to Output to the user if the user enters an invalid value for the first name field for the last parameter let's say the user must enter a value for the first name field that has at least two characters let's declare the required attribute against the first name property so we can copy and paste the custom attributes declared against the first name property to the last name property now the phone number property will include the same attributes and settings applied against the first name and last name properties but we also want to validate the phone number against a regular expression pattern that can be used to validate UK phone numbers so let's navigate to this URL I find this website very useful for finding regular expression patterns let's do a search for UK phone numbers let's copy an appropriate pattern from our search results we can then appropriately pass this pattern as an argument to our regular expression custom attribute so let's appropriately paste our pattern into our code note that we may need to include the ad symbol preceding the string references of the regular expression patterns this is because the pattern may include backslash characters which need to be escaped because the backslash character is used by C sharp within strings for escape sequences for example the backslash n escape sequence denotes a new line within a string the backslash T escape sequence denotes a horizontal tab character within a string Etc so by including the at symbol preceding the string we are indicating that any backslash character should be interpreted as a literal backslash character and not as part of an escape sequence so let's apply the custom attributes for the email address property let's find an appropriate regular expression pattern and appropriately paste it into our code let's do the same for the postcode address let's say we need the postcode to be a valid UK postcode great so now let's build a basic front end so that we can test our validation code let's write a reusable private method that contains logic to prompt the user for a relevant field value we need this code to run within an infinite Loop which we can Implement using a do Loop once the user enters a valid value the code will break out of the infinite Loop the get input method returns true once the user has inputted valid data for the relevant input field we can use the out keyword to make the last field and output parameter where we can pass the valid data to the calling code foreign let's go to the main method and implement the calling code let's instantiate an object of type employee let's ensure that we have a using directive to the attributes examples.models namespace because of course the employee class is a member of this namespace let's create three local string variables amp ID first name and postcode we need to get a reference to the employee classes type we can do this using the type of method like this let's write codes to handle the user input for the employees ID so once the user has entered a valid value for this field the valid data can be assigned to the ID property the ID property of the employee type is an integer value so let's write code to convert the relevant string value to an integer value let's write code to handle the user input for the employee's first name field once the user has entered a valid value for this field the inputted value can be assigned to the first name property let's write code to handle the user input for the employee's postcode so let's write code so that once the user has entered valid information for the relevant Fields a message stating that the user has now entered valid data for the relevant employee is outputted to the console screen great let's test the code so if we press the enter key without entering an employee ID we get an expected output an appropriate error message is outputted to the console screen let's enter a valid ID great so if we leave the first name field blank and press the enter key we get an appropriate error message output to the console screen if we enter just one character for the first name field the string length validation code deems our input as invalid and an appropriate error message is output to the console screen so now if we enter a value for our first name field that contains a character length that falls within the character length range which is between 2 and 15. this input is deemed as valid if we leave the postcode field blank we are presented with an appropriate error message let's enter a valid UK postcode great just to demonstrate that we are able to reuse our custom attributes on other user-defined types let's create another model let's create a class to represent a department record let's apply some of our custom attributes let's go to our main method and test our code in the interests of time we'll only include the department short name field in our test here excellent so let's use a predefined attribute that already exists in a.net library so the attribute I want to use is named Json ignore so we want to add functionality to Output our employee object to the console screen in Json format using the Json ignore attribute we can choose which fields to exclude from our employee object Json output let's declare the Json ignore attribute against the phone number property and the postcode property let's go to our main method and write the code to serialize the employee object in Json format let's run the code and you can see that the Json output does not include the phone number and the postcode Fields great let's comment out the Json ignore attribute declarations so that we can include all of our property values for the relevant employee object in our Json formatted output okay so I accidentally inputted Bob's surname which is Jones for the postcode field and I've noticed that there is a bug in our code the error message format outputted to the screen isn't correct the validation was run correctly I.E clearly Jones is not a valid postcode but the error message itself is incorrect the xero wrapped in curly brackets in the appropriate code should serve as a placeholder for the property name of the property against twitch the relevant attribute has been declared the one wrapped in curly brackets should serve as a placeholder for the regular expression pattern specified for the purpose of validating that a postcode entered by the user is in a correct UK postcode format so I can see what is causing this issue we need to remove the dollar symbol preceding the error message specified in this Constructor we want to use composite string formatting and not string interpolation for this string value for details on composite formatting versus string interpolation please view a video on c-sharp strings created by this channel a link to this tutorial is available Below in the description so let's repeat the input that we specified in the previous test great the validation code is correct and the outputted error message is also correct okay but in our outputted Json text here the postcode field is null so it looks like we have another bug here all right so when I copied and pasted the code here I forgot to change the relevant code so that the postcode property is set to the user's input okay let's correct this and let's test the code again excellent we looked at how attributes are used in code to add metadata to program elements like classes methods properties Etc and reflection can be used to read the metadata added through the use of the attributes at runtime we discussed that there are two broad categories in c-sharp for attributes namely predefined attributes which are built into the.net Base Class libraries and custom attributes which allow the developer to implement the developer's own attributes by creating a class that inherits from the system dot attribute built-in class either directly or indirectly we created code examples using predefined Global attributes namely assembly version attribute and assembly description attribute this demonstrated how Global attributes can be used to add and modify metadata at the assembly scope we created code examples using predefined general attributes namely conditional attribute obsolete attribute and attribute usage attribute this demonstrated how we can add and modify metadata for program elements we then created our own custom attributes as part of codelogic used for the purpose of field validation the use of reflection was also employed as part of this code logic this code implementation imitates how the asp.net MVC framework uses attributes for field validation I hope you've enjoyed this video on using attributes in c-sharp in the next part of this course we'll create a basic asp.net MVC application where we'll use Technologies like attributes link and Entity framework along with front-end Technologies like HTML bootstrap CSS and more please consider subscribing for more content on Advanced c-sharp topics and much more and please ring the bell so that you'll be notified of future content if you liked this video please give it a thumbs up it'll be greatly appreciated please feel free to share this video with anyone you feel May benefit from its content I really enjoy reading your comments so please feel free to engage with me in the comments section as always the code created for this video can be downloaded from GitHub a link to the relevant GitHub repository is available Below in the description [Music] foreign [Music] [Music] hi and welcome to the ninth and final part of this Vance c-sharp course I was going to end the advanced c-sharp course with an example of creating an asp.net MVC web application using c-sharp the more I delved into writing the tutorial on asp.net MVC the more I realized that asp.net MVC at least demands its own video series so I'm currently working on a video series where we'll build an asp.net MPC web application using C sharp I'll bring these videos to you as soon as I can as I had originally intended I'm going to finish the advanced c-sharp course focusing on the topic of c-sharp reflection so let's get into it let's first gain a basic understanding of reflection and then we'll write a code example using the reflection technology and C sharp so what is reflection reflection provides objects of type type that describe assemblies modules and types you can use reflection to dynamically create an instance of a type bind the type to an existing object or get the type from an existing object and invoke its methods or access its fields and properties if you are using attributes in your code reflection enables you to access them for Content like this and much more please consider subscribing and please ring the bell so that you'll be notified of future content if you like this video at any point please give it a thumbs up it will be greatly appreciated in the eighth part of this Advanced c-sharp course on c-sharp attributes we use the reflection technology to read metadata provided through the use of our own custom attributes from relevant program elements when I say program elements I'm referring to classes methods Fields properties Etc so reflection allows the developer to access metadata within.net assemblies at runtime.net assemblies are self-describing entities which means the metadata data about the relevant assemblies reside within the assembly itself so at runtime we are able to load a Target assembly and read its metadata using reflection using reflection we are able to for example instantiate objects from classes that reside within the target assembly and invoke the relevant objects methods or get and set the relevant objects property values so in this video we are going to create a code example that will serve as a test harness we are going to create code that loads a Target assembly and displays a list of relevant classes that reside within the target's assembly we can then select an item in the relevant list that represents a class and test the functionality within each of the classes methods the important thing to note here is that in this example we will not reference the target assembly from within the project that contains our calling client code we are using reflection to late bind to the classes that reside within the target assembly so that we can instantiate objects and test the object's functionality at runtime note that when I refer to the Target assembly I am referring to the assembly that contains the functionality we wish to test through our test harness we will be using what is known as late binding to test the methods that reside within the relevant classes contained within the target assembly so what is late binding when we reference an assembly from a project through for example visual studio and subsequently write code to instantiate an object from a class that resides within the referenced assembly this is known as early binding when we reference an assembly like this the compiler has information about the target assembly at compile time light binding occurs when we don't set a reference to a Target assembly at compile time and we instantiate an object from a class that resides within the target assembly at run time the obvious disadvantage to late binding is that late binding is prone to runtime errors when early binding is employed the compiler has relevant knowledge for example relevant type information about the target assembly's constituents at compile time so compile time errors can be flagged and corrected at compile time potential errors are averted at compile time and therefore certain runtime errors are avoided with late binding reflection can be employed to gain necessary information about the target assembly itself and its constituents at runtime so let's create our test harness code example where we'll use late binding to test the functionality that resides within a Target assembly let's create a.net core console application named test harness let's creates.net standard Library project named utility functions the utility functions project will be compiled into our Target assembly now it is important to note that I have included the utility functions project which of course when compiled is compiled into a.net assembly in the same solution as the.net core console project where we'll write our calling client code this is important to note because we are not going to explicitly reference the utility functions assembly from the.net core console project so if we were to early bind to the utility functions assembly we would reference our utility functions project like this but let's cancel this dialog box because we are going to load the utility functions assembly at runtime using reflection we are not going to set a reference to it at compile time we want to late bind to the utility functions assembly at runtime this is obviously just a mark example and not a real world application but you can see how we could put a number of assemblies within a directory Traverse the assemblies within the relevant directory and automate the testing of functionality within the target assemblies at runtime we would not have to reference any of these assemblies within our test harness project because using reflection we can access all the information we need for each assembly and test the functionality within the assemblies so the advantage of this loose coupling of our test harness application with the assemblies that we are testing is that we don't need to early bind to the assemblies that compile time we can simply put an assembly or assemblies in an appropriate directory and our test harness application can learn about the assembly or assemblies at runtime by accessing the relevant assembly's metadata at runtime through reflection but we will simplify this example and focus on classes within a particular namespace within one target assembly our Target assembly in this case will be the utility functions assembly if this doesn't make sense to you at the moment please bear with me and this will become clearer as we progress with creating this code example let's include basic functionality within our utility functions project once completed this project will be compiled into an assembly which will serve as our Target assembly I.E the assembly against which will perform our reflection functionality through the use of reflection we'll be able to read relevant information about the assembly instantiate objects from its classes and test its methods so let's write the code for the utility functions assembly let's start by deleting the class that was auto-generated by Visual Studio let's add a class named basic utility functions within the basic utility functions class let's create four very simple methods let's create a method named write welcome message the right welcome message method contains no parameters and returns a welcome message as a string let's write a method named integer plus integer the integer plus integer method contains two integer parameters and returns an integer value The Returned integer value will be the mathematical result of the first integer argument plus the second integer argument we can appropriately name our parameters operand 1 and operand 2 respectively let's write a method named concat three strings this method contains three string parameters and returns a string value The Returned string is a concatenation of the arguments passed into the concat three strings method the order in which the string arguments are concatenated is the order in which their corresponding parameters appear in the relevant parameter list from left to right let's write a method named get string length it contains one string parameter this method returns an integer value the character length of the string argument passed into the get string length method and that's it that is our very basic basic utility functions class completed let's create another basic class let's name this class basic math functions let's create two really simple methods in this class let's create a method named divide operation which contains two parameters of type double this method returns a value of type double that is the result of a divide mathematical operation in this method the second argument is divided into the first argument and the result of the Divide operation is returned to the calling code let's create a method named multiply operation which contains two parameters of type double this method returns a value of type double that is the result of a multiplication mathematical operation where the first number argument is multiplied by the second number argument the return value will be the product which of course is the result of the multiplication of the first number argument by the second number argument okay so we now have two classes in our utility functions project so now we want to be able to decorate certain program elements with a custom attribute that we can use to provide additional information to the calling code about the relevant program elements in this case the program elements will be classes and methods let's create a custom attribute named information attribute for more information on custom attributes please view the previous part of this course which is a tutorial entitled c-sharp attributes I have included a link to the relevant video Below in the description so in order to create a custom attribute the relevant class must inherit from the system.attribute built-in class let's keep this class really basic so let's add one Auto implemented property named description this property will enable us to provide a custom description about a program element that we'll decorate with our information attribute custom attribute we want to constrain our information attribute custom attribute to the decoration of only class and Method program elements so we can do this by decorating our information attribute custom attribute class with the attribute usage built-in attribute we can then pass the following bitwise operation to the Constructor of the attribute usage built-in attribute so let's pass attributetargets.class or attribute targets.method to the Constructor of the attribute usage built-in attribute so this means that only classes and methods can be decorated without information attribute custom attribute so next let's apply our custom attribute to the relevant classes and methods let's go to the basic utility functions class and let's decorate the class itself and its methods with the information attribute custom attribute so let's set the description property for our custom attribute declared against the basic utility functions class to this class contains basic utility methods let's set the description property for our custom attribute declared against the right welcome message method to this method returns a welcome message let's set the description property for our custom attribute declared against the integer plus integer method to this method Returns the sum of two integer operands let's set the description property of our custom attribute declared against the concat three strings method to this method concatenates three strings in the same order as they appear in the parameter list from left to right let's set the description property for our custom attribute declared against the get string length method to this method Returns the character length of a string argument so let's move on to our basic math functions class let's decorate the basic math functions class with our information attribute custom attribute like this so here the description property is set to this class contains basic math functionality let's decorate The Divide operation method with our custom attribute where the attributes description property is set to this method divides the first number by the second number and returns a result of this divide operation and lastly let's decorate the multiply operation method with our custom attribute and set its description property to this method multiplies the first number by the second number and returns a result of this multiplication operation so we have included in the metadata for our utility functions assembly very basic descriptions about method and class program elements through the use of our information attribute custom attribute now let's write the calling client code so in the calling client code we want to provide functionality that targets a particular namespace within the target assembly in this case our Target assembly will be the utility functions assembly and reads all the relevant information about the assembly's classes and methods that are members of the relevant namespace we'll create functionality where the user can choose a class from a list of classes that reside within the relevant namespace once the user has chosen the class that the user wishes to test the user can then choose a method from a list of methods that are members of the relevant class the user can then select from a list of methods the method that the user wishes to test once the user has chosen the method that the user wishes to test the user is prompted for values for each of the parameters contained within the relevant methods method definition once the user has provided values for all the relevant parameters our code will invoke the method and the result returned by the method is displayed to the console screen so you can see that this test harness application can be used to test functionality within an assembly note that you can extend the code that we are about to write to Traverse a number of assemblies within a directory and automatically test particular functionality within the assemblies so you could write your own automated test facility based on the code we are about to write for the purposes of this tutorial however the code will be simplified so let's write the code for our test harness project which is our.net core console project the first thing to do is within our calling client code is include a using directive to the system.reflection namespace like this so that we can make use of reflection in our application so let's start writing our code in the main method let's first create two local string constants the first constant stores the target assembly file name utility functions.dll the second constant stores the Target namespace that contains the classes that the user will be able to test through our test harness application so the namespace is utility functions let's write the code that will load the target assembly at runtime so we are using the assembly.load method to do this but we may need to replace this with the assembly.load file method when we test and debug the code later in the tutorial we'll know which method needs to be employed here either the load or load file method so we'll leave it as load at this point we pass in the path of where the target assembly will be in order to load the target assembly into memory so later in this tutorial just before we test our code for the sake of Simplicity we'll copy the target assembly into the same directory as where the assembly for this project will reside so let's write code here to point to the path of the target assembly which will be the current directory the same directory as where the test harness assembly will reside let's use the path.combine method to combine a path with the name of the file the path class resides in the system.io namespace so let's include a using directive to the system dot IO namespace so we are able to get the current path from the appdomain.current domain dot base directory property this is the directory where the assembly that we are currently working on will reside let's pass this value as the first argument to the path.combine method then let's pass the name of our Target assembly which is utility functions.dll as the second argument into the path.conbind method the return value from the assembly.load method will be the object of type assembly so let's assign a variable of type assembly the value returned from the assembly.load method so we have now got a reference in memory to our Target assembly let's write code to get a list of classes from the target namespace within our Target assembly so the namespace within our Target assembly is named utility functions so let's use Link to get a list of types or classes from within the utility functions namespace let's ensure that we have a using directive to the system.link namespace so we can use the assembly objects get types method to return a collection of classes that reside within the target assembly we can use the where method to filter on the assemblies utility functions namespace like this let's assign The Returned result to a generic list that is strongly typed as system.type then let's convert the innumerable collection returned by the link query to a list and we can do this by using the to list conversion method like this let's write a method that encapsulates writing a prompt to the user let's write code to display a message prompting the user for input to the console screen as you can see we are prompting the user to press a number key to indicate to the application which class the user wishes to test so it is better to encapsulate this prompting functionality in a method that we can reuse for this purpose throughout the creation of this application this method encapsulates the functionality of displaying text to prompt the user for input to the console screen so next we want to write code to display a list of classes to the console screen so that the user can select a class that the user wishes to test so we can simply write code that traverses the items stored in the classes list which contains the result of our link query and output the relevant class names to the console screen in sequential order so let's do this in our list of classes each class name is preceded by a number which will allow the user to press a number key to select the class that the user wishes to test let's write the code where the user can press a number to select a class from the classes list let's use a switch statement to return the relevant item from the list so now we want to create an object instance from the user's chosen class or type we can use the activator.create instance method to do this and here we are writing code to late bind to a class within the target assembly we can assign The Returned object from the activator.create instance method to a variable of type object you can see that when we like bind like this we do not have the benefits of type safety so code like this is prone to runtime errors this highlights a disadvantage of late binding like this in code so because at compile time we don't know the type that will be returned at runtime by the activator.create instance method we need to use a variable of type object to reference The Returned value so we have now written the code enabling the user of our application to choose a class from a list of classes by pressing a number key associated with the relevant class once the user has chosen a class the user will be presented with a list of relevant methods let's write code to clear the screen once the user has chosen the class from the list of classes let's write a method where we can encapsulate code to Output a heading to the console screen on the screen that displays a list of methods belonging to the class that the user has selected we want to include a heading at the top of the screen containing the class name that the user has chosen let's go to the main method and write the code to Output the relevant heading to the console screen let's write code to prompt the user to choose from a list of relevant methods we now want to write code to Output a list of relevant methods to the console screen so logically the code to present the user with a list of methods is exactly the same as the code that presents the user with a list of classes so we have an opportunity here to refactor our code by creating a reusable method that encapsulates functionality to Output a list of both classes and methods so this will be one block of code that can output a list for both classes and methods in this method we need to account for the difference between the type representing a class and the type representing a method in this context classes are of type system.type and methods are of type method info so to solve this problem we can apply generics let's create a method named display program element list let's include the T placeholder between greater than and less than symbols to indicate that this is a generic method let's base the code for this method on the code that we have already written in the main method to Output a list of classes you can see that we are writing this code in a more generic style because this code will output the items of a generic list that is strongly typed as system.type and a generic list that is strongly typed as method info great so let's replace the code in the main method that outputs a list of classes with a call to our display program element list method the type that represents a class in terms of reflection is system.type we have another opportunity to refactor our code because the code to return an object of type system.type from our list of classes or types logically is the same as the code to return an item of type method info from a list of methods so let's write code to encapsulate this functionality in a method named return program element reference from list so we need to include generic functionality within the method definition of the return program element referenced from list method we also need to return a value of type T from this method and we can copy the code for this method from our main method and paste it into our return program element reference from list method so let's replace the code in our main method that enables the user to choose from a list of classes with a call to the return program element reference from list method so let's call the get methods method on the type Choice object which represents the class that the user has chosen from the relevant list and assign The Returned value to a generic list that is strongly typed as method info note that a generic list that is strongly typed as system.type is used to store references to classes or types and a generic list that is strongly typed as method info is used to store a list of methods we can now reuse the display program element list method in our main method to display a list of methods we can pass in the method info type to the relevant type parameter but we don't actually need to do this here because the compiler has enough information to determine the type let's call the return program element reference from list method which will enable the user to choose a method from a list of methods displayed to the console screen let's write an if statement to check if the method info object returned from the return program element reference from list method is not null let's write code to clear the screen let's write code to Output a heading containing the class name and the method name of the class n method that the user has chosen to test so the next step is to prompt the user to provide a value for each parameter of the relevant method so we are able to get a list of parameters from the relevant method by implementing the method info objects get parameters method like this and we can assign The Returned result to an array of type parameter info the next step is to invoke the method chosen by the user and pass in the relevant parameter values that will be provided by the user's input I.E if the relevant method contains any parameters if the relevant method does not contain any parameters the method can be invoked without any arguments passed to it so let's encapsulate the functionality for this in a method named get result in order to execute the functionality for the get result method we need the relevance class instance object the relevant method info object and the array containing the relevant array of parameter info objects so in the get results method definition let's include a parameter of type object to accommodate the class instance let's include a parameter of type method info to accommodate the relevant method to be executed and let's include a parameter that accommodates an array of type parameter info so the invocation of our method is going to be different in terms of code implementation when the method that is invoked requires a number of arguments to when the method requires no arguments passed to it I.E the relevant methods method definition contains no parameters so let's create an if statement that checks to see if the parameter's argument contains any items if it does not contain any items we can call the method info objects invoke method and pass null into the second argument the first argument must be passed an argument that references the appropriate class instance this class instance or object contains the method that we are invoking here through this line of code the else part of the if statement invokes a method that does contain parameters so we must write code to prompt the user for a value for each parameter so let's create a method that allows for an argument which will contain an array of parameter info objects to be passed to it so let's name this method return parameter value input as object array let's create a one-dimensional array named param values and provision the array to hold a number of items equal to the number of items stored in the array passed into this method I.E the array of type parameter info let's create a counter variable named item count and initialize it to a value of zero let's create a for each Loop to Loop through each item in the parameters array let's write codes to prompt the user to enter a parameter value so let's say that we know that the parameter type can only be one of the following string int or double so let's write an if statement to check the type of the relevant parameter if the parameter is a string then no type conversion of the console.redline method value is necessary because this method returns a string so we can then write code to assign the user's inputs to the relevant position in the parameter values array so the code for when the relevant parameters of type int or double is slightly different we must include an explicit type conversion from string returned by the console.readline method to the relevant type before assigning the inputted value to the appropriate position in the param values array we must increment the item count variable by 1 for each iteration of the loop in the location in our code editors where the loop has exited we can write the code to return the param values array to the calling code great so let's go back to the get result method and call the return parameter value input as object array method then we can write codes to invoke the relevant method and pass in an array argument containing the user's input for each parameter as the second argument to the method.invoke method like this as stated earlier the first argument passed to the invoke method is the relevant instantiated object instantiated from the class that the user has chosen to test to finish this method off let's write the code to return the result returned by the relevant method to the calling code let's then go to the main method and call the get result method let's write the code to display The Returned result from the get result method to the console screen great before we test the code let's compile our two projects let's find the targets assembly and let's copy the assembly to our clipboards then let's go to the directory of our test harness project and paste the target assembly into this directory Let's test our code okay so we have a little bug here so I suspect this is because we need to use the load file method instead of the load method so let's change the code accordingly let's run the code again great we can see our class is displayed in a list but our information attribute custom attribute class is also present in the list and this is not desirable we don't have any methods in the information attribute custom attribute class to test so if we select one of the classes that we wish to test like for example the basic utility functions class we are presented with a list of methods which is great there are some methods listed here that we are not interested in testing like for example the equals method or get hash code method these methods belong to the object class which as we know is ultimately the base class for all types in C sharp so we only want to test the methods that perform functions directly related to the class we have selected in this case the basic utility functions class we'll modify the code to filter out undesirable code elements in a bit for now let's continue with our test let's select the integer plus integer method oh we should be receiving a prompt to enter a value for each of the parameters contained within the integer plus integer method so we have another bug to fix so here's where we need to fix the bug I forgot to include the prompt text in the return parameter value input as object array method so let's include a prompt for each parameter item foreign Let's test the code again let's select the basic utility functions class from our list of classes let's select the integer plus integer method so we are now prompted to enter a value for the first parameter great so let's do that let's enter five we are then prompted to provide a value for the second parameter let's enter a value of 6 for this parameter once we press the enter key the correct result of 11 is presented to us great so except for the fact that certain program elements that we have no desire to test are appearing in our lists the basic functionality of our test harness is working as expected so let's write the code to filter out those unwanted program elements we are going to use the information attribute custom attribute for this purpose let's say that we only want those program elements that are decorated with our information attribute custom attribute to appear in our lists of program elements to test so let's write a method that checks the CFA program elements iea class or a method is decorated with the information attribute custom attribute if the program element is decorated with the information attribute custom attribute we want to include the relevant program element in our list of program elements to test if however the program element is not decorated with the information attribute custom attribute we must exclude the relevant program element from our list of program elements to test so let's write a private static method named has information attribute and let's include one parameter within its method definition this parameter will represent the program element that we need to check so we need the has information attribute method to check if the information attribute custom attribute has been declared against the relevant program element in the context of the requirement of this application the program element can either be a class or a method so the parameter must be of a type that can accept a class or a method as an argument in this particular case those types will either be of type system.type or of type method info we could include two methods named has information attribute and differentiate their method definition where each method definition contains a parameter of a different type one version of the has information attribute method can contain a parameter of type system.type and the other version of the method can contain a parameter of type method info so we could use method overloading to perform the desired check for if a custom attribute has been declared against a program element I.E either a method or a class however we can achieve what we want with only one version of the has information attribute method because the system.type and Method info types both inherit from a common class the member info class if we right click the text in our code editors representing the type class and select go to definition we can see that the type class inherits from the member info class if we do the same thing against the method info class we can see that the method info class also inherits from the member info class if we look at the member info class definition we can see that it contains a method named get custom attributes and this is the method we need to use to check if the relevant program element is decorated with the information attribute custom attribute so the point is we don't need to overload the has information attribute method we can simply Define the parameter for the has information attribute method as member info in one method this will mean we can pass both types of arguments to the has information method I.E an argument of type system.type a class program element or an argument of type method info a method program element so let's look at the code for the has information attribute method we have created a local string constant to store the name of the type of our information attribute custom attribute so this name includes the namespace of where the information attribute custom attribute resides a full stop and the attribute class name we have written code to Loop through all the custom attributes that may be declared against the program element type passed into this method as you can see we are able to call the get custom attributes method for both class and Method program elements in our method because the system.type class which represents class program elements and the method info class which represents method program elements both inherit from the member info class which contains the get custom attributes method within our for each Loop we first get the type of the current attribute so we have written type attrib equals attrib the current attribute object dot get type we then check to see if the name of the type attribute is equal to the information attribute custom attributes name if it is this means that the information attribute custom attribute has been declared against the program element type passed as an argument to this method so we can return true to the calling code if all attributes have been traversed and none of the attributes match our information attribute custom attribute this means that the program element passed as an argument to the method does not have our information attribute custom attribute declared against it so we must return false so this method can be used in our calling code to filter out program elements based on whether or not the relevant program element is decorated with the information attribute custom attribute so how can we use our method for this purpose in our main method the answer is we could modify the relevant link queries to include our has information attribute method and we can include our has information attribute method in the relevant where filters so let's first modify the link query for returning a list of class program elements we can simply include a call to our has information attribute method in the where filter method like this to filter out methods that aren't decorated with the information attribute custom attribute we can modify the appropriate link query like this Let's test our code excellent you can see that only those classes in our Target assembly that are decorated with the information attribute custom attribute appear in the relevant list if we select the basic math functions class from our list of classes we can see that its methods that are not decorated with the information attribute custom attribute have been filtered out of the relevant list great let's also include functionality to appropriately outputs to the console screen the description property value of the information attribute custom attribute for our relevant program elements in terms of the user's experience this functionality will provide additional information about the classes and methods that the user wishes to test so let's write a private static method named return information custom attribute description this method returns a string and contains a parameter of type member info remember both the system.type class and the method info class inherit from the member info class so this method can be reused for both class and Method program elements we want to read the description property so let's create a local string constant that references the text description let's create a for each Loop that Loops through the custom attributes that may have been declared against the relevant program element which in this case will either be a method or a class So within the loop let's reference the attribute type like this we can then apply an if statement to check if the current attribute is the information custom attribute okay so let's refactor our code here so that the target information attribute type constant can be accessed from both this method and the has information attribute method if the current attribute is the information custom attribute then let's access its description property we can do this using reflection like this so we are attempting to check if the property info object is not null but the compiler is complaining this is because the project is currently built on.net core version 3.1 checking for nulls like this is only allowed in a later version of C sharp so I'm going to change the version of.net.net5 for this project great and you can see now that this line of code is Now supported I.E using the is not null line of code but I'm going to use the old way of checking for nulls anyway just in case the followers of this tutorial are using an older version of.net for their projects so we have now written the code to read the description property from objects derived from the relevant information custom attributes that have been declared against relevant class and Method program elements so let's write the code to appropriately output the program element descriptions declared through the use of our information attribute custom attribute to the console screen let's create a method named display element description for this purpose this method only needs one parameter which will be the text we wish to Output to the console screen let's write code to check if the argument passed to this method is not null if it is not null let's write its value to the console screen using a different background and foreground color to the default console screen colors so that the text stands out then let's use the console.resetc color method to reset the color back to the default console foreground and background colors let's go to the main method and use the display element description method to Output the relevant program element descriptions to the console screen so we can pass the result of the return information custom attribute description method into the display element description method on one line like this this code will display our custom descriptions of the program elements that the user wishes to test Let's test the code okay so we are getting a bug and this is because the load file method cannot find the target assembly the reason for this is because when we changed our version of.net for the test harness project a new directory for dotnet 5 was created this directory contains the assembly for the test harness project but it doesn't of course contain the target assembly so let's copy the most recently built utility functions assembly to the net 5.0 directory let's run the code again and you can see that our custom elements are displayed and we are able to test the functionality of methods and classes that reside within our Target assembly we have used the reflection technology to accomplish this you can also see that additional information about the relevant program elements is outputted to the console screen this was made possible through the use of our information attribute custom attribute excellent to finish off the application let's add code to enhance the user's experience as you may have noticed once the user has tested a method the application automatically ends we currently have no way of navigating back to the first screen where we are presented with a list of classes that we may wish to test we want the user to have the option of returning to the list of classes so that the user can carry on testing other classes and methods so we can do this by putting the relevant code within an infinite Loop once the user has tested a particular method the user can either press let's say the spacebar key to end the application or any other key to return to the screen that contains a list of classes Let's test the code foreign excellent so the last thing I'd like to bring to your attention is the technology encapsulated in the system.reflection.emit namespace using this technology a developer is able to generate code dynamically so the developer is able to generate Dynamic methods or even Dynamic assemblies on the Fly the user could for example generate Intermediate Language code on the Fly based on user input so because of functionality like this you can see how incredibly powerful the c-sharp language is I recommend navigating to this location to read more about this powerful aspect of reflection I hope you've enjoyed this tutorial on c-sharp reflection we have now come to the end of this Advanced c-sharp course if you've got this far congratulations this channel now provides two complete in-depth courses on features of the c-sharp language a beginner's course and an advanced course the next series of videos will focus on the asp.net MVC framework where we'll build an application in c-sharp using the asp.net MVC framework on.net 5. during this time I will also produce other videos relating to c-sharp and other Technologies so let's end this video by summarizing what we have learned about c-sharp reflection reflection provides objects of type type that describe assemblies modules and types you can use reflection to dynamically create an instance of a type bind the type to an existing object or get the type from an existing object and invoke its methods or access its fields and properties if you are using attributes in your code reflection enables you to access them we demonstrated using reflection to create an application that can serve as a test harness the test harness allows the user to add a target's assembly to the same directory where the test harness application resides and choose a class that the user wishes to test from a list of classes that belongs to a specific namespace that resides within the target assembly when the user selects a specific class from the class list that class is instantiated into an object through the use of late binding this is how the test harness is able to test the functionality within a Target assembly without referencing the target assembly at compile time in the test harness application reflection is employed to instantiate the relevant class into an object when an assembly is referenced by a project at compile time this is known as early binding with early binding the compiler has relevant information about the types within the target assembly at compile time late binding is used when the compiler does not have compile time knowledge of the target assembly so a technology like reflection is used to access the relevant information about the assembly which allows for late binding to occur at runtime it was noted that late binding has the disadvantage of being prone to runtime errors when early binding is employed a specific type can be instantiated into an object using the new operator and we have the advantage of compile time type safety we do not have the advantage of compile time type safety when late binding is employed in code and the activator.create instance method is used to instantiate an object from a type lastly we briefly discussed the technology encapsulated within the system.reflection dot emit namespace functionality for generating Intermediate Language code or IL code dynamically resides within the system.reflection.emit namespace a developer can use the functionality within the system.reflection.emit namespace to create code for dynamically generating methods and even assemblies at runtime for Content like this and much more please consider subscribing and please ring the bell so that you'll be notified of future content if you like this video please give it a thumbs up it will be greatly appreciated please feel free to share this video with anyone you feel May benefit from its content I really enjoy reading your comments so please feel free to engage with me in the comments section the code created in this tutorial can be downloaded from GitHub a link to the relevant GitHub repository has been included Below in the description thank you and take care let's go back in time to the end of February 2002 with the first release of the.net framework this is when c-sharp was first released it is a new fully object oriented general purpose programming language Visual Basic through its donut Evolution has been upgraded from a largely event-based language tightly coupled with the visual Basics 6 IDE to a new object-oriented version of itself called visualbasic.net a managed version of C plus could also run within the.net sphere new languages like F sharp which was first released in 2005 could also run within the.net environment these languages are all interoperable which essentially means for example a c-sharp application can consume a.net component written in Visual Basic or an application written in Visual Basic can consume a component written in C sharp what makes this possible is the common Intermediate Language or Cil all high-level.net programming languages like c-sharp Visual Basic C plus plus Etc are first compiled into the common Intermediate Language before further compilation into machine Language by the common language runtime all code that runs within the.net runtime is considered managed code the.net runtime also makes available a number of libraries that can be leveraged by our custom.net code this is essentially done through a library of files called the framework class libraries or the abbreviation of this fcl which provide generic functionality for our applications to consume the common language runtime or CLR can be described as the.net virtual machine and provides services like just-in-time compilation memory management security and exception handling it is important to note that the.net framework will only run on appropriate Windows operating systems and must be installed in its entirety on the target computer there have been many versions of the.net framework released since its Inception and they are able to run side by side on the same computer the latest version of the.net framework at the time of writing this tutorial is.net framework version 4.7 let's go back in time again to June 2016 when the first stable version of the.net core runtime was released it can be described as a cross-platform or agile modularized lightweight version of the.net framework it supports appropriate standards so that multiple languages can run and be managed within the.net runtime and also provides language interoperability core language compiles into the common Intermediate Language or Cil net core provides some of the standard framework class libraries which can be called The Core FX and can be described as a partial Fork of the framework class libraries dotnet calls virtual machine can be referred to as core CLR or core common language runtime and it provides services like improve just-in-time compilation memory management security and exception handling unlike the.net framework.net core can run on Mac OS Linux as well as Windows dotnet core also provides a modular framework so that only the modules that your application uses are shipped with your application an important difference between.net core and the.net framework is that you no longer need the entire.net framework installed on the target computer but only those components of the.net runtime that your application needs this is why.net core is often referred to as a more agile version of the.net framework.net core is open source software which makes things like the bug fix release process more efficient it is optimized for the cloud it is designed for high performance provides a great base for microservice architecture [Music] it is designed to be highly scalable dot net core is definitely a significant evolution of the.net runtime but it must be noted that it does not replace the.net framework please see in the description below a URL for a Microsoft docs webpage containing recommendations for when to use the.net framework and when to use.net core as the.net runtime for your server applications net 6 completes the unification of the platform and adds new capabilities for building web native and hybrid apps for Linux Windows Mac IOS and Android with a single code base this video is an overview of what to expect with the release of net 6 which is due to be released on the 9th of November of this year 2021 for Content like this and much more please consider subscribing and please ring the bell so that you'll be notified of future content please feel free to share this video with anyone you feel May gain value from its content before I give a brief summary of what new features and improvements to expect with the release of.net 6. I'd like to present you with a brief summary of my personal experiences as a developer with the technological innovations that have been made over the years I remember working as a young developer in the late 90s on Enterprise web applications when I look back I'm proud of what we were able to achieve using what is now known as classic ASP or classic active server Pages classic ASP was introduced as Microsoft's first server-side scripting technology for creating web applications the ASP files were coded in vbscript I remember we wrote our business logic in Visual Basic and compiled our code into com components we then installed our com components in an environment known as MTS Microsoft transaction server the Microsoft component object model com and Microsoft transaction server MTS later evolved into com Plus using active server Pages our code was written in vbscript and we would call our com components from our active server pages com plus handles many of the resource management tasks that previously needed to be programmed by the developer such as thread allocation and security active server Pages allowed a developer to implement codelogic using vbscript and output HTML client-side JavaScript and CSS code to the client's browser so back then we typically created our applications using a three-tier architecture classic ASP contained code and logic to Output HTML code JavaScript and CSS to the client's browser com components that contained business rules ran and MTS later known as complex SQL server was used for our backend storage facility [Music] in the early 2000s I moved to London my move to London coincided with the first release of c-sharp and net net was a gigantic step forward for Microsoft Technologies Visual Basic 6 was the last version of Visual Basic before the dramatic change that was to follow in the form of.net.net was a complete rethink Visual Basic was still offered as a language but instead of being limited to being a largely event-based language tightly coupled with the Visual Basic 6 IDE was now known as visualbasic.net and is a fully object-oriented programming language the first version of.net was named.net framework programs written in.net framework executed in a software environment in contrast to a hardware environment the software environment is named The Common Language runtime CLR a number of class libraries called the framework class libraries are built into.net framework and are available to be consumed by.net applications developers can produce their software by combining their source code with.net framework class libraries so.net framework provides a library of classes that can be leveraged from our applications net applications run in an environment known as the common language runtime or CLR which can be described as the.net virtual machine and provides services like just-in-time compilation memory management security and exception handling so.net framework provided developers with a sophisticated environment that would revolutionize the developers experience in the early 2000s I was now working on web applications using a.net version of active server Pages known as asp.net and I was able to write my code using a new fully object-oriented programming language known as C sharp so in the early 2000s the introduction of.net was a massive leap forward.net framework was interoperable meaning you could write code in any language that supported the common type system so we could write our applications using for example c-sharp visual Basics C plus Etc this was great but NET Framework could only run on Windows platforms and required a monolithic installation NET Framework does not run on Linux or Mac OS mono was released on June the 30th 2004. mono is a free open source implementation of microsoft's.net framework based on the ecma standards for c-sharp and the common language runtime mono was a version of.net that could run on multiple platforms mono can run on Windows Mac OS and Linux on June the 27 2016 the first version of.net core was released .net core is the.net successor to.net framework .net core is primarily developed by Microsoft employees by way of the.net foundation and released under the MIT license .net core supports the use of nuget packages.net core can be described as a lightweight modular cross-platform and more agile version of.net framework to prevent future fragmentation of.net implementations.net standard was introduced the motivation behind.net standard was to establish greater uniformity in the.net ecosystem net standard is a formal specification of net apis that are available on multiple.net implementations the specification is maintained by.net implementers specifically Microsoft includes.net framework.net core and mono and unity.net 5 was a significant release of.net and was released on the 10th of November 2020. Net 5 is the first release of a version of.net that attempts to unify all features of all versionsoft.net under one implementation of.net the idea behind this vision of.net is to have one.net moving forward that can Target Windows Linux Mac OS iOS Android TV OS watch OS and webassembly and more dotnet 5 is the future of.net core and is almost a complete reimagine of the old.net framework in fact Net 5 is the first major update since the 2016 release of.net core dotnet 5 was a direct Evolution from.net core 3.1 and the reason why it was called.net5 and not.net4 is because the last release of.net framework was version 4.8 which was released on July the 25th 2019. both.net core and framework were maintained in parallel allowing you to choose between one or the other you could leverage.net standard to make shared libraries between the two the release of.net 5 meant that.net framework will be deprecated this means you can only use.net framework as long as your operating systems for example Windows Server 2019 will support it so.net 5 was the first step forward to unified.net and finally we get to the release of.net 6. the main significant aspect of net 6 is the fact that it delivers the final parts of the.net unification plan that started with dotnet 5. here is a brief overview of the new features and improvements that we can expect with the release of.net 6. C sharp version 10. the significance of version 10 of c-sharp and future versions of c-sharp that are to be released in line with each new version of.net is that the developer can write less code with the evolution of c-sharp there's a strong focus on simplification much of the boilerplate code that needed to be written when using previous versions of c-sharp do not need to be written when using c-sharp version 10 so this improves the clarity and simplification of a developer's code and potentially increases productivity allowing the developer to focus more on application business logic net multi-platform app UI for Native mobile and desktop apps dotnet multi-platform app UI or net Maui is an evolution of xamarin it allows the developer to create applications for multiple different types of platforms using a single code base you can write one project that can be compiled into an application that runs on Android devices iOS devices Windows desktops Windows devices as well as Mac OS so one code base written in for example C sharp that can leverage native capabilities on multiple heterogeneous devices Blazer desktop web apps with Native device capabilities so one advantage of this is that if you're a web developer and don't want to learn xaml to implement your front-end code as you would When developing an application using for example WPF uwp or xamarin forms you can use HTML5 CSS bootstrap and JavaScript I.E the web Technologies with which you are already familiar to create desktop applications through Blazer desktop web apps you will still be able to leverage native device functionality and not worry about learning new technologies to leverage these native functionalities minimal web apis for cloud native apps this is a great feature that allows a developer to be up and coding for example a simple macro service a lot quicker than if the developer were to code that microservice using a typical web API that implements the MVC architecture there is far less ceremony involved in getting started more device targets including Apple M1 .net 6 will support single file deployments for windows with up to 50 smaller file size dotnet 6 supports ahead of time compilation productivity enhancements like part reload if for example you've developed angular applications with node you may be familiar with the hot reload feature this feature is now coming to net developers this means improved productivity simply because there's less need to stop and start the running of our code during the development of our applications continued performance improvements in runtime and builds time EF core performance is now 70 better on the tech and power benchmark so that was a brief overview of what you can expect with the release of.net 6. hi and welcome I'm Gavin long in this video we are going to look at some of the great features and improvements that are due to be released with net 7. we'll cover these aspects thematically for more details of what to expect with the release of.net 7. I've included relevant links Below in the description of this video this video will give you a broad overview of some of the improvements and new features that stand out to me that will be included in the official release of Net 7 which is due to be released in November of this year 2022 since the release of.net 5 on November the 10th 2020 Microsoft committed to a new release of.net in November of each year moving forward so.net 6 was released on the 8th of November 2021 and in November of this year we are expecting the release of net 7. Net 5 was what's known as a current release and net 6 was what's known as a long-term support release LTS release note that there is no quality difference between long-term support releases LTS releases and current releases the only difference is the length of support LTS releases get free support and patches for three years current releases get free support and patches for 18 months at the time of creating this video the latest preview release of.net 7 is preview 6. I've included links Below in the description to blog posts that contain details of each of the preview releases of.net 7. the official release of.net 7 will be a current release which means it will be supported for 18 months the release of dotnet 8 due to be released in November 2023 will be a long-term support release which means it will be supported for three years preview releases are typically not supported but they are offered for public testing ahead of the final release a preview or release candidate release are supported through Microsoft developer support only if they're specifically designated go live a brief history of.net this channel has released several videos on the history of.net the first video I released on.net is a video on the difference between.net framework and net core I've since released a video on the.net 5 release and a video on the.net 6 release in each video I've provided foundational content on the evolution of.net please see a link to a playlist Below in the description to view the videos released by this channel on the progression of.net so in this video I'll give a brief overview of the history of.net before we look at the new features due to be released in.net 7 and also the improvements and optimizations that are due to be released in.net 7. NET Framework was released February the 13th 2002 at the time it was a revolutionary release for Microsoft as it fundamentally changed the environment in which Microsoft applications run dot net applications run on what can be described as a virtual machine similar to how Java applications run on the jvm Java virtual machine the virtual machine provided in the.net framework is known as the CLR common language runtime.net framework however can only run on Windows platforms and requires an installation of all the Base Class libraries shipped with the.net framework.net core was released on the 27th of June 2016. it is a free open source managed computer software framework that is cross-platform it can run on Windows Linux and Mac OS operating systems only the Base Class libraries that are needed by an application need to be shipped with that application so it is a more agile version of.net when compared to the.net framework so.net framework and net core is being supported concurrently this resulted in the fragmentation of.net to alleviate this fragmentation the.net standard was introduced the first steps to properlyunify.net under one umbrella as it were came with the release of.net 5 on November the 10th 2020 the release of.net 6 came approximately one year later on the 8th of November 2021 which shipped with many great enhancements but most significantly.net 6 further cemented the unification of.net so.net 6 is Unified free open source software that is cross-platform and agile it is an extremely versatile framework in terms of the types of applications that can run on.net and the performance of.net has been optimized for the cloud it is also versatile in terms of the number of platforms on which it can run dotnet 6 is supported on multiple operating systems Windows Linux Mac OS Android iOS tvos including Mac OS silicon and windows arm 64. so what is coming with.net7.net Maui there is significant investment in.net Maui for net 7.net multi-platform app ui.net Maui is a cross-platform framework for creating native mobile and desktop apps with c-sharp and xaml using.net Maui you can develop apps that can run on Android iOS Mac OS and windows from a single shared codebase.net Maui is open source and is the evolution of xamarin forms with the release of.net 7 you can expect performance improvements and better tooling in.net Maui Cloud native and containers Cloud native Computing is an approach in software development that utilizes cloud computing to build and run scalable applications in modern dynamic environments such as public private and hybrid clouds so common Technologies used in building Cloud native applications are for example Docker containers a set of platform as a service products that use OS level virtualization to deliver software in packages called containers kubernetes an open source container orchestration system for automating software development scaling and management and micro Services a collection of loosely coupled services that run inside Docker containers there'll be a broad set of investments in Cloud native and containers in.net 7. in terms of for example simplifying authentication Improvement of performance in terms of startup performance and runtime performance and better integration with containers there's also investment in better alignment with the Orleans technology Orleans is a cross-platform framework for building robust scalable distributed applications Orleans scales with a single on-premises server to globally distributed highly available applications in the cloud audience uses the virtual actor model where grains serve as the fundamental building blocks of Orleans applications grains are entities comprising user-defined identity behavior and state so with Net 7 there will be investment in better alignment of all yields with.net modernizing existing.net applications with.net 7 there is investment to make it easier to upgrade older.net applications to modern.net applications for example You may wish to upgrade an old asp.net MVC application to an asp.net core MVC application for Net 7 Microsoft is making investments into its Upgrade Assistant to make these types of upgrades easier the Upgrade Assistant can for example change code written for older.net environments to be appropriate for modern.net environments it will also be made easier to upgrade applications in sections rather than upgrading the entire application at once they are framework Investments for application modernization and net 7. abstractions will be provided that for example allow the sharing of parts of the asp.net side of the application with parts of the asp.net core side of the application so the upgrade can be done in an incremental fashion rather than all at once which may not be a practical solution dotnet 6 contained many performance improvements Investments are being made in Net 7 to make.net even faster and more efficient asp.net core HTTP 3 will become part of the.net framework in.net 7. HTTP 3 is a new standard in development that will affect how web browsers and servers communicate unlike previous versions which relied on the well-established TCP HTTP 3 uses q-u-i-c a multiplexed transport protocol built on UDP HTTP 3 includes significant upgrades for user experience including performance reliability and security minimal API minimal apis are architected to create HTTP apis with minimal dependencies they are ideal for microservices and apps that want to include only the minimum files features and dependencies in asp.net core minimal apis provide developers with the advantage of less ceremony when setting up web API applications they are lightweight minimal apis hook into asp.net course hosting and routing capabilities and allow you to build fully functioning apis with just a few lines of code in.net 7 minimal API will be more consistent in terms of what can be achieved when compared to web apis that use the traditional MVC design pattern one new feature in.net7 is providing a way to group minimal apis together with a common root prefix so that they represent one part of the API space as it were a developer can take the apis and put them in different files so that it is more manageable from a project and code management perspective currently you can apply action filters to controllers in a web API component the ability to implement such code for cross-catching concerns will now be available for minimal apis the concept of endpoint filters will be available in Net 7 to apply the same cross-cutting functionality that for example action filters provide for controllers grpc grpc was created by Google to speed up data transmission between micro services and other systems that need to interact with each other with.net 7 there is investment in grpc Json transcoding the feature allows grpc services to be called like restful HTTP apis with Json requests and responses so for example this will make it easy for JavaScript code running within a browser to call a grpc service signal R signal R is a free and open source software library for Microsoft asp.net that allows server code to send asynchronous notifications to client-side web applications signalr was built for high performance and is one of the fastest real-time Frameworks around in.net 7 there will be support for strongly typed clients and returning results from client invocations a new client Source generator for Signal R will be included the signalr client Source generator generates strongly typed sending and receiving code based on interfaces that the developer can Define Net 7 will come with various improvements to the Razer compiler to improve performance resilience and to facilitate improved tooling Blazer broad improvements will be made to blazer for example mixed mode aot ahead of time compilation will allow for certain assemblies to be ahead of time compiled rather than the entire application needing to be ahead of time compiled when ahead of time compilation is implemented this makes the overall size of the application to be downloaded to the browser much larger so although runtime speeds are increased for the application the file size is much larger enabling mixed mode means that parts of the application can be optimized for Speed those parts of the application that require greater speed can be ahead of time compiled leaving the rest of the application to be interpreted so speed can be increased where it counts and a balance is maintained between less size of the application and the benefit of speed optimizations most browsers are now capable of facilitating multi-threading so.net 7 will take advantage of this and will provide multi-threading to Blazer webassembly applications web crypto simply means that cryptographic functionality available in browsers can be leveraged from Blazer applications with the release of.net 7 there will be enhancements in hot reload support data binding improvements more flexible pre-rendering pre-rendering razor files into HTML allows passing of static files which for example makes SEO search engine optimization effective and Blazer applications more control over the life cycle of Blazer server circuits improved support for micro front ends micro front ends are a new pattern where web application uis front-ends are composed from semi-independent fragments that can be built by several teams using different Technologies support for custom elements is an exciting feature where you can shrink wrap as it were a Blazer component in a standard custom HTML element this means you could reuse the relevant custom element created in a Blazer application within for example an angular or a react application so that's a super exciting feature mvc.net will include improvements made to endpoint routing link generation and parameter binding Orleans the asp.net core and Orleans teams are investigating ways to further align and integrate The Orleans distributed programming model with asp.net core Alliance 4 will ship alongside.net and focuses on Simplicity maintainability and performance including human readable stream identities and a new optimized version tolerant serializer this video provides a brief overview of some of the features and improvements to expect with the next official release of.net which is due to be released in November of this year.net 7 will be a current release meaning it will be supported free of charge for 18 months and will contain many great new features many performance and optimization improvements with this new release of.net and the commitment to release a new version of.net every year moving forward makes it a great time to be a.net developer if you like this video please give it a thumbs up and please feel free to share this video with anyone you feel May benefit from its content for Content like this and much more please consider subscribing and please ring the bell so as to be notified when new content is released I really enjoy reading your comments so please feel free to leave a comment below in the description I hope you've enjoyed this video thank you and take care