hello and welcome I'm your codm welcome to the free Advance section for my complete C Mastery course by going through this course you'll be able to make games websites apps Robotics and literally anything C is an extremely person down language this complete core starts from the absolute Basics like how code executes line by line and what is a variable then covering some intermediate topics like what are interfaces generics and events and how you can use them to build some really awesome things you will also learn the theory behind how to choose good naming rules clean code guidelines and learn about design patterns and finally in this Advent section here this one covers some very interesting topics like reflection acing programming and multi-threading this free YouTube video over here this one contains all of the video lectures for the Advan section like I said in the previous video my goal was to publish the video lectures here on YouTube for free if the premium version sells above a certain number of copies and I'm happy to report that it does indeed sold above that threshold that's why this free video is here right now so thanks to everyone who can afford and who did pick up the premium version I've already posted the two free videos with all the video lectures for the beginner in the intermediate sections and now here we have the advaned section the premium version of the course has all the video lectures for all the sections and also has a bunch of really nice bonuses So speaking of that here are the bonuses for the premium version I came up with some that I think are really awesome and definitely worth it if you can't afford it well at the same time not putting any knowledge behind the pay wall so even people who can't afford it they can still learn from the free lectures they really just need to do a little bit of extra work themselves the premium version is really just selling convenience making it really easy for you to truly gain the knowledge the premium version comes with a companion project this is a Unity project that contains a bunch of extra content basically the video lectures while being preas of themselves they're still really only half the course the other half of it is inside of this project it has a bunch of custom editor Windows to guide you through each lecture and each lecture has a section on frequently asked questions these are common questions that have some really detailed answers that provide even more details on what is covered in the lecture then there are some quizzes these are multiple choice questions again all with very detailed answers it's really not just correct or incorrect if you pay close attention to each lecture you should be able to get most of these right but with you do or don't by reading the extra explanation that will help you truly learn that topic then the interactive exercises I'm really happy with this feature I think this will really help you learn learning by doing is always much better and these exercises encourage you to put what you learned into practice instead of just blindly watching the video lectures I designed a ton of handcraft exercises for all the lectures to help you put into practice and truly learn the contents of each lecture there are all kinds of exercises some are about spotting and fixing errors others are about asking you to Define some function or class or Implement some kind of logic there are some where you just write code and some where you write code and then play the code in unity in order to complete the exercise then each exercise also contains a hint just in case you get stuck or a solution in case you get really stuck as well as a video walk through of me going through that exercise and completing it while explaining everything in detail so if you're the kind of person who gets stuck in tutorial hell then I truly believe that this will really help you escape it in order to learn need to actually do things and this exercise encourage you to do that they encourage you to do it as opposed to just blindly watching the video lectures then the companion project also has a companion window basically this window is also listening to a bunch of errors and if it finds one it will help guide you in the right direction I manually wrote a ton of texts for when text lots of errors all of them based on common errors that I see people ask about in comments in my own videos so this should help prevent you from getting stuck in your Learning Journey and allow you to get help instantly then the course also has an AI to help you answer questions this one was trained on the content of the course and my own knowledge so it should be very accurate and helpful but more than that it's simply the fact that it is extremely fast you post a question in the course comments and within a few minutes the a will respond with probably a very good answer although of course I myself will also still be answering all the questions manually the goal with this AI is really speed so you get a response almost instantly and then within the next few hours I will manually answer myself then a simple bonus is how the premium version has the course split into lectures as opposed to Here on YouTube where it will be one giant video it has to be that way due to how the YouTube algorithm works this is a small thing but it can be helpful especially if you take your time to slowly go through the course just like you should do remember that the only goal is really that you are actually learning yourself it does not matter how quickly you go through it so separate lectures help with that so that you can pause and actually try out your knowledge before going further and you don't have to memorize specific time stamps and over here on YouTube the videos have the normal YouTube ads as usual whereas the premium version has no ads so there's nothing to interrupt you while you're learning another two great bonuses is the private Discord and the live study group you get access to a private Discord with a really nice community of people on their own Learning Journey I'm there myself as much as I can to answer questions or really just chat and every week I also do a private life QA you can join me on the live stream and ask anything you want and I'll do my best to help so these are the nice bonuses that I came up with that I think are really nice and really awesome while not taking away anything or putting any knowledge behind the pay wall if you can afford then I highly recommend the premium version these bonuses will help you truly learn and learn much much faster than the 10 years that it took me but if you can't afford it that's okay like I said there's no hidden knowledge hidden behind the paywall you really just need to put more effort in yourself in order to actually applied knowledge that you gain so whether you get the premium version or watch your free lectures I really hope you'll learn a lot also just in case you're new to my channel so a bit about me and my credentials or why you should listen to what I have to teach for me I've been programming for over 25 years and specifically using C for over 10 years I'm a professional indie game developer with several successful games poish on Steam covering a wide range of genres my games are usually focused on complex systems since I am primarily a programmer it's what I really love to do and what I love to teach also a couple of years ago I started over here this YouTube channel making free video tutorials to basically share my knowledge to help you learn how to make your own games there's already over 800 free videos over here on this channel if you want to continue learning Beyond this course or look at my other courses if you want something on making a specific game you can watch my free katchen chaos course in there we build the game from start to finish and then on a second video we add multiplayer onto it then for something more intermediate for that check out my turnbas strategy course this one includes a really nice turnbas strategy game with actions and enemies and all kinds of things or if you're an advanced user if so then check out my unity. scores unity. is an extremely powerful very Advanced tool set that can help you write code that runs literally 100 a faster or in general for Unity you can check out my ultimate unity over course this one covers over 70 tools and features that Unity has also even though this video is for advanced users let me reiterate my usual advice for pretty much anyone trying to learn that's really just take your time take it slow remember this is your Learning Journey it's really no one else's so the only thing that matters that you learn it does not matter how long it takes you it does not matter if someone else learns faster you're really not in competition with anyone but yourself remember you are not expected go through this entire course in one week or even one month like I said this course contains knowledge that took me over 10 years to gather so take it slow take your time really just focus on learning and just one final request if you find this video helpful if it helps you on your Learning Journey if so go ahead and hit the like button on the video and subscribe to the channel it's a tiny thing but really does help all right so let's get to it hello and welcome I'm your KMI all right so here let's see a quick overview of everything we're going to learn in the advanced section of this C course this going to involve a lot of very interesting very unique topics we're going to start off with an interesting Advanced topic that I actually only started seriously using just recently it's reflection I had to learn this myself in order to make the exercise for the companion project reflection is how you can dynamically inspect your code and work with it without directly calling any functions or reading any Fields next is going to be a simple but interesting one it's how you can make some function extensions this allows you to extend a type with more functions without having to modify that type itself this is really useful when you don't have access to the type itself when you don't have source code access then we're going to learn about static Constructors these are kind of like the normal Constructor but they run just once for the entire class after that we're going to learn about the type of keyword this lets us get a system. type object of any type that we have this is very important to use alongside reflection then in lecture on name of this one helps you get a string name for some kind of type this is really useful to help you avoid strings in your code next is the size of operator this one lets you get the size of your types like for example you can see how an INT is four bytes a short is two bytes and a BTE is just a single BTE so this helps you know how much memory your code will use then in lecture on default simple and very useful way to get the default value of some type if you do the default of an INT you get zero if you do the default of a ball you get false if you do the default of some object you get null and so on so using this keyword is much better than hardcoding some default values after that we're going to have a lecture on expression bodied members this is a really interesting very compact way to write simple short functions there's no need to write all the usual function boiler plate code this one is basically just a Lambda after that we're going to see a lecture on records this is a super simple way to create immutable types to organize your data next we're going to learn about the null conditional operators this is how you can easily test for null before doing something like for example before firing off an event then in lecture on the null coing operator this one lets you quickly test against null and if it is null return the default value after that we're going to learn about the ternary conditional operator this is an excellent super compact Syntax for making a very simple if you have the condition with an if and an L so it's all very tiny very useful next we're going to learn about the main function in a console app and how to pass in some command line arguments this is a really important one because there are many interesting programs that you can build that don't need any kind of UI so a simple console app that you can control with some command line arguments that one is always going to be an excellent option then in lecture on nullable this is how you can make any type support null even value types like int or ball you can make them nullable to support null this can be much better than having to predefine some special value something like minus one next we're going to see a lecture on span this is a super efficient way to do Logic on arrays or slices of arrays importantly is how this does not actually create any new data it does not cost any new memory does not create a new object this one is basically just a pointer meaning it is insanely performant then in lecture on bitwise operators this is how you can work work with individual bits of data in this lecture I'm also going to teach the basics for how binary works next we're going to learn about enum Flags this is how you can turn your enom into bit masks which then allows you to make some interesting combinations then a lecture on pre-processed directives with this we can give orders to the compiler itself we can Define symbols and include or not include some code in the compilation next in lecture on the keywords ref out and in these are really useful they help you get more that out of a function than just aing single return type and they also help you work with types as references even if they are valid types after that we're going to learn about data boxing now this does not have anything to do with punching people it's really all about putting data inside a box this is an interesting property based on the fact that everything in C extends from object next we're going to learn about Dynamic this is a really interesting very Advanced topic with Dynamic we can work with types that don't actually exist so we can define something as Dynamic and call functions or films on that type on that object even if they don't really exist that validation logic is only going to run at runtime not at compound time so this Dynamic this is really useful especially when working with data you got from some kind of web server then a lecture on the class indexer with this you can make your own custom type support access through an index just like a list or array you can add whatever logic you want and make it read only or read right next is a lecture on attributes with this you can add metadata to your code then that that it can represent whatever you want you can use reflection to analyze it and do something to it after that is a lecture on Anonymous types really interesting quick way of organizing some data without having to First Define a specific type you just do new open up the Carly braces and it will automatically create a generated type related to that is the next lecture on tupon these are very similar they also allow you to organize some data without first defining a type in this lecture I also cover the differences between Anonymous types and tupon next is going to be a lecture on using I disposable this is a really interesting code block and interface that helps you make sure you don't forget any kind of cleanup code after that we're going to learn how to create custom override operators using these we can add support for our own classes to do things like addition or multiplication we can Define the logic of what exactly it means to add two custom player classes together and also Define the logic for comparing two custom types meaning Define the logic for what exactly does mean to do an equals next is a lecture on link with link we can easily do query operations on any collection of data whether it be a list or array or some XML or some kind of database we grab that data then we can query for some conditions and select just a few elements we can sort some things we can do a union and so on if you're familiar with SQL then link will be quite familiar afterwards we're going to learn about Wind forms this is how you can make visual C programs you have your toolbox and you just drag and drop the components here I'm also going to talk about the other visual program tools things like WPF and Maui as well as how Unity itself doesn't have to be used just for making games you can make normal applications with unity next is going to be a lecture on dlll import the elaborate import how to use extern and work with the windows API so this one is going to be a great lecture to learn how to interact with external libraries then a lecture on asserts and unit testing in general with this you can validate your own code to make sure everything is behaving exactly as intended next is going to be a lecture on writing unsafe C code and working with pointers now this one this is is a very very Advanced topic technically if you know what you're doing you can make some impressive stuff with unsafe code but C has a safety for a reason so definitely only use this wisely then we're going to learn about asynchronous programming specifically how to use async await and task this is how you can have some code that takes some time like for example contacting a web server and keep waiting for a response without blocking your program this is extremely important in making sure your program feels nice and responsive after that comes a super important Advanced lecture this one is all about multi-threading this is how you can take advantage of all the cores in a CPU to make them all do work at the exact same time when then properly you can get some insane performance improvements but it is also very very easy to make mistakes so this one is very much the definition of an advanced topic where you must know exactly what you're doing and yep all of that concludes the advanced section of this course as you can see we're going to learn about a lot of very Advanced unique topics some of them you're going to use quite often and some of those probably less often but just by learning about them learning that they this that will help you whenever you need to use them and of course remember how you can always come back to this course at any time you really not expect to memorize all of this personally I Google things all the time and now actually I have this course in my own words so anytime that I need to relearn some syntax I'm really just going to re-watch a lecture to learn myself so if in the future you want to re- remember something like for example how acing programming works you can just come back here and watch that lecture all right so this is everything we're going to learn so let's start learning some Advanced topics within next lecture hello and welcome I'm your kod Mony in this lecture we're going to learn all about reflection this is a really interesting topic for how you can analyze and run code in a dynamic manner so reflection is the name for a bunch of functions that you can run on the types themselves like for example over here I've got an exercise class and inside I defined a my function function and yep all this is valid code now up here constructing an instance of exercise and through that I can simply call my function and yep everything works so no errors all perfectly fine this is the usual way for how you call some kind of function on some type however another way is using reflection and the way we do that is first we access the type itself so we do that using the type of keyword and then we use the class name so in this case I want to access the things on the exercise class and then just by pressing dot over here we can already see a bunch of really interesting functions so get member get interfaces get n type get properties and so on so we've got all kinds of things in this case we're looking for a function and again technically the terminology in C is a function is called the method so it's called a get method this one takes in a string for the name of the method that we're looking for so in this case we're looking for something called my function so y just like this and now this one is going to return an object of type method info so method info and this one by the way exists inside system. reflection so let's add that using so the method info for the my function method info okay so basically now this contains the data that relates to this function and now using this we can invoke it so we can call the invoke function and this one takes in an object object for the Target so in this case let's use our created exercise and then for the parameters in this case this function takes no parameters so let's just put out an empty object array just like this and if that's it this works so let's just put a conso right line over here just test it out test it out that we're calling my function so we should be able to call it over here and also over here so let's run and if there is exal like that the function ran twice so yep here you have two very different methods of running the same code and over here you might be wondering where exactly is this useful I mean just calling the function directly that sounds much much easier now reflection is actually a topic that I myself had to learn quite a lot in order to make the interactive exercise for this course for example this exercise on the class lecture the goal of the exercise is to define a player class and basically in order to test if the student has completed this exercise the code needs to check that the class does exist so for example over here on this testing code let's do the exact same thing so let's assume the exercise the goal over here is to define a player class defined inside of this one now if if it does exist then obviously we can just access it so we can just access the exercise type that works and if over here we Define a public class player if we do this then yep over here we can access player and yep so this does work this is valid code so we do a type of in order to find so if this type is not null if so then yep then the type has been defined however by using this code remember how in the beginning of the exercise the player class does not exist so if I raisee this as to what this would be on the state in in the beginning of the exercise if so obviously this code does not compile because there's no such thing as a player class basically we cannot write code assuming something is going to exist when in reality it does not exist just yet so really the solution to this and the solution for the validation Logic for pretty much all exercises the solution is to use reflection like I said reflection is really just name of various functions that work directly on the types so for example we can access just the exercise type just like this and then let's just do a DOT and now we can see a home bunch of things in this case for this exercise let's say we want to find a defined player class so for that we can use the function getness a type and this one takes a string of names so let's look for a class named exal player like this now we can indeed write this code so there are no errors because again we're just using a string in order to identify the player class by the name itself so this valid code we've got no compiler errors and this function is going to return an object of type type so we can do type player type we can do this and then we can do a on the right line if this one does exist so let's just print out just the player type so let's see this and if there is it prints out nothing because there's no player type but if over here we Define it so public class player if we Define it like this and if now it does indeed find that class so by using reflection we can write some code that tests if something exists before that thing actually exists alternatively instead of looking for a specific type we could also use the other one so type of for the exercise and we can call get nested types this one grabs all the types it returns an array of types so we can just do a simple for each and all of this type type and all of these we can look for them and then let's just print out the type all the types so over here if we've got the player then some kind of unit class and some kind of enemy class and so on so if we test this we should be able to see all of them and if there it is we've got the first player over there then player unit and enemy so on pretty much of the reflection functions you always have one to look for a very specific thing or one to look for all of them and also on both these functions you also have all kinds of filters so there's a function that takes some binding flags and these binding flags are really just filters the main ones that I use quite a lot in the exercise was looking for static things so for example unstatic or for example this one nonpublic because for example if we don't assign this and let's say we Mark these as private if we do it and we run this code and if there this our cycle only found the player class because it is the only one that is marked as public so in order to find things that are private if so we need to use the binding Flags in this case to find that one we need to look for nonpublic and by the way if you want to implement multiple filters together if so you just need to write a pipe so that's just a single pipe this is the bitwise or operation so do this and then we can add another one like for example looking for static so right now since we defined the filter this is only going to find things that are nonpublic or static meaning in this case it will not find the player but it will find both these then let's just erase this just to not get confused and let's test and if there this ex like that finds the unit and the enemy but no player so you can use either of these methods in order to find a specific type somewhere so for example some kind of player type okay we have it so we have this player tab right here we can just test this one against null if this one is not null then the type does exist and if it does exist then again like we saw previously we can find and call some kind of function so for example over here poing void call it my function and then by using the player type which by the way another note we can get the player type either like this like we did or also again using the type of keyword this one returns a type so basically player type or type of in this case since exercise. player since this one exists we can do this so basically both these have the exact same thing okay so then using the type we can call get method and let's find our function so let's find the my function this one returns a method info my function method info and then we can invoke it as usual except over here we need an object so let me just do a new player I'm going to talk about how you can dynamically create objects in a little bit so over here new exercise. playay here then this one has no parameters so an object an empty object array and yep so this basically going to run this so conso right line and I can run my function and we can see and if exal found the player and ran the function on the player save all this works and again over here we don't have any direct calls over here to my function if we select this and we find all references to this nope we do not find any references because the code is not being directly reference instead we're referencing only through reflection now like I said over here the second parameter this one is for all the parameters that this function takes and just in case you don't remember object this is the base C class this basically the base type that all the C types inhered from so this can be anything so for example we can define a function with an in parameter and then over here we can call like this so we can do this and then print out that one and let's see and if does work my function and did receive that one although of course we need to pass in the correct type since over here this is an object this has no limitations so we could pass in for example a Bion and there it is we have an error we passed in a bullion which cannot be converted automatically into an int32 which is what the function expects so even though this is of type object obviously the types need to match whatever this function expects and through the method info we can get pretty much all the info for this function so for example through that one we can get for example the return type and this going to return over here in this case going to return void or alternatively we've got all kinds of things you get the parameters this returns an array of parameter info which again contains all the data for all the parameters so the type the name itself again all these are things that I use in making pretty much every interactive exercise there are various exercises that require you to implement a specific function that returns a specific type with a specific number of parameters so that's pretty much how all of that code works if you want you can actually inspect the code for the exercise completion so you can start an exercise like for example this one on defining a player class so the goal on this one is to define a player class and then Define some functions inside of it and in the project files over here you can see inside the exercise folder you see a bunch of files related to to the exercise that you have enabled so in this case let's open up the exercise scene tester and up over here if we scroll down we can see all kinds of reflection being used to make this exercise work so for example over here it's going inside the exercise class and looking for the nesa types in order to find the player class and if it does find it then it goes inside all the methods within that player class in order to find a say hello method and if so then basically yep the exercise is completed successfully for another practical example you can for example just look at the visual studio intelligence so if we write some regular code like exercise. player and then put a dot so for example if over here we construct a brand new player so we have a player and then we access the player and we do a DOT and you over here this is basically using reflection Visual Studio is going through the entire type over here behind Dot and it shows all the fields all the functions and all the events related to that type so using reflection you could build something like intelligence another thing is how code in C is grouped into assemblies so for example let's grab the type of of our program type so that's the default one up here we can grab that one and grab the assembly let's just do a console. right line on this one so let's just print this out and see and if there it is that is the name that is the reference for our assembly which again inside that assembly that returns an assembly so inside that one you can then put a dot it can get all the types all the files all the things everything that exists within that assembly also if you want to look for any types inside of an assembly of course as usual you can cycle through the types and print them all but if you're looking for a specific type if so then over here on the name you need to write it exactly as the assembly writes so if we print to see what this one up top writes y this one says code Mony C course which is the namespace then the program so we're inside the program class and then for example the exercise class and then the player class again note the dots and the pluses if I want to get the player type over here if I were to just write exercise. player so if instead of this I just write this so just exercise. player if I do this then nope it does not find it in order to find it over here when you call get type it needs to be called with the exact same full name including the namespace including the name space and also including over here the dots and the pluses if we do this then yep now this one does find it so one more thing is like I mentioned while ago which is dynamically creating objects of a certain type so for example over here we constructed a brand new player and we use that to invoke the method but again if this code was written before the player class existed then this would not be valid code so we need to also dynamically create an object of that type so over here we have the player type that we dynamically grabbed and now with this one we can create it and for that we use a class called activator exist inside of system and then we call create instance and then we can either pass in strings for names or if we already have access to the type let's do that one so let's just pass in the player type and Yep this one is going to construct a brand new player object this one is going to return of type object because again we're running this before let's say the player class is defined so we need to use the generic object so player object but then again over here on the invoke this one also takes in an object for the Target so we can pass in the player object and yep so now this one is going to create an instance of our player type so it's going to create a brand new player object and then we're going to use that player object over here to invoke the function so if we run this and yep everything works as usual now yet another interesting thing about reflection is how you can bypass access modifiers so for example over here for this function instead of making it public let's make it private so in this case even if you have access to this this code right now if so if we go inside exercise. player if we construct a brand new player and then we go inside player and try calling my function and Noe this does not work because again like it says this is inaccessible due to its protection level so if you have a private function you cannot call it you cannot access it through regular code that's the usual thing however you can still run it over here through reflection so if we run this code it still works we just need to make sure we find the actual methods over here for The Binding attributes and we need to make sure to find the functions so over here looking for it since this one is private let's make sure to add The Binding flags for nonpublic and also for this one we also need to add the instance because this is an instance function so if we run like this even though the function is private yep that one still run the function so by using reflection you can run private or internal code now again do keep it in mind this is probably not something you should do in your own code if you make something private then you probably want it to actually be private but for example if you're making some kind of testing code if you're doing test driven development if so you probably still want to test your private functions so if so then reflection can be a use case for it or another example is when working with some apis like for example the unity API where some functions might be marked as private or internal so in those case where you cannot directly modify the code and you really need to call that function if so remember how you can do it through reflection related to that is also doing things like modding and plugins you can allow your game to dynamically load a DL at runtime and then use reflection to run the code inside that Library so that's reflection it's a very interesting topic definitely very niche in terms of use case like I said I really only had reason to learn about it right now in order to make the exercise for this course so it's probably not something you're going to use regularly but do remember that it exists remember how there is a way to dynamically run your code if you need to hello and welcome I'm your Cod Mak in this lecture we're going to learn about function extensions or extension methods this is a really interesting C feature that allows you to extend classes without having modify the code in that actual class so usually if you have some kind of class like for example over here I've got in my transform if you have it and you want to add some kind of function to it usually you just modify the class and write the function inside of it so for example a public void move right and then over here we take the position and increase the right something like this okay so yep that works here is the function and up here if we have something of type my transform if so then we can go inside of this and we can indeed call the move right function so y this works this perfectly valid code we have modify the class to add our custom function and then we call the function however what happens if you can't modify it like for example let's say I do want to implement this kind of move right function however instead of making it work with my custom my transform type instead of this I want to work with the built-in Unity transform type now that type is sealed I cannot modify it so I can put transform for some kind of transform and we can try going to the definition so here it is except this class is compiled meaning we do not have access to modify this so the method of just writing the brand new function directly inside this class this does not work because we cannot modify this class so that's exactly where function extensions come in which again remember how function and Method are pretty much interchangeable names so if you look in the C docs what we're talking about here is actually technically named extension methods so extension methods are function extensions this is basically how you can add extra functions to some kind of type without having to modify that actual type we just need to follow a bunch of rules to make it work the first thing we need is to be working on a static class so let's make a static class and then usually the naming rule is to name it something and then add extensions onto it so in this case we want to add some function extensions to the transform type so let's call it transform extensions like this that's the first rule the second rule is the function needs to be defined as static and be public so over here a public static void call it move right and finally the third rule for this one over here inside the parameters the very first parameter this one needs to have the disc key keyword it needs to have that and then be the parameter of the type that you want to extend so in this case we want to extend the transform type so let's put a transform like this and if that works so this is now a valid function extension and now inside of here we can do our regular code so for example we can do exactly what we're doing so let's go inside this transform and modify the position and do a new Vector 3 and just move it to the right and if there it is this is our function extension and now up here when we have access to a transform like for example the transform that this object is attached to we can go through that and we can call the function move right and yep it does work and we can see over here intellisense is telling us Yep this is an extension function so we can call this and Yep this works perfectly so we've got no errors basically what is happening here is the this keyword over here inside the function this says that this first parameter is special basically it assigns what it was called on and uses that over here on the first parameter so basically over here this is doing the exact same thing as if we were to manually go inside the transform extensions call the move right function and pass in this transform so both these are doing the exact same code the only difference is this one is much easier to use so yep as you can see like this we have added a brand new function onto this type onto our transform without having to modify the transform type itself so we don't need any access to it we just need to know the type and we can write an extension and then we can write some kind of code that works directly on that type and of course over here after using this special parameter so the this parameter this one has to be the first one but afterwards you can add whatever you want so let's say for example a float amount and over here we modify this one by the amount and then when calling it we just pass in for example three and Yep this works so we call the function extension which is going to call this function for the transform it is going to use this one and for the amount it is going to use this one and again this works on any type so over here we are making a function extension that is extending the transform type but for example let's do another one again we just need to make sure to mark it as static and let's extend say the b type let's make is true this one returns to this bull bll and for example just return if the ban is true so again all the rules are being followed it's inside a static class the function is static and has a disc keyword so now here B and we can set it to something and then B do is true and Yep this does work so yep we can add function extensions to some custom types or we can add to built-in types can be a bll in can be an N can be literally anything all of this works so we can easily extend any type with any functions we want this works for extending classes but also works for extending vals like we saw over here at the ball so we can also extend structs and this also works for extending interfaces so if you want to add extra logic to a type but either you cannot or don't want to modify the original type that's where function extensions or extension methods come in it's one of the best ways to make some helper utilities functions that you use a lot and make them super easy to use hello and welcome I'm your Cod Mony in this lecture we're going to learn about the static Constructor this is a really useful way to run some kind of initialization code where you can be perfect Ely certain that it will always run okay so you're already familiar with the regular Constructor so we have the class and then we have a Constructor and this code is going to run whenever a new object of this type is constructed so basically before you use this type at all before you use any functions or Fields before that you can make sure that this code always runs and static instructors are basically the same thing but just in a static context and the way that you define them is super simple you just use the static keyword with no access modifier so no public no private this cannot be either one of those you cannot manually run a static Constructor it always runs automatically and then it must have the same name as the class so player and it also must have no parameters so a completely parameterless Constructor also you can only have a single static Constructor and it cannot be inherited or overloaded so it has a ton of limitations because like I said this one runs automatically so that is why we cannot have any parameters over here because the compiler is going to run this automatically whenever we need to and basically this will run either when an object of this type is created so for example before the Constructor or also when any static data or any function is accessed so for example let's do a conso out right line here just to see when this runs so the player static Constructor and if we run like this so we have our player class we've got the Constructor the static Constructor and up here we are just constructing a brand new player if we run this code if there it is it ran first the static Constructor and secondly ran the Constructor so the static Constructor always runs before the object is constructed now let's say we have some kind of function so a static void for some kind of test function and over here same thing let's we conso that right line on our test function okay and now up here before we construct let's go inside the player and call the test static function let's do it like this so let's run and if there it is again same thing the static Constructor ran then the test function and then the Constructor also note how the static Constructor only run once so when we construct an object it did not run a second time or alternatively if we have some kind of field so a static int for some kind of in field if we have this and up here we read it so let's do conso out right line let's right line on the player. I so our static field so by default if we don't assign any value this is going to default into zero so over here if we set I equals something let's see what this one is going to print so is it going to print the zero that is over here by default or is it first going to run this code and basically print 56 so let's test and if there is exactly like that so as soon as we access the static field as soon as we do that before it actually runs that code it is going to run the static instructor so first runs that one then prints the value which in this case was assigned The setic Constructor and then again runs the function and the Constructor and same thing the CTIC Constructor only ever runs once meaning that the satic instructor this is really excellent for doing any initialization logic that this particular class might require one example is exactly this is if you have a static field and you want to make sure to initialize with some data if so you have two options so basically over here when you def find it you can also assign it some value or alternatively you can assign it on the static Constructor both are valid options pretty much just like on a regular Constructor you can also have some kind of regular field so you can have that one and over here you can assign it some value or inside the Constructor you can assign it some value so you've got these two options for non-static context and you also have these two options for a static context now the static Constructor this one can also be very useful for debugging you can basically place a log over here and it will let you know when this class is used for the very first time whereas if you were to place the log only on the Constructor itself if so then this would only run when an instance of this type is created whereas for the static instructor that runs whenever any object is created or when any static element like a field or a function when any of those are accessed so the static Constructor this one guarantees that it always runs the very first time that this class is used in pretty much any way it is also important to know how in the context of multi-threaded code the static Constructor is guaranteed to be thread safe meaning if you have multiple threads and all of them try to access some kind of data inside of this class at the same time if so the net runtime ensures that this class is locked and make sure that the static Constructor runs only once no matter how many threads try to access it at the exact same time so the static Constructor is relatively simple to understand definitely use it whenever you need to ensure some initialization logic happens and ensure that it happens in a static context and not just on a per object basis hi there so quick intermission are you are you enjoying the course are you learning quite a lot I really hope so I hope you're paying attention I hope you're taking it slow and real learning everything also remember to pause at the end of each lecture and dive deeper into each topic I made sure to include the titles for all the frequently last questions all the quizzes and interactive exercises those only show up at the end of each lecture so you can use that to guide yourself or you can pick up the premium version of the course to get all that info in the really nice companion project so if you can't afford it you can use that page to dive deeper into each topic but if you can't afford it the companion project makes it really easy to keep on learning all right so let's keep going hello and welcome I'm your Cod monkey in this lecture we're going to learn about the type of operator this operator lets you get the type object of a certain type okay so type of now we've actually already used this a few times in the reflection lecture and also on the one on type casting the way we do reflection is by accessing the type and I don't mean by accessing the type name itself so if we call Just Player if we do this nope we are not accessing the type itself this is not valid code in order to access the type object meaning the object of type system. type the way we get that is with the type of operator which works sort of like a function so we write type of then parentheses and then the type within it and if we do then we can see that this does now return an object of type system. type like it says here this represents type declaration so class types interfaces arrays values and numerations and so on so this is the base type that references pretty much any type you can create so now with this type object then over here you can do all kinds of things so you can get n types n function and so on so this is how you access the reflection that we already covered whenever you have some kind of function that requires a type object meaning system. type if so then this is what you want to use like for example when working with some Unity code if you want to get the component attached to some kind of game object use the get component function and this one actually has two versions one of them is this one with the angled brackets meaning this one is using generics this is actually the version that I normally tend to use so just put this and then inside you put the type that you want to get so just like this it's going to get the component of type player however alternatively you can also use the other version so this one over here which is non-generic and note how instead of having a generic parameter this one receives a parameter of type type so this is where you would use it if you were to use this and you just type in player if you do just this then nope this is not valid code again that's the difference between having an object of type player as opposed to accessing the type directly so in order to make this work in order to use a function that receives a parameter of type type for this one we use type of and yep now this does return the correct thing and this will return a component of type player this is the one thing that you definitely need to remember this is something that drove me crazy for a long time until I finally memorized it whenever you see something that takes a type parameter whenever you see that always remember you have to use the type of because yeah for me it has happened many times where I see a function like this I try to use like this and I have no idea what is wrong and the reason that is wrong is exactly that we need to do type of in order to get the object of type type and now this does work we alternatively like we saw on the lecture on type casting you can for example create an object of that type so for example making a brand new player and another way to get the type of type player if you have an instance of that type you can just call the function get type and Yep this is going to return the exact same thing so if you have an object of a certain type you can call get type and if you don't you can do type of and then pass in the class name itself so yep that's type of it's very useful when you need to get the type object to use in some kind of code hello and welcome I'm your Cod monkey in this lecture we're going to learn about the name of operator with this one you can get the string name of a certain type or field or fun function okay so name of this is an operator meaning you use it sort of like a function so it's similar to the type of that we already saw so you write name of and then inside parentheses you put the name of something that you want to get the name of now the main benefit of this operator is to avoid using strings which is something that I always highly advise you to do you should never use strings to identify something so if you want to reference the player class if so do not type A String just same player so don't do this instead do something like this so player class name you do name of of the player class so instead of using hardcoded strings use name of to avoid using strings directly in your code this also helps avoid issues with refactoring so if you have a hardcode string kind of like this one if you do this and you refactor so instead of player let's call this just a general unit if so then yep now this literal string this now completely wrong whereas with name of if you modify the name inside of here the name of the actual tabe itself if so then what returns from this is going to be updated now this works for classes but also for fields and functions so for example let's actually do a log just see what this says so let's do a conso the right line let's print out this one to see what this says and let's also rename this back into player okay let's test and if that's it it says literally player this gets just the string name for the class whereas for example if you do type of in order to get the player type and then you convert that One automatically into a string let's see what this says and Y if you get the type then you get the whole thing in order to get to the type whereas with name of you get just the name of that class that type that something so this works with types itself like these but it also works for fields and functions so we can do this print out the player speed and print out is grounded and if we run this and Y this return exactly the name of those elements so it can work with classes with Fields with functions and pretty much anything one thing this is great for is for example for debugging so for example if you want to validate some kind of function so over here let's say a public void set spe in order to set the player speed this one let's receive an in for the spe and then set this. speed equals this kind of speed however for debugging for some kind of validation we can add some extra logic here we say for example if speed equals zero if it is let's say this is an invalid value so if so let's do a console that right line let's print out to the console error and then instead of hard coding saying speed must not be zero instead of hard coding this because again if we were to modify this for the something like set speed and so on if you were to modify to something then a hardcoded string would not update whereas if we have the name of here so name of and pass in this speed parameter so this parameter name if we do this yep now this will indeed work so up here let's call create a brand new player and call player. set speed and let's set it to zero and if there it is now that is correct so error speed must not be zero and if we were to refactor this so speed to set if we do this and yep now it correctly sets the parameter name exactly as it should be so this can be really great for making your documentation a little bit more robust again anytime you can avoid using hardcoded strings that is always a better approach and technically this one also has a nice performance bonus for example if you already have a player you can technically go and call get type and then from type you can just access the name so this works and this will pretty much print out the exact same thing as here so let's actually do that so console that right line and there it is this one prints out player exactly the same so the one performance bonus is if you do this if you access the object you get the type and you get the name or alternatively you would just do type of of the player type and then grab the name doing that that code would actually run at runtime whereas over here the name of this one is executed at comp time meaning that when the code goes to compile this code when it does that the compiler replaces this line of code over here with a literal string so as soon as you compile instead of this code being right here it will replace it with exactly this so this is a tiny tiny change but still a nice bonus so it's a tiny bit more performant all right so that's name of if you ever need to get the string name of a class or field or function or anything then use this instead of hard coding a string this makes your code more maintainable and less airr hello and welcome I'm your Cod monkey it's in this lecture we're going to learn about the size of operator this one lets you see the size and bytes that are used in memory to store a certain type okay so let's see the size of operator now this one Returns the value in bytes of a certain type like for example we know that ins are stored in four bytes so if we have an inti we know this is going to take four bytes and we can test that let's do a console. right line and let's print out the size of this is an operator so we use it kind of like a function so kind of like the type of and name of and this one takes in a type so let's put in int and let's see and yep ex like that four bytes so we can see the size of an INT we can also see for example the size of a bowan and yep a Bing is only true or false so this one only takes one bite or for example let's see a u short which is a much smaller version of storing whole numbers and if this one unlike the in this one takes just two bytes or on the other hand we can see for example a long and yep a long takes eight bytes so yeah basically this one lets you see how many bytes a certain type occupies now this is extremely important for memory management memory management becomes really important when you're working with some very memory limited devices like for example if you're doing something on some very old mobile devices or maybe some iot or embedded devices or perhaps if you're syncing data in a multiplayer game if so usually you want to limit how many bytes you send over the network as much as possible the less you send the less it's going to cost in terms of bandwidth so knowing that a u short is much smaller than NT that can be very helpful if the number you are trying to send across the network can fit with any a u short or it's also useful if you're doing some spefic specific lowlevel memory management where you need to allocate some unmanaged memory manually this way you know that for example if you have 4 ins you know how big that will be in memory so as we saw you can see the size of all the built-in types so in B short and so on this way if you have to sore let's say 1,000 ins you know exactly how big that won't be in memory however you cannot use size of on classes so for example if I put here of the type player nope this one does not work so we cannot use size of in class like it says here player does not have a predefined size therefore of can only be used in an unsafe context now there is a lecture in the advance section later on on using unsafe this basically removes all kinds of protection that c has by default so that's one option is you would use unsafe and then put this inside an unsafe and if this wouldn't work you just need to enable unsafe compilation or alternatively if you need to know the size of some kind of class for that you can use go inside the Marshall class which exists inside this names space system runtime interrupt services and inside you do have a size of although this this one has a bunch of strange limitations that honestly I'm not very familiar with I'm definitely not an expert when it comes to marshalling data dealing with btes and all that stuff but over here if we don't include this attribute then this throws this error it says cannot be Marshall as an unmanaged structure no meaningful size or offset can be computed and with that attribute it does work does store it in four bytes but then if I were to add some like a public list of ins for some kind of int list if do then yep that shows that same error again so honestly I'm not entirely sure how to make all this work I believe you have to use the mar as and then Marshall this field as some kind of unmanaged type and then you have the select the one that is related to whatever type you're trying to Marshall but like said I'm not an expert in marshalling so I'm really not entirely sure how this whole thing works but basically you can use the standard size of to get the size of any of the built-in types then for classes either use Marshall do size of or put it inside an unsafe context and for structs this one also works so you can do Marshall do size of of some kind of struck that has some kind of data again it can't have any kind of manag data like a list but if we do them like this give this PR the size of that struct is 8 bytes which makes sense since it has hello and welcome I'm your Cod monkey in this lecture we're going to learn about the default operator this one is really useful for when you want to assign a value to initialize something but without giving it a specific value okay so default now we've actually already used this keyword in two scenarios so for example we use it in some kind of switch so you define something do a switch on that something and then do all kinds of cases so case some kind of number run this code and if not if it does not match any then run the default case so basically this the code that will run if the value does not match any of the other cases and the other scenario where we've also seen the default being used for that was on the lecture on the optional function parameters so if we have some kind of function public void set Spen and this one receives an in for the spein and if we want to make this an optional parameter if so we just have to do equals and then default it to some kind of value so you can default it to a fixed value or you can use default the default keyword which will return the zero equivalent value for that type now there are actually two ways to use default the shorthand and the normal way now the normal way is using the operator default kind of like a function so we do default and then for example we pass in the type so let's say int let's do a console right line on this to see what this says yep there it is zero like I said default will return the zero equivalent value of that type so in the case of an in the zero of an INT is indeed just zero however if we try to see the zero equivalent of a bullion Yep this one prints false in bullion you have either true or false where true is usually equal to one and false is equal to zero so for the zero equivalent it returns false and then for class types like for example a player class for that class types of default is going to be null remember the lecture on value types versus reference types value types always have to have a value so when we do a default on something like an INT which is a value type when we do that we have to get a value but references like the player class these can simply have a reference that points in nothing meaning null so default of any kind of reference type is going to be null now this is the quote unquote Norm way of using default use it as an operator with parenthesis and then put the type inside of it however another way is just to let the compiler in for the type for example if we just Define a float variable if we do this and then for assigning we just assign it to the keyword default and if that's it no per with float just like this and Yep this does work so if we print out DF and if there it is a float does default to zero which is actually the exact same thing we are doing down here on the optional function so we can just write default or we can write default int and Y both these work exactly the same now another place where default is very useful is when working with generics so for example if we have some kind of class for some kind of box and this box stores an object of type T then over here let's do a public going to return T and let's call it get default so on this function we want to return the default value that is stored inside of this box now by being generic that means we don't know what type T will be maybe it's going to be an INT or maybe a bull maybe a player we really don't know so over here on this function to get default we can't really just return zero because again T might be something like a player and it cannot convert a player onto a zero it can also not be false it cannot be null and so on so in this if we want to return some kind of default value again we can just use the default keyword either with the short hand or defaulty for the long hand and yep so now if we create a box of int bent player so for example up here let's do a console. right line let's do a right line let's create a new box let's do a box of ins and then let's call the get default let's see what this prints let's create a box of ins then a box of balls and finally a box of player okay let's see these three boxes and if there is zero false and then null so the same code now returns different default values depending on what generic type we use or alternatively when using the ref and out keywords I'm going to cover these in detail in a future lecture over here on the advance section if we were to do an outb is set something like this basically the out keyword means that this parameter is an output parameter and must be set before the function ends so again for these if you want you can Define some kind of default value you can default that or you can just use a default keyword so if you ever need a default value for something instead of hardcoding some value you can just use a default keyword it will use the zero equivalent value of that type usually that is either number zero or false or no hello and welcome I'm your Cod Mony in this lecture we're going to learn about expression bodied members this is a way for you to write C code in an extremely compact manner without having to sacrifice readability Okay so expression bodied members like I said this is a very compact way of writing some code for example if I have some kind of player class and inside I have some kind of player name and then I have a function that Returns the player name so get player name so I can do this and then simply just return the player name and if that's it a very simple function this is the regular normal C code however we can make this quite a bit more compact by using expression body members basically if you are familiar with the Lambda Anonymous functions and this is basically the same syntax so we Define the function and then instead of opening a code block instead of that we do a little arrow and then we just put what we want to return so in this case just player name just like this so if that's it this is the whole syntax super simple so basically this and what we had previously both are doing the exact same thing the compiler basically sees that this function returns a string so it automatically adds a kind of return statement here so this one does do the same as the other version it just returns a player name now this method expression body members this is really only meant for extremely tiny pieces of code in fact you can't even do a a code block with this syntax so if I try opening and closing a code block nope this is not valid code you cannot do a code block with this syntax which means that this feature can really only work with single instructions you cannot use this on things that require multiple instructions you can use it like this in order to return some data from a function but you can also use it to set some data so for example a set player name and receives a string for the player name and we can do the little arrow and set this. player name equals this player name and Y there you go another perfectly valid function again with same limitations this one can only have a single instruction so if you need to do multiple things you do still need to use the regular normal C code block but for super simple things like just getting and just setting then this makes the code quite a bit more compact in fact one place where I've used this quite a few times is for function passrs like for example if you have some kind of class and that class is really just meant to be a layer of abstraction for another class for example when I made a turn-based strategy game I had some kind of level class and inside that one I was using the actual underlying grid system and for some fun I really just wanted to pass that function call onto the underlying rrid system so for this use case this super compact function pass through this is a really great option so here we can see how this works for functions but it can also work for properties so for example if we have a public string player name just a regular property if so we can do the get and now normally we would write a code block however we can do the same thing just a little arrow and this case return player name so this is a readon property or we can also assign the set player name equals value Yep this this is also valid code or you can actually also use it in a Constructor so if we have public player Define a Constructor with some kind of string for the player name that receives on the Constructor so here we can do the little arrow player name equals player name and Yep this is a valid Constructor code however again the same limitation this only works if the Constructor has just one instruction so for example if over here we had two films like vector 3 for the position if so we couldn't set the player name and then set the position on the same line of code so expression body members are really good for making some really compact code but as always you should never sacrifice readability for compactness so personally I really like how this has a whole bunch of limitations which means that it can really only ever be used in situations where it should be used if you have some extremely simple get and set functions then this can be quite useful without having to sacrifice any readability hello and welcome I'm your Cod Mony in this lecture we're going to learn about C records this is a super simple way to create immutable types to organize your data okay okay so records the basic usage is actually incredibly simple so first you write the access modifier like let's say public then we write the record keyword and then some kind of name for this type like let's say person and then we open the parenthesis and we write our parameters so for example something like first name and last name and yep that's it just with this we have created our person record so as you can see if you need to organize some data it can be similar to just def a simple record as opposed to defining a home class so for example something like this so person class if we had this we would then have two properties so one for the first name with a get and a init meaning needs to be initialized and same thing for the last name so basically over here we have the exact same thing written twice we have two pieces of data which in the case of Records the underlying compiler these are actually Auto implemented properties and they are also immutable meaning they only have a get and have no set and also they need to be initialized so y this super simple record is exactly the same thing as the you can see how this is quite a bit easier to write whenever you need some kind of structure to hold some data and then to construct a brand new person you really just find person and then you can do new person or really just open up the new like this and then pass in the all the parameters so in this case let's say code monkey and if that's it here is our brand new person so we easily Define in just one line of code and easily created in this one then with this let's do a console now right line in order to see person what this says and if there it is the two string automatically writes out the type so person and then all the parameters and all data they have so Yep this is how simple records are and now by default records are indeed like this meaning they are immutable they have no set they cannot change here if we try creating a brand new person and then go inside the first name and modified to something else nope this does not work this one can only be set once it is initialized it cannot be modified afterwards however if you really need to technically you can make it mutable you just need to define the record and then instead of doing a semicolon you just open a code block and now inside you can Define all the properties so for example first name and on this one let's put it with a get and with a set in order to make it mutable and we just have to do equals first name in order to make sure that the value that it receives over here is the same one that is set to this property same like this if we now do a person and go inside person and modify the first name to something else yep now this is indeed valid code however records really are primarily meant to handle immutable data so you really should avoid doing this unless absolutely necessary the fact that they are immutable is indeed part of the purpose immutability is really great for handling static data especially when working with things like multi-thread code if you have multiple threads all them accessing an object that is mutable it can cause all kinds of strange issues all kinds of RIS conditions when multiple threads try to write to the same field at the same time whereas if a field is marked as immutable meaning that data can only be read that eliminates all those issues now if you want you can also do something that is called non-destructive mutation which really just means creating a brand new record based off another record so for example over here we can do person call it person two and we can start from thata contained inside person and then use the keyword WID then open some currently brackets and now here overwrite any of these so for example let's say last name set it to gorilla and if just like this so now we have person and we have person two and there it is the first one Code Monkey second one code gorilla now this is technically called non-destructive mutation because in reality it doesn't really mutate the original data this one still stores the exact same thing basically just creates a brand new one using the parameters from the previous one also over here we are really just using the record keyword but what this is really doing is really the same thing as writing record class so by default records are going to be classes however if you want you can also make it a record struct Yep this also works so your records can be either classes or structs however in terms of equality they mostly behave like structs they mostly behave like value types meaning if we make this a record class and up here let's create two persons so let's call it and person three so here we're doing new twice so technically these are two objects so if person was a class these two would be different because they are different objects however if we do a consant out right line if we do that and we check person equals person 3 if we check this Yep this one does return true now in a normal class If This Were a normal class this would return false because these two are technically separate objects however since this is a record class because that the equality behaves more like struct meaning it checks the underlying values for the equality again this is because records are really primarily meant to be used for data organization so the equality logic is all made based on that then if you want you can also handle inheritance with records so for example we can do a public record let's call it unit and inside let's do some kind of float for some kind of speed and then we can have a public record for some kind of player this one receives a string for a player name and also a float for a spein and this one then extends unit and for the parameter it pass in the same speed parameter y have that's it this is valid code also when one more note technically records were only introduced in C 10 and unity is actually currently on C 9 however it does support records but in order to make it work it requires a slight workaround so here I have some Unity code and if I Define let's say some kind of record for a player receives a string for the player name so this is a record however if we do we see this error so predefined type system. runtime. compiler services. is external nit is not Define or important so in order to make this work in order to make records work inside of Unity for that we basically need to create this type so we need to put it inside of this namespace so we need to create a class inside of a namespace so let's do a namespace and name it like this Exel like this so system. runtime. compiler Services let's open and close and then inside we need to define a class and the class has to have this exact name so is external in it and Def find a class just like this so it's all completely empty it really just needs to exist and if it does exist and Yep this is now valid code all right so records are an interesting way to very quickly Define a type to hold some data instead of defining an entire class or a struct you can very quickly Define a record and have it with the perfect accessibility for some immutable data hello and welcome I'm your kodm in this lecture we're going to learn about null conditional operators these are two operators that help simplify your code by eliminating the need to do some null checks now this is actually something that we already used in the events lecture if you remember for events before you invoke the event before that you need to test whether the event is null or not not otherwise it won't throw a n reference exception if there are non listeners and the compact way that I showed you for doing a null check is with this question mark this is what is called a non-conditional operator and basically the code is executed from left to right so when the code reaches the question mark at that point it checks in left side if this left side is null if so then this instruction terminates right here and just moves on to the next one however if the left side is not null then it continues executing onto the right side as if this question mark was not here so basically the question mark this does a null check at this point and on the right side you can write any code with a safe assumption that the thing on the left side is not null also when I say that the instruction terminates here if it is null what that means is that this whole thing gets evaluated into null so for example up here if we do a consant out right line let's we function to print something so a public string get player name and let's just return a string so something like this and up here let's just construct a player so player and actually let's leave it in no and now we do player then the question mark and then get player name so if player is set if so then it's going to return the player name but if the player is not set then this whole thing is going to evaluate into null so if we run this if there we go it's empty meaning that it's actually null so we can test and verify equals null and if that is indeed true so if the left side is null then this whole thing evaluates into null whereas if this one is not null so over here let's just construct a brand new player so this one is not null if so then yep it runs the entire thing and calls the function and by the way like we saw here you can call any function after the question mark so the standard that I showed you for the events is using invoke but that's just a event specific thing however the question mark the null conditional operator this one is not limited to just events so as you can see it works over here for the get player name and also works for Fields so over here if we have a string player name if we have this and up here we can call the same thing player name yep just like this so basically it's only going to access this field if the left side is not null and also you can have multiple of these in a single line you can chain them together so for example if the player if over here it had some kind of player for another Target if so then you could do player question mark in order to make sure it only runs if not null Target another question mark to make sure that it runs if it is not null and then call take damage over here pretty much the same rules apply so basically as gets to this question mark it checks the player if the player is null then terminates the whole thing with null but if it is not null continues running the right side and then gets to this question mark and checks in left side so if the player. target if that one is null if so then again it terminates over there but if it is not null then it's going to call take damage on the player. target so the same rules always apply regardless of how many non-conditional checks you have now the second non-conditional operator is pretty much the same except it's for index accessing so for example if we have a list of strings for some kind of player name list if we have this we can do for example player name list do a question mark and the then the square brackets to access on some kind of index like this so let's do a console right line on this and here the same thing will happen so if the list is set to null if so then when it gets to here it's going to stop evaluating whereas if this one is not null so if it has something like for example let's say just one element if so then yep it is going to go inside the list and grab it on the this index like this does print code monkey and of course you can combine both of them so you can combine the one accessing strings and the one just accessing properties and Fields so instead of UN list of player names let's do over here a list of type player so player list and we have a new one and over here let's construct a brand new player so now on this we can go inside the player list we can do the question mark and then the index access on index zero then do another question mark and call some kind of take damage function so it checks the player list if it is not null continues running to the right side it checks one an index zero if it is not null continues running to the right side and runs the take damage function so if over here this element on zero if this one is null then it would safely stop the execution right here however this will still throw an error if the index zero is out of range so do be aware of that and since the home point of this whole operator is doing no check it can only work on null types like reference types so if we put for example in I and set this something then I question mark. compare to nope this is not valid the question mark operator so the null conditional operator this one cannot be applied to an INT again that's because int is a value type so it cannot be null however if we make this into a nullable so we add a little question mark if so then this does not work so we can call two string Yep this works if you don't know this syntax this is nulli bbls and I'm going to cover nulli bbls in a lecture later on in this Advanced section all right so that's the two nonconditional operators quite useful for very easily doing some n checks and especially useful for making your event invocation much more compact without sacrificing readability hello and welcome I'm your codm in this lecture we're going to learn about the n Ling operators these two will let you easily test for null and return a value or test for null and do some logic okay so the null quessing operator now this one is defined by two question marks and the simple use case is for testing if something is null and if so returning some kind of value so for example here we have some kind of string player name and then we've got a function to get the length of a certain string this one receives the string as the parameter and just Returns the string. length and then over here we're trying to get the player name length by passing in the player name onto that one and then printing get out however if we run the code like this without assigning player name to anything if there you go naturally we have a non reference exception if we don't assign any value to a string then that one is going to be null so over here we can add some kind of a null check so let's find the player name then if player name if it is null if so let's put this one equals get the string linked and pass in just an empty string if not then let's assign the player name length equals our string length so we do a n check and depending on that we get one or the other so let's see and if now it does work so without assigning an actual player name just return zero so no more errors this code is working and we can do exactly the same thing but in a more compact manner using the noncing operator the way you use it is for example by writing the player name then two question marks and then basically here we want whatever this is going to evaluate to if player name is null so for example we can do this meaning that this will either evaluate to player name or an empty string so if we use this instead and put it over here here and just have one of these y just like this so basically this one this instruction here what it does is it evaluates the left side left to the question marks and if this one is not null then this whole thing is going to evaluate to just this value however if the left side is null then this whole thing is going to evaluate to whatever it is on the right side so basically if player name is not null then it's going to call get string link to the player name but if player name is null then it's going to call get string length with an empty string so now if we test and if there we go no error and does return zero and now if we give the player name something so let's say code monkey and if now the exact same code also tests for the null check and now gives me the actual length of the actual string so here we are doing exactly the same thing we were doing previously with the null checks but in a much more compact manner now I can also link multiple of these together for example let's define here a string for a default player name and let's assign to something then over here we can do player name double question mark default player name double question mark and zero so you can change multiple of these together if we run this code yeah there you go it does return seven which is exactly the length of this string so basically this is going to execute from left to right so if this one is not null then returns this one but if this one is null then goes to the next one and if this one is not null then returns this one however if this one is null and this one is null then returns this one so this operator is really useful for very quickly doing a null check and returning a nonnull value instead of doing if else testing for null you can just write this and everything works perfectly by the way on the right side instead of just returning a value you can also run some logic so for example if player name is null you can throw a custom exception with a custom message now the second operator that one is the null coaling assignment operator in terms of syntax is exactly the same with double question marks the only difference is that has an equals at the end so for example if we have some kind of player class in a player field if we try running some code on the player here let's just do a player. two strings let's we consel that right line on this if you do this then naturally this one will throw a null reference exception because player is indeed null so as a way of doing some kind of initialization we can can write player then double question marks equals and then new player basically what this does is it's going to check the player variable if that one is not null then nothing happens just continues executing the code afterwards however if player is null if so then it's going to construct a brand new player and assign it back onto this variable so this operator can be really great for initialization like for example let's say the player down here has a list of other players to Target and now usually if you have this kind of thing you can either initialize this list directly on the Constructor that means that the list will be constructed as soon as the player spawned however you can only initialize it when an enemy is added so if you have a public void add Target player this one receives a player for the Target player and now here if you just go player Target list and add the target player if you do this then naturally this going to throw a non reference exception because this one does not exist so before this you can do double question mark equals new list to initialize the list so basically if the left side is already initialized if this one is not done then this line of code is going to do nothing but if the left side if the list is indeed null if so then it's going to evaluate the right side which is going to construct a brand new list and assign it so this operator is great for initialization or really just any kind of null check where you want to run some code only if the left side is null also what we covered in the previous lecture the non-conditional operator like I said that one returns null if the left side is null so for example we can do player then question mark in order to make sure we run the code on the right side only if it's not null then call some kind of function like get player name and then have double question marks and say unknown player so basically what this is doing is if the player is not known then it's going to go inside the player object and call get player name it's going to return that however if the player is null if so then this whole thing is going to evaluate into null and then we have a no then double question mark and something so it's basically going to return this one so if player is no it's going to return unknown player but if it is not no then it's going to return the player name and by the way since the whole point of this entire operator since the point is to do a null check now naturally it can only work on null ball types like reference types so if we Define an INT if we do this then naturally this does not work whatever is on the left side has to be a nullable type however if we make this instead of regular int into a nullable int if so then yep now this code does indeed work I'm going to cover NBL in a lecture later on in the advanced section but basically they allow you to make any type like a Bare Bones in and make it into nullable so that's the two null quessing operators another very compact way of doing a null check in this case to return some value do some logic if something is indeed n hello and welcome I'm your codm in this lecture we're going to learn about the tary conditional operator this is how you can write some super simple IFL statements in a really compact manner okay so this is another simple way to write more compact code here I have a function with a regular normal if it's called get player State string just as an if if the health is above zero if so then returns an alive string if not returns a dead string tip like this if the player has 100 health if it works the player alive and if over here set it to zero and if it works the player's dead so this code Works however a much more compact way to write literally the exact same thing is like this we just write the condition without the if keyword so in this case Health above zero then we write a single question mark and then whatever we want to return if the condition is true so in this case we want to return the live string and then we write a conon and then what we want to return if the condition is false so in this case we return that so you can do the whole thing and then then just return it basically this entire thing this going to evaluate into this code if this condition is true or this code if this condition is false which legally means that over here in just this one line of code we have the exact same logic we have down here so it really is this simple anytime you want to do a super simple if else then you can just use this it is more compact but also being very readable now technically you can also use it to run some logic so you write the same thing then on the right side instead of just a normal value you can run some kind of function with some kind of logic so teally this is valid however you have to make sure to either assign to something or return something because otherwise like this this is not a valid assignment not a valid instruction so technically just to demonstrate how you can run some more custom logic like call function directly inside of this format however for this usage I would say this is maybe sacrificing a little bit of readability so personally I would really not use this I really only ever use the tary conditional operator for super simple IFL statement just like this one and for these yep theary conditional operator is definitely an excellent way of making them really nice and really compact so if you can use them without sacrificing readability definitely go ahead and use them hello and welcome I'm your codm in this lecture we're going to learn all about the main function in a c program and how to receive command line arguments this is very important to know when making normal console apps doing things that do not have a UI by using command line arguments you can still control what exactly you want your program to do okay so we've already been using console apps a lot in this course it's the easiest way to write and run some C code we just make a console app project and we end though pretty much with this code then if we run this y there you go there's our super basic console app now by default it creates this main function this is our program's entry point meaning as soon as the program starts running it will automatically call this function and start running it line by line it continues doing that until this function terminates at which point the entire program Ends by the way in case you're wondering so how do game engines work if the entry point is just a normal function that runs line by line eventually terminates if that's the case how does a game engine run Logic on every single up upd dat and the answer is actually quite simple so game engines or really any program that lives for more than just duration of whatever it is doing usually they have some kind of while loop so here while either while true do something and if so then update some kind of update function then when the player presses the quit button at some point it just breaks out of the cycle which then terminates this one and terminates the entire program so it can obviously be more complex than that but that's a general gist of it all programs have a single entry point and then if you want inside the entry point you can have code that runs constantly Non-Stop and at some point the function ends and the program terminates so main this is the starting point and it actually has some very specific requirements the main one being how it has to be named exactly main it cannot be called something else it cannot be called start or even something like main with lowercase if we do this and we try to run nope it does not run we have an error here in the error we can see the program does not contain a static main method suitable for an entry point so the starting main function needs to be named exactly main exactly like this then another very important requirement is how it has to be static you cannot make this non-static if we do yep there you go same error again main has to be a static function and that makes perfect sense so the reason why it has to be static is because when the program first starts at that beginning you have no objects there's no instance of anything so you can't really start by calling a non-static method inside an object because no objects exist so that is why main has to be static so that it can be called in the very beginning of the program when No Object exists then this function also has to be inside some kind of class or struct and that one can either be static or non-static both of them work main can also have an access modifier you can make this either private or public doesn't really matter next for the return type for this one it can take many forms so first one is like this it can simply be void meaning we don't need to return anything or if we want we can return something and when we do then it simply won't execute any more code so we can either manually return or just let the function end normally alternatively we can make this return an INT usually this is done if you want to return some kind of exit code from your program and usually if you return in returning zero usually means success means the program ran correctly so there are no problems and if not if something went wrong then you want to return some kind of number that that refers to some kind of error code and the other two options for return types are task or task with a generic this has to do with asynchronous programming it's how you can have your program execute some logic without blocking the main thread I cover asynchronous programming in the lecture on async and weight if you want to learn more on that particular topic so here just know that main can return task it can be async but in most case you are probably going to do either void or int and if you do return int and you return some kind of value here you might be asking so if this function if the main function returns something how exactly do we know what this returns if we test a code like this here at top we don't see anything but here on default console at the end it says this message it says our executable exited with code 56 which is exactly the number that we said alternatively we can also execute our program manually so here I've got the command prompt opened and over here we can execute the program manually so just run the executable and yep it does say hello world but we don't see any return code now for that it is actually stored in an environment variable to ex an environment variable we use the percentage symbol then it is named error level and another percentage symbol so if you want to print this let's just do an echo on this and there it is 56 so whatever value you return from here you can access this one in order to get exactly what is the error code so that's the main return so either void or in that's usually what you do and the other important thing about main is over here the parameters here it can have either no parameters so this perfectly fine or you can have some parameters you can have a string array and usually by convention it is named arcs arcs for arguments so this will contain whatever arguments you use when running the program for testing let's print out these size this array so console let's do a right line let's do the ar. length also by the way here this array this arcs this one is guaranteed to never be known so there's no need to test for that here let's print out the SI array and then let's just cycle through it so a string r in args and let's just print it out so console. right line right line our ARG okay so like this if we run it just over here inside Visual Studio then we are not passing in any arguments so naturally it is zero but now here we are in the command prompt to run our code and if we run just like this again no arguments does return zero okay correct and then for calling it with arguments we just add a space and then add whatever arguments we want for example let's pass in the number 32 and if there you go it does work it did receive one argument and the argument is number 32 now here we can include as many arguments as you want of any type we want so for example for a string we can include the quotation marks say code monkey and then we can include maybe a volan so maybe true and if there it is three arguments 32 code monkey and true in terms of arguments usually what you might see are some kind of flags so for example have A- debug this would start the program in debug mode or alternatively you could have an argument like my data.csv so this would be the file that the program would open to do some kind of analysis arguments are really extremely useful when you don't have any kind of UI when you just want to program to run and just do whatever you want it to do based on whatever arguments it gets just like this don't need any UI and you can still do quite a lot of things now one very important thing here is how arguments this one is an array of strings so over here when we execute our code with the parameter 32 Code Monkey true technically that's a number that's a string and that's a bullion but in reality all of these are strings so if we want to get an actual number and an actual bullion if so we need to parse them now all of the built-in types they have a parse and TR parse function to do that so for example for the first one int do let's do a triy parse we can try parse and for the string let's grab the args and the first parameter was the int one we can do out in and let's call this the end argument so have just like this basically triy parse this one will return true if it does succeed in parsing and false if it doesn't and alternatively we have the parts and this one assumes that it will succeed now I covered these two functions in a bit more detail on the leure on data types how you can convert from types back and forth like converting from a string onto an INT and so on so you can do for example this and then for e b let's parse out the one on index two and then we can print those so let's print out a right line print out the r int our in argument then the second one is actually going to be a string so let's just grab the one index one and then for index two that one is going to be our AR ball so let's see here run our code and yep it did work we did get the n32 the string code monkey and the ball intro so this is how you can convert a string into whatever type you want and then you can do whatever you want using these now there's actually another alternative for getting some arguments technically you don't have to include the string array over here you can remove this and if you do then you can basally go inside the environment and inside there's a function called get command line arcs and this one does exactly the same thing so let's receive a string like this arcs so like this our main does not have any parameters but still let's try so here let's run it and if it worked although we got one extra argument so the very first one is a path to the dll so you can either include it directly over here or grabb it from this and this can be quite useful if you don't have access to actually modify the main function if you can't modify it then it suck with no arguments you can still use this to grab whatever arguments we used and finally if you have multiple class in your code base for example let's do a public class another program and in this one if we also Define a static void main function as well if we do this in test nope here we have an error it is saying the program has more than one entry point to find this is how you can only have a single entry point there can only be one you can't have multiple possible entry points now we can still do this we can have a different class that also has something called public static void main we just can't have two entry points so if we have this two classes that both have a static void main if so then we just need to Define which one we want to be our entry point so here let's do a console d right line let's call it another program and way we modify that is over here on the right side let's go on the solution Explorer then let's right click on the project important it's on Project not on the solution so right click over there on the project and let's go down into properties and then it's over here under General that we see the startup object this one like says defines the entry point to be called when the application loads so it's over here that we can select and it's basically going to show us the classes that have a main function so let's say we want to start out from the another program yep just like this now let's test and if now it runs and ran exactly starting from that one all right so that's the main function and command line arguments with this you can see how you can have quite a bit of control over even some very simple console apps you can make some very complex programs that do lots of things depending on the arguments they are given so always remember how you don't necessarily need need complex goys for a lot of programs like just a simple console app if you just include some arguments it will likely be simpler and work just as well hello and welcome I'm your Cod Mak in this lecture we're going to learn about nullable this is a special built in type that lets you make any type nullable even value types like in and B okay so in a previous lecture we already learned the difference between value types and reference types how reference types like for example a class they can be set to either no or an instance of that class but on Val time like an INT you cannot set it to null so over here we can define a player field and set it to null this works but if we Define an INT nope this one does not work here we have an error cannot convert null into an INT because it is a non-nullable value type however C does have an interesting thing called nulles which lets us make anything support null even valy types and there's two ways to do it one is very simple we just add a question mark to the end the type just like this Yep this one is now a nullable and now we do not have the error we can now set it to null this works with any type so here we can make a nullable int we can make a b nullable this works we can also Define some kind of struct Define some struct and over here if we just have the struct the stru cannot be null but if we make null all yep that does work so we can really make anything support null by adding the little question mark by making it into a null B now this can be really useful if the variable is only used in certain scenarios like for example let's say we had the player and this was some kind of strategy game so this would be some kind of player unit and inside you would have an in for some kind of attack damage that the player could deal and we could Define some kind of value if we wanted the player to actually deal some damage or alternatively we could Define it as null if we want the player to not be able to deal damage like let's say they have no weapon equipped setting it to null makes more sense in defining the attack damage is either zero or minus one that makes it a little bit confusing that this specifically means no attack damage whereas null makes it much more straightforward this means we have no attack damage or alternatively null bols can also be very useful as function parameters so for example let's say we have some kind of setup function we use this to set up our player and in here we can receive an end for the starting health and if we do it like this then this one is a mandatory parameter if we wanted the player to keep whatever Health was set in the prefab itself meaning if we did not want to override it with any kind of starting Health if so we can just Define it as nullable and then default it to null again that would make a lot more sense as opposed to making a normal in defa into zero and then having to remember that okay if the health is zero that means do not override what is on the prefab instead we set it to null and this one makes quite a lot more sense so NBL can be quite useful to make literally anything nullable and if it does have a value if it is not null you can just cast it and use the value so for example up here we got our I it can be null or it can have some kind of value and to grab that let's say in attack damage we can grab the value and simply just cast it yep just like this although of course this one is going to throw an error if we have null here so if we do this yep naturally we have an error so in order to do this before we cast it we can check if I is not null if so then let's actually grab the value and if it is null then don't do that alternatively instead of checking it against null itself if so we can go inside this one and inside we have this really interesting property called has value this one like name implies is going to be true if a value has been set and false if it's null so we can check if it has a value if so then let's cast it onto our value or alternatively we can also do something instead of doing a cast so instead of a cast we can go inside and we can grab Direct Value and this one is going to be of whatever type it is the type that we made null so y just like this no need to test directly against null no need to cast it just like this everything works or yet another alternative we can go inside our n LEL and inside there's a really nice function called get value or default and this will either return the value or some kind of default so we can use this function that returns a default value so if you put it something like this like a 12 let's put a console that right line on this okay so let's see what this one returns considering how this one is null and of course it returns 12 so that's how we Define nullable and how we interact with it but like I said there are two ways to do it this is just one adding the little question mark and the other one is to much more explicitly use the nullable class so there's a class called nullable just like this it takes in a generic parameter so we can do n of in just like this and it that's it everything else works exactly the same way it also supports null it also has the has value and the value it also has this function really writing this or adding the L question mark ends up the exact same thing this one is really just a shorthand both do the exact same thing in reality this class is really just a wrapper around some kind of value so it has a bullion and has the ACT value so it's essentially just a class with two Fields instead of being just one and then if you want null BS can also work very well in combination with the nulling operator that we saw in your previous lecture so we can Define let's say an INT nullable call it a set it to null then int B and let's set it to either a if a is not null but if a is null let's set it to let's say 56 and if this works so B will be set to the value of a if a has a value if not if a is null then it will set a default value all right so that's nulls whenever you have some code with some Val type and you want to make it support null then go ahead and use it it is super simple you just had a question mark at the end and all of a sudden your code your field now supports n hi there so quick intermission are you enjoying the course are you learning quite a lot I really hope so I hope you're paying attention I hope you're taking it slow and real learning everything also remember to pause at the end of each lecture and dive deeper into each topic I made sure to include the titles for all the frequently last questions all the quizzes and interactive exercises those only show up at the end of each lecture so you can use that to guide yourself or you can pick up the premium version of the course to get all that info in the really nice companion project so if you can't afford it you can use that page to dive deeper into each topic but if you can't afford it the companion project makes it really easy to keep on learning all right so let's keep going hello and welcome I'm your Cod Maki in this lecture we're going to learn about span and C this is a really interesting type that lets us do operations on slices of rays and do so in a super fast performance manner okay so let's see span this is a really interesting type that was introduced to C just a few years ago it allows you to grab a slice of an array and do it super fast and importantly without any memory allocations that's a crucial part of it so for example let's say we have an array of numbers so an interray for the number array and we have just a new one and then just have a whole bunch of numbers so a whole bunch of random things okay y just like this now let's say we want to sort this whole array but we only want to sort the numbers in the middle we don't want to sort the edge ones now way you could do this is by making a sub array so you define another array for the sub array you would Define it a new inter array and basically just use the length minus two so go into this one length minus 2 you do this then copy all those elements so only these elements then sort out this array then copy them back onto the numbers array yep you could do that technically that would work but doing that would also require creating a brand new subarray this requires allocating additional memory depending on how constrained you are in terms of resources that might be a problem it allocates new memory which of course also then has to be garbage collected so once again another potential issue for performance problems so in order to solve that and many other problems for that we have the span dipe a span is really just a slice or it can actually be an entire rray but importantly in creating a span we don't actually allocate any new memory it is a very special class that is all handled with pointers to the original memory all done in the background so the way we created is actually very simple we Define something of a span this one is a generic so let's use a type in this case we want the span of int let's call it our int span and then if we want this span to have the entire Ray we can just equals it so equals number aray and if there is that does work so now this pan again this one is not constructing anything this one is not constructing a new object Instead This span now simply has a pointer to the entire original array so you can do this if you want the entire array or in our case we only want to sort the ones in the middle so let's grab a subarray so we can do a new do a new span this one has a whole bunch of Constructors which first of all receives an array so that's number array and for the start like I said I want to start after one so let's start on one and for the length so over here we have 1 2 3 4 5 6 7 8 we have eight elements minus two let's grab the length of six and if that's it so here we created an in Span so that's a span it's basically a pointer in memory that is super fast and is pointing just these elements and inside the span we can do whatever we want like for example we can just call the sort function that's it very simple and importantly by calling this we don't need to actually update the original array so we don't need to Second through the span and update the new array elements we don't need to do that because again this span isn't actually holding any data itself it's really just a pointer to the original data so by modifying the data inside of this span we are also modifying the original data inside the array so if we do this and then we print out the values so let's do for each in number in the number array let's do this and in conso the right line let's print out the number so this should say five then all of these should be ordered and then should have a 10 at the end let's see and you correct so five then 0 2 12 so these are all sorted and at the end we have our 10 see if we sorted all the elements but just ones in the middle exactly as we wanted and very importantly we did not have any new memory allocations which in turn also means we're not going to have any garbage that needs to be collected which in turn means that our program will be much more stable and much more performant then with this span you also have all kinds of functions for working with this data for example you can copy just a slice onto another span or copy this entire slice and convert into an array you can do a slice of another slice or you can fill it all with a bunch of elements and again all this this applies to the original data remember how the span itself isn't actually holding any data it's really just a pointer to the original data in memory so in this case we made a span that takes all the elements in the middle now if we call it fill and we fill it with some kind of value let's see and if there it is just like that so the original array still has the first and last one unchanged but the ones we selected those have been filled with one number so span is really great for manipulating slices of arrays again without any memory cost then if you want something even more efficient and you only want to read if so then you can actually use a read only span and if this one is really the exact same thing but limits you to read only so you can't write to it on this one you can't fill it but if all you need is read only if you just need that and you need Extreme Performance then this one can be a great time now spans work on arrays and a string is really just a Shar array so for example if we have a string and inside we have some numbers let's say for example that we worked with with some code that contacts a website that receive this string with these values now let's say that we want to parse these values so one way would be to do a substring so you do Str str. substring and over here put the start index and length that would work but once again we are wasting memory to allocate this temporary string so if we are building a performance cral application and we don't want to allocate any more memory than we need to again we can use a span to slice a string although in this case for a string for this one using a span doesn't actually work if we do span sh for the sh span and do equals Str Str if we do this nope this one does not work it cannot implicitly convert that one into that one for Strings it only works the read only span and if this one does work so here we have a span which again is really just a pointer and memory to this data so now let's say we want to parse out these values we can go and set this one let's grab a slice grab a slice on zero go for a length of two and this going to give us our first number so we can do int. parse let's parse out this number for the int for the number one and then for number two really same thing let's slice star on three and go for two more values so then let's do a console di right line let's write number one and our number two okay let's see and if there it is we do have our two separate values and importantly just like this we did not spend any memory allocation cost whereas if we had done subrings in order to do the exact same thing we would have quite a little bit of a cost now one practical example for how this could relate to game development would be perhaps some kind of inventory system where the UI has various pages to show all the items so you would have some kind of array with all of your items and then for displaying each page in DUI instead of creating a brand new temporary array instead of that you can just very easily grab a span just grab a slice of that array that item array and use that to display it on the UI all right so that's span it's a very interesting type for grabbing slices of an array or doing some operations on it without having a memory cost this is a very useful type in some performance and memory critical applications hello and welcome I'm your Cod monkey in this lecture we're going to learn about the bitwise operators in C this is how we can do operations on individual bits of data okay so like we covered on the beginning lecture on data types C has a bunch of built-in data types you've got things like short and long and so on all of these they all store whole numbers but their range is different for example a short can only store 65,000 numbers then n can store about 4 billion and long can store an insane amount the difference in all these is how exactly they are stored in memory meaning how many bytes or how many bits they actually use by the way remember how one bite equals 8 Bits so over here a bite this one literally use just one bite so eight bits whereas a short uses 16 bits an end uses 32 bits and long uses 64 bits so for example here we have a bite in memory we have eight bits meaning eight zeros or ones this is how memory actually works it's all binary in the end so for example here we have the number zero then here we have the number one in binary this is a two this is a three and so on now in case you don't know how binary Works B basically every single position on this number every position represents 2 to the power of something so this one represents 2 to the^ of 0o this one 2 to the power of 1 power of two and so on and those Powers equal these values so this digit over here represents one this one represents two this one represents four and so on so in binary you basically just add ones or zeros to whatever number you want to build and then you just multiply it by whatever is the value on that digit and simply add them all together so in this case this one is a three so we've got a one over here on the two position so one multiplied by two is two and then a one multip by 1 is one then you do 2 + 1 and you have three if for example we wanted to store the number 13 if so we would have a one over here on the eth position so that makes so that makes eight then we would also have one over here on the four so that makes 12 and then we would have a one on the one so yep this one is 13 this is how you represent 13 in binary so it's really all just ones and zeros and the goal with bitwise operators is to basically let you manipulate these bits individually these are the four bitwise operations we can do we can do an end we can do an or and X or or an exclusive ore or we can negate for example up here we have the number two and down here we have the number three if we want to do an and operation between both these if so then we just do a normal bowling operation on each bit meaning that both of them have to be one in order for the output to be one so over here we do 0 and zero and the result of that is going to be zero this one is also going to be zero Z and so on then we get to this one one and one both are one so this one does relate to one and then we've got zero and one that one does equal zero so the the whole thing equals A2 doing a bitwise and operation between the number two and number three equals the number two so over here in our code we can Define just number two and find the number three and then do a bitwise operation so we do a and b now importantly it's this one just one % it is not two of them this one is a bullant and that is not what we want we want just one % to do a bitwise operation s like this let's do a conso d right line on this one to see what this returns and if there it is the number two exactly as intended so what we are doing here is doing an end operation but applying the end to the bits themselves another operation we can do is an or so this one outputs one if either bit is one so all of these that are all zeros these are all going to end up as zero then over here we've got one or zero so one of them is one so it becomes one then zero or one also becomes one and one or one also becomes one so the end result of doing an or operation between numbers five and three the result is the number seven so yep let's verify it here in the code we have numbers five and three and now let's do a bitwise or operation so it's just like this again just one pipe it is not two of them we do not want to do a bulling we want to do a bitwise or operation so let's see like this and if ex out like that we do have a seven another operation we can do is an exclusive or this one outputs one if either bit is one but not if both are one so in this case all of these are zeros then this one One X or Z that does equal one 0 x or of one equals 1 because again one of them is one and the other one is zero but on this one where both are one the xor does equal zero on this one so the end result of this one is the number six again here in the code let's verify so between number five and three Let's do an exor and to do that we use this little symbol apparently this actually called a carrot in Portuguese we just call it a hat so it's this one if we do an xor between these two values and if there it is we do have our six and finally we have the negate this one like name imply simply inverts all the bits so a zero becomes a one and over here one becomes a zero 0 1 1 into a zero here in the code the way we do a negation is we add a little TI we add a TI before our number so this is going to negate the number five let's see and if there it is the number minus 6 by the way the reason why the number is negative is because something called two's complement this is how the first bit the leftmost bit that one is used to note either positive or negative values that is also how back here if we look at all the types that c has you can see how we have both signed and unsigned versions basically the signed one the leftmost bit is going to define whether it's positive or negative whereas the unsigned ones those don't have a concept of positive or negative so they can start from zero towards some positive maximum okay so these are the main bitwise operations but we can also construct numbers directly from bits for example let's say we want to construct here the number four so in binary number four is really just a one on this position it's a one on the third position meaning the one on index two so this is index zero index one index two in order to construct this number we can use a bit chip so this is where we start a number usually one because it has Zer on everything except a one in here we start this one and then we shift it by several places so in this case we want to shift by by one and two and we end up with our four now here in the code like I said usually we start with the number one and then doing a bit shift we do two angle brackets so two less than signs and then the amount that we want to shift so in this case we want to shift by two places so let's see and after this this equals the number four we can also shift in the opposite direction so let's pick the number eight let's shift towards the right and shift by two places and if there it is we end up with number two so manipulating bits is really interesting but you might be asking yourself where would you use this in a practical manner now the main thing this gives you is the ability to store a bunch of data in a really compact manner so you can have each of these bits represents something like for example attributes on a gun for example let's say that this bit over here this one represents that the gun deals fire damage then this one let's say that it deals damage over time and this one perhaps is it causes stun so with just a single number with just a single bite with eight bits with just that you can actually store quite a bit of information so we can sort that the gun deals fire damage deals stun damage and Deals damage over time or more practically Unity actually use this a lot in layer masks as you probably already know game objects belong to a certain layer you can change the layer here and you can add a bunch more layers also note how there's a specific limit of 32 layers so from 0 up to 31 that's exactly why is because the layer this one is a bit mask it's a 32-bit bit mask and in the code when you do something like a physics rcast when you do this note how one of the parameters is an INT that represents a layer mask this is a bit mask it is not just a single number so for for example if you want to hit all the objects on layer six if so you would not put a six here instead you would Define for example in for the units layer let's say it's layer six and to construct an in for the layer mask the way you do this is by doing a bit ship so in this case one and bit shift to the left by the units layer so just like this this layer mask would mean that it would only hit objects on the units layer or for example if you want to hit units and buildings so let's say we have another for the buildings layer and this one is on layer nine if we have this we can bit shift this one onto the left and then do an or operation with one bit shift to the left by the buildings layer and doing in one operation again basically it makes one when either of them is one so it essentially combines two layers and doing so this layer mask would then hit things on units and or the buildings layer alternatively instead of all this Unity actually already has a built-in layer mask type so up here let's just make a type of type layer mask let's see and if there is we can see a layer mask and over here this one shows a really nice drop down menu so you can easily select all the layers that we want so for example select the attackable layer select the U layer the water layer and so on so here you can very easily select all the layers that you want and then Unity automatically construct a bit mask based on all these layers then another place where bitwise operations are used quite a lot is with inum flags and that's actually what we're going to cover in detail in the next lecture all right so here we'll learned about bitwise operators how we can manipulate individual bits in our data this is an excellent way to store some data in a really compact manner with just a single bite you can store quite a lot of information hello and welcome I'm your Cod monkey in this lecture we're going to learn about enum Flags this is a special thing you can add to your enums to make them work like bits which enables you to do bitwise operations on them okay so in the beginner section we already covered enums so here's a basic enum that represents various abilities now let's say we want to use this to Define what abilities our player has we can easily Define a field of this type and we can say for example that the player can jump okay that's it pretty simple but now let's say we want the player to be able to both jump and shoot like this we can't actually do it we can't do something like ability Jump Plus shoot that doesn't really work we can't add it onto here we can only override it so inside of this one we can really only store a single ability but that's exactly where enum Flags come in first of all we just had the flags attribute so up here an attribute for flags and this one by the way exists inside of system so we add that attribute and then over here we Define numeric values to all of the these inim values meaning we use equals and then some kind of number now specifically for this use case we want to use powers of two that's very important so for example for none let's assign it to zero for jump let's assign it to one for Sprint let's say two shoot four and fly let's assign it to eight now on the previous lecture on bitwise operators we already covered binary that's exactly what we're doing here in fact like we mentioned on the previous lecture over here instead of using numbers which can seem a little bit confusing instead of that we can just use bit shifting so you can you can do one bit shifted by zero and that makes a one then one bit shift by one bit shift by two and so on yep just like this so we Mark that as a flag and we Define the values as power of two now with this we can actually solve our original problem so we want the player to be able to both jump and shoot and with this we can now combine our enum values so we can make a jump or and this is the bitwise or so again just one pipe or ability. shoot any if that's it if we now do a log on this so let's we right line on the player abilities if there it is the player can jump and shoot so here we have the player abilities field that's just one field just a single field but it is actually storing two separate pieces of data it source that the player can jump and can shoot so here we Define it now let's say that we want to check if the player can jump if so we can just go inside the player abilities and we can use the has flag function so let's say if the player can jump let's do log on this like this let's test and if there it is it is indeed true the player can jump or alternatively since over here really we are just working with bits because this we can really just use some basic binary math so if we want to check if the player can jump if so we can just take our jump ability so just like this and then we can do a bitwise and operation doing an end with our player abilities and basically the output of the bitwise end this one is going to be one when only both these are one which in this case means it's only going to be jump so we can just compare if this one equals ability. jump let's put this one inside parenthesis so let's see if the player can jump and if that is true the player can indeed jump so enum flags are really super useful for combining multiple options in a single enum field it is just like the layer mask that we saw in the previous lecture how Unity has this type which lets you select multiple layers so here in the editor we see this fill and we can easily select as many layers or as few as we want and here Unity also already supports the flag enums so if we do this and we expose the field of our flag enum then up here in the editor we do indeed get our drop down menu where we can select as many or as few things as we want now another thing we can do with enom not necessarily related to Flags is we can actually Define the underlying type we want this enum to use by default this one is going to use an INT meaning it is actually going to use 32 bits but if you want to limit memory as much as possible if so we can actually Define what type we want this to use and you do that by adding a little colum and then Define this one as a bite so now sorting a field of this type is just going to occupy a single bite now naturally bite means 8 Bits so if you want to sort it as a bite you are going to be limited so y like this if we Define more than eight possible values yep here we do have an error basically a bite can only store eight bits so we cannot add nine possible values here if you want more of those then you can use a short or just default int then yet another interesting thing you can do here is you can also Define some combinations so you can Define one for shoot and fly and you can do equals shoot or fly and Y again this one is going to do a bitwise r operation and it's going to combine both the shoot and the Fly tag and both them inside of this one okay great by the way I should also mention that technically the flags attribute this one is not really required for this you just need need to assign the binary values and all of this works but if we don't assign the flags if we don't do that let's see what this one is going to log and if there you go that one just logs the number five whereas if we have the flags attribute y that one logs the proper readable thing jump and shoot so you don't necessarily need it but adding it makes it very easy to read all right so that's enum Flags it's a great way to store multiple enum values in a single enum field this is really excellent whenever you want to store combinations of values instead of storing just a single one hello and welcome I'm your K mck in this lecture we're going to learn about pre-processor directives this is how we can give some instructions to the component itself which are run during compilation time and not during runtime okay so pre-processed directives with this we can tell the compiler some things the simplest thing we can do is just to find some symbol for that we need to do it at the very top of the file so over here we start with a number sign or a hash sign then we write Define and now we can Define whatever name we want to give to this symbol so something like testing and usually as a convention you write the symbol names in all uppercase so that's it this defines a symbol that's all it takes it doesn't equal to anything it's just a symbol symbols either exist or don't exist so they're not variables that hold any data they are just defined or undefined so here we Define the testing symbol and then anywhere else in our code base we can do an if so for example let's go over here let's do again the number sign then write if and then whatever symbol we want like let's say testing and then to terminate our if we do and if and just like this so now for example we can put some line of code inside of this one yep just like this and now what this is doing is basically it's telling the compiler to either include or not include this line depending on if the testing symbol if that one is defined like this if we run our code if there it is it did say testing but now if we remove this Define up here right away Visual Studio even helps us by gringing this out it means this code is not going to be included in the compilation so right now if we run this and if there this now we do not see that message essentially this code right here this does not exist at all in the final program this if over here here is adding some instructions to the compilation itself and since the symbol is not defined this code will not be included in the final program it literally does not exist one very common use case for this is for debugging so you can add some complex code for supporting debugging doing all kinds of log messages and so on but you might not want that code to be using a performance in the final build so you define a symbol in order to make some kind of debug build and then you remove that Define when you make the funnel build so that the debug code does not run that's one of the main ways that pre-processor directives are used and and just like in pretty much any kind of programming if we have an if we also have an else so we can write else and then do whatever we want so for example over here let's say not testing and right away in the coln we can see so this one is not going to run because testing is not defined whereas this one is going to run and if we go up here and if we Define our testing symbol and yep now this one does run and this one does not run so you can make an if and an else just make sure it always ends with an end if or alternatively we also have l if this is basically else if so L if something let's find a testing two and then let's do one else so here let's put testing two and Y so if we Define testing then it runs this one okay if we don't Define testing then goes into this an and checks does this one exist it does not exist so it runs this one whereas if we Define our testing two if so then yep it runs this one so all this some simple if else logic just like you're used to and right now you might be thinking okay so what exactly is the difference between this and just writing a normal if so just a b testing let's set it to true if testing if so then do something if not don't do it so the difference between this and this the difference is that the normal if this one will be included in the final program this if will only be evaluated at runtime so only when the code is actually running whereas this one for pre-processor ifs these are evaluated during compilation times and whatever does not match the if like this one and this one is simply not included in the final build at all so this code literally does not exist at run time the compiler evaluates ifs in order to figure out if something should be included or not and after the go compiled all of this does nothing all this is replaced by just the things that aren included so this one is a runtime if and this one is a compile time if another important thing about the Define is how it only applies to this one file so here we have this file and I created this brand new one so it's a complete separate file and over here let's find the testing and just do our normal testing just like this see if it does run on this one but now on this one if we try doing the same thing nope here this code will not run will not be included that is because this testing symbol is not defined anywhere in this file it is only defined on this one so defines are on a per file basis but we also have options for project wide defines there are two main ones that are automatically defined by default one of them is called debug and the other one is called release these are the two automatic configurations so up top here we have a drop- down menu this one is for the configurations and by default it always starts with a debug and a release one and doing so these automatically create the finds and applies it to the entire project so here with this set to debug if we have the if debug this one is going to run and same thing on this other file if we Define this as debug Yep this one also runs so this debug Define applies to the entire project like I said one common use case for this is for debugging so rather than defining a debug symbol on every single one of your files instead of that just use the built-in configuration manager to use this debug and then when making the final build you swap it over to release and doing so all of this debug code will no longer be included so setting to release both does that and also creates a new release so yeah this is a super easy way to enable project wi defines and if we go on the cont configuration manager here here we can click on this and we can add some new ones we can add for example testing and now we don't need to define a testing anywhere and we can do if testing any y it does work then over here if we just write if and we press space we see a bunch of autocompletion so we can see a bunch of thees that are created by default for example these over here are related to the net version the net core version and so on so with this you can write some version dependent code for example some code that depends on a specific version like only works on net 6 or greater so you can do this this run that code and then have an else and if the project is not set up without thex or grer you can then fire an error log a message or do something like that now another place where we can create project by defines is in the project properties so over here on the right side let's open up the solution Explorer let's right click on the project important it's over here on the project not on the solution so right click over here go inside properties and then over here let's scroll down under build yep just like this and here we have a bunch of custom symbols that we can add these are related to the configuration builds that we saw so we've got debug release and our testing one and again these are project wide so these will work on all the files so over here like C course just add it and Y there you go it's enabled now over here on any of these I can search for C course and yep it does work and again projectwise so it works on both that one as well as on this one okay great now other defines are the ones inside of unity so here's a script inside that Unity project and over here we can write if and again we do see a whole ton of defaults there's a bunch for all kinds of interesting things and Main one's are really just over here for the versions so you want to write some code that requires 2018.1 or newer any of these you can make it based on build so it has to be on a 10 alone Windows build and so on or actually one that is really important when making tools is this one for the unity editor with this you can either include or not include some code that is specifically related to the unity editor then in unity we can also add project wide defines so let's go into edit and down here onto project settings and over here let's go on the player Tab and let's scroll down under other settings let's keep scrolling down any if here is we've got the script compilation so the scripting defined symbols and if it's over here that you can add whatever symbols you want you can write anything and again these willon be Global defines that apply to every script in your entire Unity project okay so that's defines in if but there are more pre-processor directives when that I use every once in a while is one that is called region you write this and then optionally you give it some kind of name like functions and then at the end you write and region any of this creates a region and importantly over here in Visual Studio this one creates a collapsible menu so we can collapse expand this can become quite useful in large files for organization so for example you could make a region for all of your fields and make end region then make another region for all of your Statics you could have like this and even on a giant file things will look quite manageable another simple one is both warning and error so we just write error some error and if that's it very simply this creates an error so it says some error and if we look down here on the error list yep we have an error so this basically a compilation error we cannot compile like this and as for or when would you use it well you can actually combine this with the if so for example let's go with if so for example if we are not using net 8 if so then spawn some error if not then don't spawn that error so these can be quite useful for validation on your project and related to that we have another one and that other one is the warning and this one really the same thing so this is a warning this one is not an error so it does not stop compilation it's just a warning so down here on the error list if we include warnings yep we see this is a warning and related to that is another very useful one for disabling some warnings for example let's say we we have some code here and we Define some kind of variable but we never initialize we never use it and let's say this was actually intentional right now if you do this we see the little Squig line so this is a warning it is saying the variable is declared but never used and down here on the list yep we do see that same thing if we wanted to disable this warning if so then we can just write pragma warning and then disable and then the actual number for the warning so over here let's Mouse over and see okay so this is warning 0168 so up here disable 0168 and there you go it does disable warning so that one no longer shows up as a warning anywhere so if you have some warnings that you know are not a problem you can use this suppress them or alternatively you can just do just this prma warning disable and this is going to disable every single warning also this does not have to be written just on top of the file you can write this anywhere so for example right before this line we can write this one and then let's say we want to ignore literally just this warning and nothing else and then afterwards we can write pragma warning restore and now if we write a similar error y there it is now this one does show up the warning so it only suppresses the warnings directly within both of these lines all right so that's pre-processed directives in C it's how you can give instructions to the compiler itself which mainly allows you to write conditional logic that will run at compound time instead of at runtime hello and welcome I'm your Cod monkey in this lecture we're going to learn about ref out and in keywords this is how you can output more data from a function than just a return type or how you can pass in something explicitly as a reference instead of a copy okay okay so here's some similar code and we have a basic function it's called get unit State and returns a state that's it pretty basic but now let's say we want to return more data from this function let's say I want to return also the unit health and the unit name so over here I can really just add a comma and then add the health and then add some kind of name this does not work this is not valid code also up here on the return type I can't just add an INT then a string this does not work not valid code functions can really only have a single return type now by the way just quick mention for those of you who already know tbal technically over here you can make this return to tupon I cover tupon another lecture in this Advanced section but for now let's ignore tupon so for now here all we can do is return just a single type so we cannot return multiple pieces of data now one way to solve this problem is to make some kind of class to hold whatever data we want so here we can define a class let's say unit data then inside we have a state then inside we have a health amount and we also have some kind of string name so we can do this and then over here we can return this type and on return we can the brand new one of that set the state equals some kind of state set the health amount and set the name so if this does work and just like this we are indeed returning multiple pieces of data all composed inside of one type so this works this is a perfectly valid option but if we don't want to constantly have to define a brand new separate type to do this if not then there's actually a simpler method over here we can define a parameter for our function like let's say an in health amount and now like this this is a normal parameter so it's an input parameter however we can now add the out key word and just like this this one now turns into an output parameter meaning that over here in this function we can assign this parameter to S and we are going to receive that data over here when we are calling the function so by using over here the out keyword we are defining this parameter as an output so just like the return type that is the standard normal output you have from any function just like you have that one using the out keyword is another way of getting some output from a function inside of this before our return let's set Health amount equals something and if just like this this is our function it has a return type it return state so that's a normal thing and then we're also using this parameter as an output parameter then up here when calling that function we just need to include this parameter however importantly this is an output parameter it is not an input if it was an input we would write some kind of number here that would work that would be an input but this is not an input in the case of an output we Define some kind of variable like int Health amount by the way it doesn't have to have the exact same name you can name it whatever you want so we Define that variable then over here we pass in that variable and importantly we have to write the out keyword and yep just like this so we defin the variable and we didn't give it any value directly to the variable we just defined it and then we pass in that variable using the out keyword onto the function and then the function does whatever it does now by the way if we were not using an output parameter so let's make this one an input parameter so they just say normal parameter and if we do it like this then we have an error here it says use of unassigned local variable if we're using a variable as an input we have to give it some kind of value we have to initialize to something but when it's an output parameter we can indeed pass in then just an uninitialized variable yep like this does work the reason why this works is because this variable is guaranteed to be set inside this function so it doesn't need to have any value preset before calling the function now here after calling the function let's do a consant the right line let's print out what's inside the health amount and let's see so again here we are initializing and not giving it any value passing it into the function then the function is doing some logic and then afterwards let's log out and see and if there it is it does have the value 56 so we Define the variable we pass it in as an output parameter onto the function then inside the function that variable was set and in doing so it actually updated the value outside of it now this actually really interesting right now you might be remembering a previous lecture on value versus reference types and how I said that value types like int int is a value type when you're using value types as parameters in a function these are passed in as a copy and not a reference so normally this would actually receive a copy and modifying this copy would only modify the copy itself and would not actually modify the original data in memory but that's exactly what the out keyword does even though int is a value type by using the out keyword instead of passing in a copy of data to the function instead it passes in a reference even though again the type is actually a valid type so that's how this function can modify that we passed in and if we exit outside we see this variable is actually modifyed whereas if we remove the out keyword if we do it just like this and let's initialize it so it doesn't throw that error so let's like this and see if it says 0 or 56 and like this it does say zero because again without the out keyword this one is just being received by this function as a copy and over here we are just modifying the copy and not actually modifying the original data so that's very important basically by adding the out keyword we are converting this into a reference type and doing so anything we do inside this function will affect the actual original data so the out keyword this one lets you define parameters as output parameters instead of input parameters which means for example over here for this function we can actually make it return void and instead for returning all the data from this function instead we can just do it all through output parameters so let's put an out state state out in health amount and out string for the name then we just need to assign all of those before we exit the function so State let's put it on something and for name let's put it on something and out here this one no longer returns anything so none of that here we just need to write all of our output parameters and by the way here's a quick tip you can do this you can Define the variable and then pass in the variable that works but we can actually shorten this so over here when we Define our output parameter we can Define the variable right here so just like this out state so out in out amount and again the names don't have to be perfectly exact and out string name and now we can print out the state print out the health amount print out the name and let's see and if there is we have our three pieces of data and all of them being returned by just this one function all right awesome now related to this the other keyword we have is the ref keyword so instead of out we write ref and this one is quite similar it also defines this variable as being a reference instead of a copy then up here when calling we also Define refence however one very important difference is when we use ref we need to initialize our data so over here this does not work we need to Define our state initialize it with some kind of value and then we can pass in a ref on that state and yep now it does work so we call it and over here this function receives this one as a reference and inside we can set it to whatever we want and again since it's a reference it's going to modify the actual data so in terms of behavior ref and out are quite similar but they do have some very important differences both of them have very specific rules you have to follow so inside the function an out parameter like this one you have to set it before exiting the function for example here if we don't set the health amount yep we get an error it says the out parameter Health amount must be assigned before the control leaves the current method so if you have something with an out parameter you have to assign it and if you have multiple branches so let's say B set do something so if something else something if we have this and we have a return and let's put the name before those y like this this one does not have an eror because we are indeed assigning Health amount before this return so before this Branch ends but on this one we have an error because we are not assigning it so if we have multiple branches multiple place where the function can terminate if so we need to assign all of our outputs assign all of them before exiting the function so this is why it's called an output parameter whenever the code calls this function it has a guarantee that the output data will be set to something that's why up here we don't have to initialize this one but we can use it afterwards assuming it's been initialized that is because we can inde make that assumption we know for a fact that if we pass it in an output parameter to a function this function has to initialize with something before exiting so afterwards we can assume this variable has been initialized whereas with the ref keyword this one does not need to be sent so over here if I remove the state nope there is no error no problem with this we can receive it as a parameter and either do something with it or do nothing or we can also do something in some branches like for example on this Branch set it to that one and on that one don't do it that's perfectly fine and then up here when it comes to calling that function when passing in a state parameter we have to initialize it if over here we don't initialize it then yep we have this error use of unassigned local variable in order to use something as ref it has to be initialized before passing into the calling function again difference between these two is what happens inside this function for an output you are forced to assign to something inside of this one so you don't have to assign it before but for a ref you don't have to do anything inside of this one you might or might not initialize it so because of that up here you have to make sure to initialize so these are compile rules you have to follow them if you don't initial a ref you get a compiler error and if you don't assign a value to an output you also get an error so you have to always follow these rules and for these two the one that I tend to use most is really just the output the rules for the output parameter are really great they make it very clear that this one is an output parameter for example here we have some Unity code and I'm sure you've already done many Ray casts and with this yep you've already seen an output parameter in action so the ray cast basically sends the ray cast over to the physics system it does whatever it does in order to figure out if this Ray hits something and whatever it hits all that data will be contained inside of this object so this is a great example for how You' normally use out this function over here returns true or false depending on whether it hits anything and then based on that it also returns extra data in this output parameter whereas the ref here this one is used mainly for converting value types into reference types so for example let's say we have some heal function in this one we want to heal some kind of Health amount so we pass in the health amount and need for the heal amount how much we want to increase it by so if we do this and we do for example Health amount plus equals the heal amount if you do this then obviously this is not going to work because again this one is a normal parameter and it's an INT meaning this one is going to bece as a copy so up here we are only healing the copy and not actually healing whatever we want to heal whereas over here if we set this one as ref then even though this one is a valy type it w be passed in as a reference and we can modify data here and it's going to modify the original data also one interesting thing somewhat related to this is the discard keyword for example let's say on this get unit State function let's say on this one the only thing we care about is just a name we don't really care about the health amount or the state if so then instead of defining variables for it we can just use an underscore and Y this right here this is the discard keyword this makes it so that this code is valid so we did not Define any health amount variable this is valid code and simply means that when this code runs it is simply not going to assign the health amount to anything because over here it is never going to be used so this the kind of thing that can help improve readability when we're in this code we make it very clear that we care about the state we care about the name but don't really care about the health amount and yet another related keyword is the in keyword so over here here instead of something being out we Define it as in and this one like them implies makes this an input field so it's kind of similar as to without it so by default this one is going to be an input field but when you add the N keyword now you are passing it in as a reference so again the same thing about value and reference types and by this being marked as in meaning input it means it cannot be modified inside the function so over here we have this error cannot assign it because it is a readon variable now one scenario where you would use this would be in some performance intensive applications you're working with structs for example let's say we have a struct and this is like a huge struct it is something that takes up a ton of data a ton of memory if you have this and then you pass it into some function if you pass it in like this then this function is going to receive a copy of this struct which again if this one has a lot of data and you call this a lot of times you're going to end up with a ton of uses a ton of wasted memory because when you pass it in as normal it is going to create a copy of that data so to help solve that problem to not use as much memory here you can use the in keyword and in doing so no copies created because this one is going to be treated as a reference so this function will receive a reference to the original struct data then inside here you can access it you can read whatever you want from it by being an input it makes sure that the data cannot be modified and it makes it so that it does not receive a copy instead it uses a reference and if you did want to modify then of course over here you would use a ref and it worked just fine all right so that's the ref out and in keywords these are very interesting very useful keywords it's a super easy way to either output more data from a function or to pass in something as a reference instead of a copy hello and welcome I'm your Cod monkey in this lecture we're going to learn about data type boxing this is an interesting feature of C due to the fact that everything is based on the object type okay so let's look at data boxing which by the way the name sounds like it has to do with boxing as in punching people but no it's actually related to putting things inside a box that's boxing this is how you can put some thata inside a box and then get it out data boxing is really just a term for converting something usually a type onto an object type and converting it back so for example let's say we have an INT and we have some kind of whole number and then we can assign it to something of the object type so create an object and assign it to in it and Yep this right here this is data boxing with this we have now placed the I variable we place this data inside a box and the box is named o and it is of type object like I mentioned this is possible because object this class right here this one is the base type for every type in C everything extends from this one and specifically data boxing usually refers to taking a value type kind of like an INT or perhaps a struct anything like that and converting it into a reference type this int is a value type but it is being put inside a box that box is an object type and object is a reference type so in memory I just stores the value directly it's an in which is a value type so it sores it directly on the stack but then o which is an object this one is a reference type so when we assign I to O we are boxing it so O then contains a reference and a reference to the actual place where that is stored although also importantly modifying I will not modify the value inside of O and modifying o will not modify the value inside of I that is because when it converts into a reference type it converts a copy of the original data onto a reference type not the original data and in terms of performance is actually pretty important value types exist on the stack the stack is super fast super performant memory whereas the object by having a reference this one is going to be stored on the Heap which is quite a bit slower now since we can box a Val like this we can also unbox it meaning get value out of the object box and the way we do that is just with a cast so let's go inside of O and cast down into an in and Y just like this super simple it works now of course if we try casting it to the wrong type let's say into Bion let's put here b b yep if we do this we don't get a compiler error that is because object this one technically can be castable down to a ball it just depends on what data is actually inside that object but if we try this we're going to see a runtime error so let's test and if there it is a simple invalid cast exception we cannot cast an object of type in 32 onto a b so basically we need to know what that this object is holding we need to know that so we can use the correct cast and if you want to protect yourself from errors like this you can just put all this inside a TR catch and catch for an invalid cast exception so now as to when you would use boxing we actually already saw a when use case when using events just like this when using the standard event handler so this the C standard to use this delegate type and this one for the signature we can see it as an object Senter and the event RS so vially with this with the center being of type object this means that it can be anything it can be of any type usually when you find fire off this event you fire off whatever class is firing off this event and then later on in the listener usually you know what type is going to be fired so you know which type to cast it to or another potential use case is doing something like for example a list of object you can do this do a brand new list and then on the list you can instantiate it with whatever you want so over here I can put an INT I can put a bullion I can put a string all of this does work because again object is the Baseel upon which everything is extended from so if we make a list of object that list can sort literally anything although this particular use case definitely something that you would only very rarely use using object and data boxing that's a really interesting Quirk of C but in most cases chances are there's a better way to do things so in this case making three separate lists for each data type that would make quite a lot more sense so while you can technically do this you should really only do this as the last possible option all right so that's data boxing it's an interesting Quirk of C due to the fact that everything extends from object because that that means everything is convertiable to and from object just make sure you use it spently only when you absolutely need hello and welcome I'm your Cod Mony in this lecture we're going to learn all about dynamic in C this is a really interesting feature of C that allows us to write code against a type that doesn't actually exist okay so here let's see the dynamic keyword now this is a very special very unique thing we use it kind of like defining a variable so we write Dynamic and then we give it some kind of name let's say just D if there it is with this we have to find the variable D and it's of type Dynamic now what dynamic means is we don't actually know what type this is the type will only be defined at runtime that's very important so this is somewhat similar to VAR so for example if we say VAR V equals something if we do this we also don't specifically Define a type however VAR this one is being evaluated at compile time so when the code is compiling this line it looks at what comes after it and infers the time so when it comes to runtime VAR doesn't actually exist when it comes to runtime VAR is replaced by an INT whereas over here with Dynamic at compile time we still don't know what type this is we're only going to know at runtime when this code actually executes so that also means that within this type we can do anything we want for example let's say this type is a new object something like this and then over here we can call whatever we want so we can call some kind of test function and if there's no error we can access some kind of field and do something and yep no error that is because again right now we have no idea if this is right or wrong maybe when this code actually runs maybe the object that is inside of this one maybe that object does have a test function or maybe it doesn't for example in this this case it will not work here we construct a brand new object of type object and the object type does not have anything called a test function so if we try running this and if there is we have an error a runtime boundary exception it is saying object the type object does not contain definition for test so you can write whatever you want after this you can write whatever function name Field property whatever and you won't get any compile time errors but during runtime it won't check and if it does find some function or some property with that name then it runs it if not then it throws that error this is the really important thing about Dynamic it is how it only runs at run time and not at compound time during compilation it assumes that whatever you did with this Dynamic object whatever you did is correct it is what you wanted to do only in runtime does it actually try doing something and if it can't then throws an error so in order to see a positive result for example every object always has a two string function so if we run this if there you go the program runs no erors everything is fine because again two string does exist within the object but we only saw that during runtime so now with this you might be Wonder wondering where exactly is this useful it does seem a little bit strange I mean right here if this is what we want to do then naturally instead of making this Dynamic we would make it object and that way we can't write something like this we get a compiler error so if you want to do this and obviously using Dynamic doesn't make any sense if you know the object type then just use the object type however where this is particularly useful is when dealing with something like Json data from a web server the data schema might change over time so you might not be able to define the exact type over here for example here we have some simplejson so it's just an object object inside it has an assets and this asset is actually an array and within the array it has three separate objects those objects have a type field a name field and a path field so let's say for example we receive this Json from some web server like for example maybe some modding site and this is the data that we need in order to install our mod in our game here with the Json now the first thing we do is convert it into a dynamic object and one simple way to do that is with the Newton soft Json Library that's the most popular very capable Json library in order to install it let's go over here on the solution Explorer let's right click on the project itself so not on the solution right click on the project and then down here let's go into manage n get packages and up top just go into the browse Tab and then search for Json and there it is the main one newon soft. Json with five billion downloads so let's go ahead and install this one and then with that package installed over here we can use the class J object which exists inside of this namespace Newton soft. json. link we can use this and we can call the parse function this one takes a Json string and returns an object so let's parse our Json and let's put this inside a dynamic object so Dynamic let's call it Json Dynamic and Y just like this and now here we can do whatever we want inside of this object so for example we can go inside of this one we can access the assets and again note how we have no Auto completion because once again Dynamic does not know what type this is going to be so let's make sure to write it properly so assets and assets is going to be an array so let's access the first element on that array and then let's just access the type so it should be this one it should say texture so on this let's put this inside a conso that right line let's print out this and see exactly what it says and if there it is it does say texture all right awesome so you see how here we Define some structured data but we have no class no struct we have no actual type defined that matches up this structure but thanks to Dynamic we were able to load it onto a dynamic object and then we were able to go inside it write all the names for all the properties and get whatever that we want so it works perfectly fine for accessing something but if we access something that does not exist let's say for example then we go on assets instead of assets let's call it asset which does not exist yep of course we get the same error so if we want to test if a dynamic object has a certain functional property for that we have two methods so one option is using reflection so we can go through Json Dynamic we can call get type this is going to return our type for this and then we can call get properties and yep we get an array of property info so the same as with any other type of reflection you can watch your lecture on reflection for more on this method or another alternative is to simply try to access it so for example here let's try reading this so string for the type name we read this and we read inside of asset which does not exist and if this one naturally throws an exception so this is how we can test it we can put this inside a try catch and let's catch for that one catch for a runtime binder exception and if it happens then that property does not exist so you can do this to go one by one throughout your Dynamic type in order to figure out what exists inside of there then Dynamic can also be a return type of a function so here let's do something and return Dynamic some kind of test function and then here we can return whatever we want so we can return an INT we can return a bullan we can return a float all this does work or we can even actually return an anonymous type Yep this is perfectly valid code by the way I cover Anonymous types in another lecture and then up here we can simply call test and grab whatever returns from there then inside that one we can access for example the name let's we console. right line and if there it is and does work perfectly now before we end this lecture let me also give you just one quick tip that is somewhat related it's related to Json here like I said the goal with Dynamic is that you don't know exactly what schema is if you don't know that then use Dynamic but if you do know so if you know your Json is always going to have this format if so then you should create an actal class with all this data but doing that by hand is actually quite tricky you would have to write some kind of class called Json data then you would also have to find another class for something like asset single then on this one you define a string for the type the name and so on so you can write it manually one by one which when you have some complex Json that can actually be quite laborious or alternatively Visual Studio actually has a super simple super helpful answer you just copy your Json the Json that you receive from whatever web server whatever you have just copy it onto the clipboard and then up top go into edit then let's go into paste special and paste Json as classes and if there you go it automatically creates this so it creates our single asset that has a string name path and so on and if these were bullion or a whole number then it would change the type here it would not make it all string and then for our root object so that the main object just has an array of assets so you have just a quick tip when dealing with Json if you don't know the data schema then use Dynamic but if you do know it then use that in order to get the exal type and then work with it with the exal type all right so that's Dynamic it's a really interesting feature of C for working with types where you don't really know what the type is until runtime this is super useful when contacting something like a web server and getting data without knowing the schema beforehand hi there so quick intermission are you enjoying the course are you learning quite a lot I really hope so I hope you're paying attention I hope you're taking it slow and real learning everything also remember to pause at the end of each lecture and dive deeper into each topic I made sure to include the titles for all the frequently last questions all the quizzes and interactive exercises those only show up at the end of each lecture so you can use that to guide yourself or you can pick up the premium version of the course to get all that info in the really nice companion project so if you can't afford it you can use that page to dive deeper into each topic but if you can't afford it the companion project makes it really easy to keep on learning all right so let's keep going hello and welcome I'm your codm in this lecture we're going to learn how to create a custom class indexer this is how you can access some data in your classes using an index kind of like an array or a list okay so here let's learn and build a custom indexer here we have a very simple player stats class this one just stores various stats then up here we are just constructing it super simple and now let's say we want to access these player stats kind of like an array so I want to access for example player stats access it like this on index0 and I want this to give me the strength amount if we try doing it like this then we have an error it is telling us we cannot apply indexing with these square brackets we cannot apply that to this type the player stats so let's build it now the way we do it is actually like a normal property so let's go over here first for our property let's make it public then we can make it return anything in this case let's make it return int and now here's the important part instead of having a name kind of like any other property instead of that we have to name it with a this keyword we do that and then we add the square brackets so basically this property is what is going going to happen when we try to access this specific type using square brackets then inside these square brackets we put our indexer and for the indexer we can use whatever type we want let's go with in just for Simplicity and then name like index yep like this okay so this is our definition and now just like with any other property we can define a get and a set so let's do a get so get open and close the currently braces and then for the get we just need to return something so in this case depending on the index we want to return a different field so let's do a super simple switch do a switch on the index and case we receive zero let's return the strength case we receive one let's return Dex and case we receive two let's return wisdom and in case we receive anything else so on default let's just throw a new index out of range exception okay y just like this we no longer have any compile errors so we Define it kind of like a property with the special key word this then we put our indexer inside we Define the get and we do whatever logic we want so now here yep this one no longer has any error so this one is now perfectly valid so let's try doing a print on this so console let's write line let's write our strength and it should say 12 so let's see and you correct it does say 12 so by this we are accessing our custom player stats type we are accessing it with a custom indexer and everything works great all right awesome so this is working and just like with any property we can make this read only meaning only thein get or if we want we can make it read and write by also implementing a set so let's do the exact same thing so a set just like any other property let's do a switch on our index and case we are on index zero then let's set the strength amount equals the value that this one receives and same thing for all the other ones so case one case two and then the same default and if default let's throw an exception okay yep just like this so now here let's read the player strength and then let's write to it let's write something so let's set it to like 99 and then let's read it again and let's see and if there it is the first one says 12 yep makes sense then we override it and then that one prints out 99 so yep everything works super simple so here we have our custom indexer so we have a custom type and we Define this logic so we can access it using simple square brackets and then we can run whatever logic we want to get whatever values we want as you can see it's really simple to build and it lets us use our custom type kind of like it was a list or an array however down here the index this one doesn't have to be an INT you can use whatever you want so for example we can actually use the stat enum so let's find a stat for a stat then up here same thing just do a different switch and doing K on stat. strength do something and so on yep just like this everything works perfectly fine we just refactored made this one receive a stat instead of an INT so now we go up here and instead of using an INT which by the way the reason why this isn't throwing an error is because every enome is automatically convertible into an INT but over here we want to use a proper player stat so let's use it let's say we're working with strength let's print that one out and on this one same thing print the strength and print this right okay let's see and you same thing it does work so over here we can see how the index are the type over here here can be whatever you want it to be and yet another thing this all supports is multiple indexers so we can add for example an inum and then an in for some kind of index and if this works this is perfectly valid code then you can use both of these in any logic we want inside of any of these so for example this could be really useful if you're accessing some multi-dimensional data to receive an index for the X and Y all right so that's how you make a custom class indexer with this you can make your custom class is much more usable in various scenarios by making it really easy to read or write some data just as if it were a list or an array hello and welcome I'm your Cod Mony in this lecture we're going to learn about attributes this is how you can add some extra information some metadata to your code then you can read that metadata and do whatever you want with it okay so let's learn about attributes now you probably already know exactly what are attributes if you're Unity dev then you've certainly already seen the one that is called serialized field here I'm running this code just on the C console so that's why it's throwing an error this is a Unity specific thing but anyways usually you use this one then use some kind of private field so like a float for a move speed something like this and by using this attribute it means that this field over here this one will be shown in the inspector even though it is marked as private so basically this attribute over here this one is adding extra metad data to something in this case to a field and then the UN inspector is running different logic depending on whether this attribute exists or not so that's really what attributes are they add extra metadata and then you can do something based on that metad data and attributes can also be applied to pretty much anything so we can apply it over here into some kind of field then we can can also apply to a function to a class and so on there's a bunch of built-in attributes like for example one of them is serializable this makes it so that this type becomes irrealizable then if you want you can Mark some methods as obsolete if you do and you Mouse over an object it says that it is deprecated then you can also use DL import to import some external libraries and a bunch more but beyond the default attributes you can also create your own and doing so is quite simple let's say we want to Define an attribute to Mark a bunch of classes as being of a certain type so we want to Mark classes them El as being like a unit and object and so on we want that to be part of the class metadata as opposed to storing some kind of inum field so the way you construct a brand new attribute is first of all you define a class so let's make a new class then you give it a name in this case we want to Mark certain classes as being of a certain object type so let's call this is object type and then for attributes you open the word attribute so attribute so is object type attribute okay great this our class and then we just need to make it extend system. attribute yep so this one is now marked as an attribute then inside we can define a Constructor so is object type we have the Constructor inside if we want we can make it parameterless or we can actually receive some data in this case let's say we want this attribute to receive the object type so up here let's also Define Nim for some kind of object type then we have like unit like object prop and so on and over here let's receive a field for our object type just like this and then we simply store it so up here a private for that one like that and on the Constructor we just set it this one equals this y That's it here is our very simple attribute and like we saw attributes can be applied to almost anything but you can also limit that to certain specific use cases the way we do that is by adding an attribute to the attribute itself so over here let's add one let's add the one that is called attribute usage this one right here and if this one takes a parameter we can see that it is valid on and we can see we have all kinds of possible options so we can make this attribute valid just on assemblies modules classes structs just on Constructors on any kind of method fields and so on so you can really Define where your attribute should be applied to and also note on the values for all of these so that one has a value of one that one has a value of four 32 496 16 and so on note how they are all power of two so if you seen the previous lecture on bitwise operators and bit masks then you already know Yep this is a bit mask each of these occupies a different bit so because that that means we can also do all kinds of combinations so for example for this one let's say we want to apply to classes or structs so we can do class and then we can do the bitwise or again important it is not a Bing or nope just one pipe just a bitwise or so let's make it apply to classes or structs meaning it works on either of those and Y that's really it now to apply to something for example let's make some kind of player class so class some kind of player the player is meant to be a unit so we can apply our attribute we can use is object type note how we don't include the attribute so just the name is object type and then since we added the Constructor over here let's put object type and and let's say this one is a unit and yeah that is it although if we try adding this to for example over here to a function if so then we get this error it is telling us this attribute is not valid on this declaration type it is only valid on class or structs so if just like this we Define a brand new attribute and we attach it to our custom class so now the next step is for doing something with it and the way that we run some logic and check for attributes is actually with reflection now I've already covered reflection detail in a dedicated lecture for example for up here let's try doing that so let's do type of in order to get the typee get the type of our player class then from that one we can call the function we can get all of the custom attributes so get custom attributes and we can either get all of them or we can look for a specific type in this case let's look for just of our custom one so type of for the is object type attribute so let's look for that one and for inheritance doesn't really matter so let's put it on false yep so now this one over here like it says it is going to return an array of object the reason why it's an array of object is because it's going to return potentially multiple attribute types so they have different types so up here an object array for the attribute object array and now you can cycle through this array and test if it is of that type now in this case we already know it is going to have one of this type so we can just grab the one on index zero just for testing let's cast it onto our type so is object type attribute so we have our is object type attribute and then with this object we can grab whatever that we included inside of our attributes so let's do a console. right line let's right line going to that one and let's expose something to get the object type so public object type get the object type and just return the object type okay like this and up here let's call that one and let's see we are looking for thata inside the attribute on the player class so this one should return unit let's see and if there is a player class does indeed have an attribute and that attribute does indeed have data for unit okay awesome all right so those are attributes it is really just metadata that you can apply to a class or a function or literally anything it is really just metadata just extra information so it's really up to you to Define what that data means using this you can do all kinds of analysis or build some hellphone tools do anything that does any processing or any analysis on any of your types hello and welcome I'm your Cod monkey in this lecture we're going to learn about Anonymous types this allows you to essentially create a completely brand new custom type on the fly without having to First declare it okay so here let's learn about Anonymous types let's say for example we want to Define some kind of type that will hold a string for name and in for an ID and one way to achieve that is obviously by defining a normal type so we can do a public class call it player then inside Define a string for some kind of player name and then in for some kind of ID then up here we can construct something of new player and then assign whatever that we want and if that's it this works we Define the type and then we use it this is what you should do if this type is something that is wly used something that you use in a lot of places but what if for example you just need this type you just need to organize this data just a single place what if it's used in just one tiny use case what if you really just want to organize some data if so then for something super quick is instead of defining a normal type like this one instead of that you can just use an anonymous type so let's not Define this and instead for defining an anonymous type first we write the keyword new and then we don't write any type name nothing like that nope instead we just open the currently braces right away so just like a normal object initializer and now here we can Define whatever properties we want with whatever dat we want so for example let's say name equals code monkey and ID equals 1 any just like this here we have our perfectly valid Anonymous type then we can assign it to something we can assign it to some kind of variable but since this type has no name we can't really write a name for the type we can't write int or something like that we can't write a type name because no type name exists what we can do is simply use VAR so VAR and then the name let's say player data equals this and yep here we have our type and if we Mouse over player that we can see yep here Visual Studio telling us that this this is an anonymous type and inside it we have a string for name and an in for an ID we can also do a log on this and see so console let's write line and if there it is name Code Monkey ID equals 1 so here we have constructed our Anonymous type with our data then we can also access it so we can go inside player data and over here yep we can see autocomplete already shows us everything inside of this type so it has the default functions that every single type in C pass so get type hash code equals into string all C objects all C types have these functions and then it has the two specific properties that we justify name and ID now also one very important thing about Anonymous types is they are read only they are immutable types meaning that we can read data so we can access the name we can print this we can read it but we cannot modify it if we try modifying nope we have an error it is telling us that the property name cannot be assigned to it is read only we have this error because this is a property and it's a property with just a get to finded most importantly there are properties they are not fields that is why I named them in this way using Pascal instead of camel case that is because Anonymous types the data that they store they store it inside properties and not Fields so Anonymous types are really meant for readon use cases like for example you just want to organize some data in some nice structure and if your goal is just organization then you probably do want read only so this is perfect if you want something with read and write AIS then you should probably Define a normal type or a tupo which is something somewhat related that we're going to cover in the next lecture so essentially Anonymous types those are all based on inference during compile time you already know how far this compile time feature during compilation the compiler looks at the variable it looks at what VAR is being assigned to and use that set of type so if we do VAR I equals some number if you do this then when the compiler goes to the find the type for I it looks and sees what is being assigned to it this case it's a whole number so it defines I as being an INT and it's really the exact same thing over here for the anonymous types the compiler refers the type for each of these properties based on the value assigned to them so that's is why this one is an nth this one is a string and then the compiler constructs a brand new entire type just to store this data so literally the compiler in the background is storing something like what we had previously so something like a class player data with a public string name and this one is a property with just get no set and a public string ID with again also just to get no set so when we do this the compiler is autogenerating a type just like this one and then it assigns that type that instance of that type assigns it over here to the player data now we can actually see the type for this we can go inside player data and call the get type again the standard function that every single type has let's do console now right line on this one to see and if there it is we can see this one is of type Anonymous type and inside has two parameters it has a string and an INT so this is the type it's an actual type it's a normal type just like any class any struct but it's simply autogenerated doing compilation now this is quite different to what we covered in a previous lecture the one on Dynamic when you make something Dynamic this one is all based on runtime data meaning during compilation it does not run any checks it does not create any types meaning it does not validate any data at compound time so over here we can access name which does exist but we can also access something that does not exist again because Dynamic is only handled at runtime whereas VAR in Anonymous types this is handled during compound time and if so over here we have validation and we know okay this type does not have anything called test so if you ever get confused about Anonymous types do remember this part it helps a lot in understanding how they work if you look at it from the point of view of the compiler the compiler looks at this data and uses that data to infer and create types so for the data inside the an type this can be anything you want as long as the compiler can infer the type so for example you cannot Define here something as null this is not work this is an error it is an error because null can be anything it can be pretty much any type so just like this compiler has no idea what type to make this name but we can for example define a class a normal class and then up here do something like this and yep now this does work another thing we can do is put Anonymous types inside other Anonymous types so over here let's find a type let's called message and we do a new Anonymous type and just say something like message yep so here we have our nice Anonymous type and then inside player data we can also add that so we can add message equals our message Anonymous type and then through this one we can access message and inside we have the actual message also instead of writing message equals message if you defining a new Anonymous type with something that is already stored in a variable you can just write that variable and doing this it will essentially name this property with the exact same name as this variable so if we go inside player data we you can see yep we do have a messager so when using other data to create data inside our Anonymous type we can just pass in the variable that source that data and we don't have to give a specific name then like I said Anonymous types are read only meaning you cannot create and modified so over here player thata set the name equals something nope this does not work this has an error but what we can do is use a WID expression we can use that to create a new type based on another one so for example we can construct a new player data okay great and then we construct a new one so VAR player data 2 and for this one we can base it on the original player data based on that one and then we write the keyword wind and then we can open and close the currently braces and modify some data so let's say name equals Iron Man and Y just like this so basically this is going to start with the data inside of player data and then applies an over right to the name so here if we do a constant out right line on both these so on player data one and player data two if there it is so the first one is Code Monkey ID one with message and the second one has the same ID the same message but a different name however importantly we did not modify the original Anonymous type we did not modify that one that one is still read only we simply construct a brand new one based on a previous one so here we can define an anonymous type with really whatever that we want and then we can also Define an array of anonymous types so to create a new array we do new and then again it's an anonymous array so we don't Define any type instead just open and close the square brackets then open and close the colic braces to initialize our array and now here we can Define our Anonymous types so let's do one let's Sy something like name equals something yep just like this and again we can assign this to a player data array just like this and Y here we have an array an array of anonymous types and it has four elements for with all of this data now one very important thing is the anonymous types here they have to have the exact same format the exact same properties if we add a different property let's say an ID to just one of these if we do then this one does throw an error so it has to have the exact same properties and it's also important that they are in the exact same order so if we have the exact same ones but are in different order like this nope we still have an error again that's because of what I mentioned how the compiler is creating an actual type based on this data and if we have one with a different format then it needs a brand new type and the compiler does not let us create an array using multiple different types by the way actually there's one exception to that if we make this an object array if so then yep now this one does work object is the base class for every C object every C type so if you make an object array you can indeed store literally anything in there I covered something like this in the lecture on on data boxing by doing this we can sort multiple object types and we can see there are multiple object types if we for example put the cursor on it any Visual Studio automatically highlights the exact same properties on the exact same type and note how these three are highlighted but this one is not that is because this one is a complete separate type from these three so when making arrays of anonymous types do make sure they all have the exact same structure in the exact same order so just like this now one use case where Anonymous types are very useful is when doing link queries I already covered Link in tell in a previous lecture essentially link is a way to do operations on collections of data similar to how you do queries on a database so here for example we have our player that array now let's say we just want to get the players just on the red te so for that we can do some simple link to get that query so let's go inside the player data array and this one let's call where to write a condition and for the condition we're going to have a player data and we want to select just ones on the red team so let's go inside player data and select the team equals red okay so we do a query for where the player data team is Ren and then let's just call Select in order to select some elements we going to get the player data and it's over here that we can construct a brand new Anonymous type let's say that after getting the red team players we just want to keep the name we no longer care about the team so here we can construct a brand new Anonymous type and you set the name equals the player data. name or again the same thing that we saw previously literally just put it player data. name and Yep this constructs the anonymous type and over here just make sure this one is in Lambda expression okay so yep so just like this we can put the resulting thing inside of our let's call the red team array and then we can cycle through it so let's go for each VAR red team in the red team array let's do a console. right line go inside the red team and just grab the name okay let's see and if there is Code Monkey and black widow which turn indeed Red Team and Red Team so y here we are cying through some data and for the selection we are constructing a brand new Anonymous type that holds just the data that we want importantly is how this code is actually quite readable and we were able to do this without having to construct a brand different type just to store the player name if we had created a brand new type just for this one use case if so that would cutter our project since this new type would only really be used here just in this one function so with this Anonymous type it works perfectly for this use case without adding any clutter to our project now like I said I said the words on this use case Anonymous types are excellent so you should definitely use them where they make sense but you shouldn't use anonymous types for literally everything the rules they have actually make it perfectly clear how they are meant to be used so first remember how they are read only so you are only meant to use them as a way to organize some data temporarily not something like long-term storage they also cannot have any functions or events just read only properties then since they are meant for small temporary use cases you cannot store the anonymous type in a field you cannot pass it on to a separate function although I should say technically you can actually do that if we make here a public static void test and up here for the parameters we receive something of type object and again object is literally anything any type extends from object so we can call Test passing the player data and this does compile but again this one really completely defeats a purpose because right now we have no concept of what that is inside this object so technically you can do this but you definitely shouldn't all the rules of the anonymous types they are there for reason if you ever find yourself running into the limits of all those rules then that's probably a sign that you should be using a normal type instead Anonymous types are absolutely excellent for exactly what they're meant for small simple data structures for organization that's it for pretty much anything else just to find a normal type now one feature of C that is quite similar to Anonymous types are tups they also allow you to create types with no previous definition they also allow you to organize and structure some data we're actually going to learn about tups in the next lecture as well as a Rough Guide for when to use tups and when to use anonymous types and what exactly are the differences between them all right so here we learned about Anonymous types this is how you can easily organize some data in a proper structure without having to First Define a normal type this can be faster and more readable and the specific rules that you must follow those ensure you only use anonymous types in the way they're actually meant to be used hello and welcome I'm your Cod Mony in this lecture we're going to learn about tupon this is how you can basically create brand new types to organize some data without having to normally Define it okay so let's learn about tupon and here in this lecture I'm actually assuming you've seen the previous lecture on Anonymous types those two are somewhat related they solve similar problems but they also have their differences I'm going to cover those differences as we go through this lecture and also a general conclusion of which one you should choose at the end of this s so just like Anonymous types tupon let us create a type with no name without having to previously Define it and to define a tupon we have multiple ways the simplest one is to use VAR so let's use VAR call it my Tuple and then we do an equals and then we open our parenthesis and inside we put our data so let's say on this one we want to sort the string code monkey and then the int value 56 by the way tupon need to have more than one piece of data otherwise this one is really just a normal field so this just a string and this is a tup Okay so here we have our tupon and right away we can actually do a log on this and see what this creates and if there it is that's our tupon with Code Monkey n56 so we construct a brand new type and that brand new type now holds the two piece of data we can Mouse over the type and see and Y here we do see our ton definition it stores a string and an INT so this one over here we are defining the type and then we can use it so we can go inside my tupal and access all kinds of things and you inside we do see these two item one and item two so item one this one is a string and item two this one is the end and here we can already see a difference between tupon and Anonymous Types on the anonymous types in there we had read only properties so properties we just get whereas this this is a normal field because that that means this one is read and write so we can read this we can read it with something and we can also modify it and it does work although here we also see one thing we see that it is called item one and item two those aren't very descriptive names but thankfully we can actually give them proper names so here when constructing it we can give it a name so we can write for example let's say name then a con and then some kind of value like that and now inside my tupon we still have item one and item two we can still use those two and that is not a compile error so if we use item one yep that one still refers to the string but since we have proper names we can also use those so we can use the name and we can use the value alternatively the name can also be inferred if we pass it in using a named variable so string player name let's call it code monkey and then in for the value with some value and then up here we just use our player name and we use our value and then we can actually access go inside and access yep the player name and the value it is right there so yep all this works great then yet another way of defining tupon is with the types over here in our parentheses instead of using just VAR we can Define string and then int and Y this is our tupon definition and again with no name we can access it through item one item two or of course over here when defining we can also give it names so the player name and the value and then if we go inside yep we do see it then tups can also have a very large number of fields so we can Define let's say a VAR call it Big tupal and inside just open and close the parentheses and we can write as many fields as we want so y there's a giant tupon and if we go inside big tupon and try to access it yep here we see item 1 2 3 all the way up to 20 now one main use case for tupon and actually another big difference between Anonymous types and tupon is how you can actually use these inside functions for example returning some data from a function usually you have just a single return type so you've got some kind of function and over here you define the return type but that can only be one thing just one piece of data although like I've also covered on the ref and out keywords lecture using those you can return more data from a function so that's one option but you can also do that with tubs so here for the return type instead of just one type we can define a tupon so just put it inside parenthesis so just like a string and then NT we can also optionally assign the names to these parameters so like this call it get tupon and now inside we can return and we can return a brand new tupon you have just like this and up here VAR Tuple equals get Tuple and if we go inside inside tup we can access the name and if we do a console do right line on this one y there's a tupon that we receive exactly the one that came from the function so this is one common use case for tupon returning some data grouped inside a tupon or yet another thing tupon can do that Anonymous functions can't is actually being passed onto a function as a parameter so over here on the parameter same thing let's define a bow b and a float F and if there it is this one is perfectly valid code now would really interesting thing about tups is the concept of Destruction this is how you can take your tupon that you have this one again is a type that groups multiple piece of data together into one Anonymous type and then you can essentially deconstruct it into separate variables so here we have our tupon and then we can essentially write the same Syntax for defining a tupon but without a name so the parenthesis let's define our parameters so let's say player name and then for the value and then instead of giving it a name instead of that we just do equals right away and then equals our tupon and doing so with this is doing this is essentially defining these two local variables and then taking pieces from inside this tupal and assigning them to these local variables so this one is now a perfectly normal local variable so we can do a console. right line on this one and we can see yep that one does say Iron Man so basically this line over here this one is going inside the Tuple and inside Tuple it has a name and a value and grabs both those pieces and place them into separate local variables so what we have here is very much the same thing as doing like string player name equals C.N name and in value equals ton. value so basically up here in this one line this one compact syntax in this we are doing the exact same thing as here now if you want to simplify it even further you can actually use VAR so we can raise the types from here and said in the beginning write VAR and if there you go exact same thing VAR means the compiler will infer the types for both these and again these are going to be local variables so whenever you have some kind of tub like some kind of function that returns a ton and you want to split it into multiple local variables and do it then yep that's where tupon construction comes in it is really useful for breaking it apart to do whatever you want with each individual piece then these tups that we've been using these are actually called value tupal so the actual class that we've been using is system. Val tupal it is this one right here actually the one with generics all this syntax is doing this really just a short hand for Value tupon we can actually verify that so let's do a console the right line and let's print out the my ton. get type and if there it is we can see so this tupon is a type system. value tupon and does have a string and does have an end so as you can see this is another difference from those Anonymous types Anonymous types create an actual Anonymous type whereas tupon those are essentially new versions of that tupon generic and C actually has yet another type of tupon this one is called the system. tupon and there's some big differences between these two first is how Val tupal those are val types whereas this one system. tupal this one is a reference type so that has all those normal implications regarding copies and references that we covered in a previous lecture another big difference is how system. twoo this one is immutable meaning it cannot change similar to Anonymous types they are read only whereas value tups these are mutable we can modify them and for valid tupon the data is stored in fields whereas in system. tupon that data is stored in properties again similar to Anonymous types so out of all these three similarly related types which one should you choose and the official C dogs actually has a great page on it so here are the key differences so Anonymous types in terms of the exess modifier they s off is internal Where is the start off as public this has to do with if you are working with multiple assemblies then Anonymous types those are class so again reference types same thing for tups but value T policies are struct value types then with Anonymous types you can make a custom number name so you can name it like player name value and so on same thing with value tup but you cannot do that with tups the construction that really useful thing that one is only available over here on Valley tupal and for expression tree support that's those LM the Expressions that are mainly used in link for that you can use U but not Val tup all right so that's tupon really great way to create a type with some Fields without having to define a normal type they have a bunch of differences related to Anonymous types they are mutable and they are value types so if you need to organize or structure some data this can be really useful to hello and welcome I'm your codm in this lecture we're going to learn how to implement the I disposable interface this allows us to write some code with using statement that will automatically dispose of any resources okay so CP has an interesting built-in interface it is called I dispos this one is implemented automatically by some classes like for example the file class so if we go inside the file class and we open some random file for reading so open then for the path let's say my file. text something like that and for file mode Let's Open just opening so this returns a file stream file stream yep here we are opening our file and what this is doing it's basically it's using up some memory to open and load the file then we can do whatever we want from it like for example let's go inside the file stream and let's read let's read a bunch of bytes so we read a bunch of bytes and then after we do whatever we do with this file object afterwards we need to remember to call dispose so need to go into file stream and call dispose we need to do this in order to clear up the memory used by this class if you forget to call dispose that's a problem you're probably going to end up with a bunch of memory Lees so in order to help you not forget that c has a nice way of doing things so instead of doing this do that then read all the stuff and manually call this poose instead of that we can write over here using then open the parenthesis inside we construct our object and then within the currently braces we do whatever we want with our file stream and that's it then we close basically by using this using statement by doing this this will ensure that this POS is called on this object right as soon as this code block terminates and the reason why using exist again is because file stream this one does implement the ey disposable interface so this can be really useful for any class that requires any kind of cleanup it can be memory or really just resetting some kind of state and if you want your own custom types to also support this format if so then all you need to do is just implement the I disposable interface so for example let's say we have a class for some kind of save system we have something like this and if we try using it in a using block so using save system save system equals a new save system if we try doing this then nope obviously we have an error it's telling us this type being used in a using statement must be convertible into I disposable so let's add that over here let's Implement I disposable okay and this one requires us to implement something it requires us to implement the dispose function and here quite simply write whatever cleanup code we need basically this function will be called automatically when this using Code blog ends we can actually verify it so let's add a console right line let's write a log and say dispose let's see and if there is they call dispose on our save object so now here we can write whatever logic we want like for example on the save system class perhaps on the Constructor so public save system perhaps on this one we would create some kind of file for opening so we've got a private for file stream file stream we would have this then over here on this one we construct a brand new one so we do a new file. open let's open some kind of save file so you could do this open it then we would have I don't know maybe some kind of function to save some data so save player data you would save some kind of player data do something on the file stream then do another one for like save object data and so on so you can do that and all these functions would write this file stream but you need to make sure to close it in order to properly save this file and for doing that we can run it over here on dispose just call the dispose inside of this one so yep now this simple safe system class this one is very well made and very safe from any kind of memory leaks so up here all you need to do is just call Save player data save object data and everything works perfect yep just like this by the way one extra thing which is over here this is post function this one is running some cleanup code but if you forget to call this function if you forget to put it in a using statement or manually call if so there is one phone back you can use you can use the class instructor I I covered that in the intermediate lecture on classes basically to define the structor is kind of like the Constructor except you start just with a TI then the name so save system basically this code over here is going to run whenever this object is deallocated whenever it is garbage collected so here to make sure that everything works just manually called dispose and that's really it super simple implement the interface implement the function and doing so your class can now be used inside the using statement all right so that's high disposable that's how you can use the using Code Block in your own custom types it's a great way to make sure your custom type support any kind of cleanup logic hello and welcome I'm your codm in this lecture we're going to learn how to write custom override operators these allow us to customize Logic on doing various operations with our custom type it allows us to support addition subtraction equals and a bunch more okay so here's some code I've got a public class resource amount it sores a resource type and an in for the amount pretty simple and up here let's say I want to add one resource amount onto another one so let's first make two so resource amount call it resource amount one and let's construct a brand new one let's say for the resource type this one has wood and for the amount this one has something like five okay then let's make another one so let's make resource amount too this one has wood but has 12 now what I want to do is actually add both of them so to find another resource amount for the resource amount total and make resource amount one plus resource amount two so basally I want the final result to have 12 + 5 of wood except nope we cannot do this by default if we Mouse over we can see we do have an error so the operator plus so for doing an addition cannot be applied to things between resource amount and resource amount so that is because our custom type resource amount this one does not support doing addition but we can make it supported so the way we do it is over here on the class we Define new function let's make it public then for this one it needs to be static for the return type let's return the exact same type so also resource amount and then we use the operator keyword and then for the name of the function in this case the name is going to to be the operation so we want to do some addition so let's use a plus sign yep like this and then we have our two elements as parameters so we're going to have a resource amount for resource amount a and another resource amount for resource amount B and Yep this is the syntax now in here we just do whatever custom logic we want in this case we want to add both amounts so let's just return a new object a new resource amount and for the resource type let's just grab the one from inside of a and then for the amount let's grab resource amount a do amount plus resource amount b. amount and yep that's it and just like this up here our error is now gone so let's do a log and verify that it does work so a conso out right line let's print out the resource amount total okay let's see and if there is the math is correct so we've got wood we've got 17 Wood so 5 + 12 that is indeed 17 all right awesome so this is how you can support math operations in your custom types and here of course you can write whatever logic you want like for example we can write some validation so we can test for example if the resource type is the same so grab the resource have this one and check if it is different from the one on B so if these are different resource types then over here perhaps we don't just have them together so perhaps we just return either A or B so that's one valid option or perhaps we simply return null that's also a valid option or perhaps we simply throw a new exception this also works again it's up to you to Define whatever custom logic you want to do with all the operations of your custom type and since we can Implement a plus operation as you might imagine we can Implement all the other ones so we can implement this addition we can can do subtraction we can do multiplication and we can do division all of them works exactly the same so it's a public static function it returns exact same type it has the operator keyword and then has the symbol for the thing and then has an A and A B so this syntax up here that one covers all the math operations but then we also have equals for example up here let's put the amount both exactly the same so both are 5 wood and now let's do we console the right line let's print out resource amount 1 equals resource amount two if we test this if there it is this shows up as false and the reason why it's false is because it's really comparing two references these are two brand new objects so they are completely separate references so that is why this equals is returning false but we can also override this we can do it if for example we want to compare the data inside of it instead of comparing references so we want to compare if the resource type matches and the amount matches if so this one should return true so let's do that let's override over here the equals operator and that works very much exactly the same thing so let's make public static and since this one isn't equals we're going to return a volum then operator double equals and we've got the A and B so resource amount a and another resource amount for resource amount B and know again here we do whatever logic we want so in this case let's compare just data inside the objects so let's return go inside resource amount a and make sure that the type matches so resource amount b. type if these to match and resource amount a. amount equals resource amount b. amount if both those matches then this one does match now here we can still see that we have an error and this is telling us that the operator if we override the equals we also have to override the not equals so let's do that as well and the syntax is pretty much exactly the same and for the symbol is the not equals and for this one is actually quite simple we can literally just use the equals and invert so we can do return resource amount a equals resource amount B so this right here is going to run this logic and if we want the not equals let's just simply invert it so put inside parenthesis and do a knot and if that's it so with this done now up here if we have this one now it should be comparing the amounts inside of it comparing the actual data inside the object instead of comparing just references so this should now return true let's see and if that it is correct it does return true okay great so this working although over here we also see a little squiggle line so we have a warning here it is telling us that we did override the equal sign but we did not override the object. equals function or the object. get hash code function if we override these two we should also override those now this is technically not a requirement as you can see this is not an error it's really just if you override one type of equality you should really override all of it so let's do that one and here we can use Visual Studio to help us Implement these so over here click on this little icon let's override the object. equals and yep it creates this one and let's put the cursor there and override also the object. get hash code okay we have these Su so now let's Implement them and by default here it already writes some pretty nice code so first it does a reference equals meaning it is testing specifically for references between this and the object that it is equating against if they are the exact same reference meaning it's the exact same object let's just return true or if the object if that one is null that means we are comparing something against null so let's make sure to return false and then down here we can write our own custom equals logic in this case we probably first want to test for the type so let's test if the object if that one type is of type resource amount if so then it is the same type and then we can just use this one equals that we override so here we can just return this object equals so we're going to use this operator equals then object we just need to cast this onto a resource amount and if just like this so if the object that we're comparing against is the same type if so we're going to run our equals logic and if not then it's a different type so let's just return false and if that's it this is working perfectly now by the way this one does show warning here it is talking about the nullability of the parameter object this is actually a setting inside of Visual Studio depending on how your project is set up over here the equals will either be object or will be object knowable so in this case the project is set up to this so that is why that showed up but yep all the code is exactly the same so this should now be work working and up here we can test that one so instead of using the double equal sign let's call the equals function so compare that one to that one and it should be true and if there this it is indeed true great and then down here for the get hash code for this one there are several ways of generating a hash code and the simplest way is just with the hash code helper class this one has a function the function is called combine that basically combines a bunch of values and generates an entire hash out of all of them so over here let's use this let's combine both the resource type and the resource amount so yep combine those and just return so this way if we have the exact same resource type and the exact same amount we should get the exact same hash code so here let's do that same thing so let's call get hash code on resource amount one then a space then resource amount two let's also get the hash code of this one and even though these are two separate objects because the thata is exactly the same these should match and if there it is that number is exactly the same okay great now finally since over here we're on the topic of equality there's actually one other interesting interface that we should Implement that one is called IE equatable so this interface like here like it says it is used by generic collection like dictionary list and Link list it is used when testing for equality on methods like contain index of and so on so let's also implement this interface now for this one it is actually quite simple so over here in our type let's Implement I equatable I equatable and then it takes a generic so equatable with resource amount okay and all this just requires us to implement one function over here the equals so let's implement this interface so if here is it's an equal so similar to this one with big difference this one is the generic object equals receives a generic receives an object whereas this one down here receives a resource amount so here we can really just do the exact same thing just do a normal equals since again the proi is set up to use these with nullable let's first compare it against Noble compare the other way down if it is no return false okay but if it is not no then let's just return this equals the other and Y that's really it so now for testing let's go up here let's construct a brand new list so a list of resource amount so resource amount list construct a brand new list let's initialize it with something so let's initialize it with a new resource amount and in this case let's go resource type let's go let's say gold and then for the amount let's say 12 okay that's it so we store this object inside of this list and now we can go inside this list and call contains and again the contains function that one is going to run that logic so you can call contains and construct a brand new resource amount so let's do another one that is exactly the same meaning it has the exact same data but we are constructing a brand new object so this reference does not match whatever reference is stored in there but since we override the I Equitable it is actually going to contain and compare all the data inside of it so if we do this let's we console the right line on this one and see and if there is says true so it does contain that amount even though the object is completely different all right awesome so here we learned how to implement custom override operators we can Define custom Logic for how to do math operations or do equals on any of our custom types so this helps make our custom types behave exactly as we want them to and enables a more straightforward usage by using normal operators as opposed to having to call Custom functions hello and welcome I'm your Cod monkey in this lecture we're going to learn all about link this is a way for you to do queries on your collections in C kind of like the same as you would do with some databases so if you already know something like squal queries then this is actually going to look quite familiar okay so here let's learn all about link if you work with databases or or simply do lots of data queries then this is going to be extremely useful link is really just a collection of functions that works with collections of data importantly is how that collection of data can be almost anything it works on lists it works on arrays it can work on databases XML documents and a bunch more it works on anything that implements I enumerable or I queriable since list and arrays already Implement those let's use a nice list for testing so here I've got a simple player class just as a string for name and a team then I've constructed new list and constructed a bunch of players they got the different names and they're on different teams so right here this is our data now we want to do some kind of query on this data for example we want to grab just the players on the red team now one way to do this is obviously by doing a simple 4 in cycling through this list then construct a brand new list and inside the 4 inch check out inside the list which one has a team equals red and if so add them to the other list so y that would work perfectly fine but we can also do it somewhat more simply by using link first thing is we need to go up top and we need to add the link name space so using an inside system and system. Link yeah that's it this is the namespace that has all of the link functions so now for example down here if we grab the player list and just write a DOT so this right here is the normal list of functions so this is the normal list functions and then over here on the size these are the function extensions most of these are actually link functions this s link is super easy to use it is all based on extensions upon other types so if you have any kind of collection you can always find a lot of these functions now in this case we want to do the simplest thing possible really just query this data for one specific condition we just want to grab the elements where the team is red so over here one of the things we can do is use a wear clause and this one is like name play it's going to select some objects where this condition is true this one takes in a predicate which is really just a fun so just a delegate it takes in a player object as an input and outputs a volum so basically if this output is true we are going to select this player and if it's false then we don't select now in this case we want a very simple delegate so we can just use a very compact L of expression we can Define the player then our little arrow then for the condition in this case we want just player where the team equals red and if that's it super simple this is our delegate so this is going to do our conditional logic and now this function itself this one is going to return an I numerable so if we want we can just do for each directly on this or if we want a more let's say standard type if so we can call something like either two array or two list like that implies it will convert it to either an array or list so let's put this inside a list so let's define a list of player type called the red player list just like this and yep so here we have a list of our red play Players let's actually verify it so let's do for each player player in the red player list second go through all of them and just do a console down right line do a log on our player okay let's test and if there it is it found Cod monkey and black widow both on the red team all right awesome so in this super simple example you can already see how link is quite useful instead of having to do a complex cycle having to make a brand new list to store all of our select elements instead of all that we just have a single line of code and in this we automatically query for all of our elements based on our condition and make our final list so link really is quite easy to use if you want to do tons of data queries then this is going to be much easier as opposed to using tons of four each with tons of conditions now inside we've got the wear but we have all kinds of things so here we can inspect all the operations we can do for example all this one returns a bullion and determines whether all the elements satisfy a certain condition we can do any to check if it contains any elements we can grab just the first element of a sequence we can grab an intersection between two groups of data we can join them we can grab the last and so on so you can see tons and tons of functions to do tons and tons of operations and Link also has one very interesting thing so we can do this we can just run the normal link functions this is the link method syntax but there's actually another way there's the link query syntax now if you know SQL then this is actually going to look quite familiar the query syntax that one returns an inumerable so let's make an inumerable of type player so red player I innumerable okay and now after the equals instead of writing normal code so first grabbing the en list instead of that over here let's write the from keyword and then we give the individual element some name so in this case we're cycling through player so let's call it player so this going to be our local variable that is basically going to cycle through everything and then in and then we select the collection of data where we want to work on so in this case that's going to be our player list and then we can do all kinds of operations so once again we can do a group we can do a join we can order select switch and so on in this case we want a simple condition so let's go with where then our condition let's do the exact same thing so where player. team equals red if the player is on the red team then we want to select it so let's just select this player and yep that's it so this code over here is basally going to do the exact same query that we did up here the only thing missing is really just the tool list but here we have the inumerable and if we want we can then convert this into a list but in terms of the condition itself yep these are doing the exact same thing so this one grabs the list as the input then Cycles through the list and grabs each element and calls each element player then for each one it runs this condition checks if it is true and if so then simply going to select that element so if you're familiar with SQL then you're basically familiar with this here what we have is essentially let's say a select everything from some kind of player list database where the team equals red so this is some basic SQL and right here we have pretty much exact same thing but written in the link query syntax let's just verify it and make sure that it says the exact same thing so let's cycle through this one and if there is same thing it did find both them okay great so yep these are the two methods for working with link we can either use normal functions or we can use the special query syntax now one very important thing about link it's how up here when def find the query this line of code this one isn't actually doing anything this one isn't actually creating a new list or any new elements it isn't actually running any kind of conditional logic this line over here all it does is just Define the query that's it this one does not execute the query the query is only executed down here on the4 each when cycling through all the elements of this inumerable that's where it runs the logic for checking the condition selecting and so on meaning that link has the third execution writing the query this one just defines it it does not execute it right away only later on when actually cying through the collection all later on doesn't actually execute the query now this can be quite important if you're Unlimited in terms of performance you can safely create the query pretty much whatever you want and then you can wait until later in order to actually run the query or if you want you can actually run it across multiple frames so I numeral you can manually get it whenever you want doesn't have to be inside of four each so you could run this over multiple frames which could be helpful if you're cycling through a massive database although Al Another quick note which is up here when using this method when using this one same thing it is not going to execute just to find the query but when we call T list naturally this is indeed going to run the entire query right away and put it inside a list and like I said link works with just about any collection type so here we're working with a list this one would also work with some kind of array it would also work with for example something like XML so for example if we have some kind of list of context if so then we can define a query going inside it inside some kind of record node then inside grab some kind of field check if the field value does match something and select that contact and Yep this is perfectly valid code all right so that's link it's an interesting way to do queries on collections of data in many cases it can actually be simpler than doing normal Cycles by normally going through a list and testing for some conditions the only downside is it can sometimes be expensive in terms of memory and performance but when not doing anything super performance critical in many cases link is a great way to do quick queries on all your data hello and welcome I'm your Cod monkey in this lecture we're going to learn about Wind forms this is how we can build visual applications in Windows if you just want a quick and easy way to make something visual then this is really great you can just drag and drop all kinds of controls like buttons scrome bars labels and so on and everything is pretty easy to use then of course all the cop code that we learn throughout this entire course all of that works on any of these controls okay so in this course we've been mainly using console apps they are great for focusing on the code itself but sometimes you might want to build something a little bit more visual something with a proper UI and for that for making visual applications we have two main options there's Wind forms or Windows forms and WPF or Windows presentation Foundation those are the two main ones and in order to be able to use them we need to First install the modules so open up the visual studio installer and on your Visual Studio installation let's go and modify it then over here under desktop and mobile here we do see net desktop development so we can see build WPF for Windows forms and console applications using C and so on so make sure you select this one and install it in my case I've already installed and now if we open up visual studio and let's create a brand new project any up right here we do see the things that we just added so right away we have the two main ones that I mentioned we've got Wind forms or Windows forms and WPF now for these two Wind forms this one has been around for ages pretty much for as long as net has been around so it is very mature technology whereas WPF this one is newer and has some more advanced Graphics capabilities they also have some very different architectures Wind forms this one is very lightweight and very use while WPF is a bit more complex also by the way I should mention these are not the only two options for example one limitation of Wind forms is by default it only runs on windows so for crossplatform development you have something called net Maui by the way you might somewhere see the name zammer that's what this used to be called but zarine has since turned into net Maui this one is crossplatform so you can write your code and then you can deploy it onto iOS Android Mac OS or Windows and also just another quick mention remember how even though Unity is a game engine that does not mean that it can only build games you absolutely can build normal applications in unity Unity is really just a rendering engine for example I've built a controller module to control my live stream overlay this whole thing this is really made with unity even though it's really just a menu with some buttons I've also previously built a launcher to launch all my games so just remember how you always have that option if you're already familiar with unity and you want to make some non-game app then perhaps using Unity might be a good option but over here when it comes to Wind forms versus WPF Wind forms is really great for Simplicity and WPF is great for more serious visuals but like I said if I'm building something based on visuals I'm just going to use Unity so for making nonunity apps let's learn a little bit about Wind forms Now to create we want to create the template however it is not this one remember the whole thing that we saw in the beginning of the course this one is using NET Framework that is not what we want so up here on let shirt for Windows forms any if we see one without Net Framework and one with it so it's this one over here the one without NET Framework this is going to be the latest net version let's go ahead select this one now let's give it some kind of name so win form C Core something like this and let's click on next then for the framework yep let's go with net8 and yep here it is and right away we actually do see a difference so instead of the code that we saw right away on the console La instead of that now we see a visual window right away and if we try running this if there it is here we have a standard Windows window all right awesome so on this you can build whatever visual program you want on the right side we have over here the toolbox if we go under all the controls yep here they are you can see all the tons of elements that we can add so for example we can add buttons we can add checkboxes we can add a daytime picker we can add some fonts we can add a label for just some text we can have a list view just a panel just a picture and so on so basically all the elements that you're used to in any kind of windows program you cannot find them here let's do something very basic let's just take a button so let's take click and drag the button and drop it over here on our visual window and yep there's our button right here now here we've got the usual controls that you find in pretty much any visual program so we can move it around we can skeleton and so on then also on the right side we do find over here the properties window so this is kind of like the inspector inside of unity here we can customize this object we can modify pretty much anything we can modify the font the color the text and so on so here let's change the text right here instead of saying button one let's say click me and then another very important one is to give it a proper name so instead of button one let's name it the click me button and if there this however if we run this there's our button a normal Windows button we can Mouse over and change the so on and we can click and it does work we can click but nothing happens so let's give it some Behavior with the button selected over here up top we see these two little things so this one over here is for the properties and this one over here is for events so here we can see all kinds of events now Wind forms this is really all based on events so you listen to a bunch of events events like Mouse click and when that happens then you can do some kind of logic so you can hook on to any of these events as you can see there's tons of them the simplest one is we just a click so here you can write some kind of name for a click event function or you can just double click for default and if right away it opens up a view with some code so here we've got our event so as you can see standard event so object and event AR here we have the event where we can write whatever we want now just make sure you don't modify the code up here this is the forms Constructor this what actually runs and sets up the form with all the visuals we can actually inspect over here the initialized component so let's go to the definition to see and up here is all the code all the code for initializing and creating the form you can see here we are constructing a brand new button then it is setting the button location the name size and so on and then down here setting up the form itself setting up the dimensions the size the name text and so on so really what we are doing here in this visual interface all of that is really being converted into code which then actually creates our form okay so here on the form one code when we click let's just fire off a normal Windows message box so for that we go inside the message box class and let's just call the show function and then show something okay yep just like this super simple this will show a message box with some text so let's go ahead and run and okay here's our button and I click and there you go here's our nice message box okay great so this is probably the basics of Wind forms you've got over here visual design you've got your toone box with a bunch of stuff you really just drag controls and add whatever Behavior you want on it now let's just see how to do some logic between events so let's drag something else let's drag a label so this really just some text so there you go just label then here on the label again the properties we can modify with all of this for example we can change the font there you go I just use a random font we can modify the bord sound we can modify the cursor so let's make it with a nice hand cursor for the bord sound let's make it fix 3D just like that for the padding over here let's increase by a bit and that's it as you can see we can modify pretty much anything on our object and up here we also do see some events so again we can add anything that is going to happen whenever we interact with this label for example we can add some Logic on click that works perfectly fine but now let's say we want to click our button and on the button change the text on our label now first let's also just make sure that over here the name has a proper name we're going to modify text dynamically but for the name yep here it is let's call it our text label okay and now the way we access other objects is actually quite easy we can look here on the code where we are initializing our form and we can see okay we have the clickme button and over here we have the text label that we just created and it has all the setup that we just made and as you can see this one is a text label meaning it is just a simple fi that is defined on this class and this class note how this one is a partial class and and the other one where we have our click code this one is also a partial class both have the exact same name meaning both are part of the exact same class so to access other objects we really just use the name because again this class shares the other class which share the same field so in this case we named it our text label so yep here it is there's our field our text label and then inside we can do whatever we want so for example let's change the back color let's call it color do let's say Sandy Brown then text label let's change the four colors so this is the text color let's put it color. white and then for the text label let's modify the text itself and say hello and welcome I'm your code monkey okay yep that's it super simple let's test and here we are and there's our label and by the way as we mous over the cursor actually changes so that's fun now we can click on click me and there's the Box click on okay and if there it is there's our text all right awesome so you can see on a mouse click we easily changed a bunch of properties on a different object now also here we saw one interesting thing which is over here it's like this by default and when we click on this yep there you go go look at this it did not change the text right away that is because this message box over here this one is actually blocking the program execution so the code over here basically stops when it gets to this line and only continues executing the rest of it when we finally dismiss this window basically this is now pausing the mainu Y thread and when we click on okay that resumes and Y continues running the rest of the code so this is where things like asynchronous programming become really important it's so you can do all kinds of logic without blocking the Manu white thread which then is going to update the visual all right so that's the basic of Wind forms this is how you can very easily and quickly build a visual window application it has a very intuitive workflow by just dragging and dropping some controls and of course all the C code that we learned in this course all of that can be used with any of these visual elements so if you want to make a quick simple visual program then win forms can be a great option but also remember how Unity doesn't have to just make games so if you want to make non-game apps if you want something visual you can also just make a simple Unity window hello and welcome I'm your Cod Mony in this lecture we're going to learn about dll import and the extern keyword with this we can interact with external libraries so we're going to see an example of how to interact with the windows API okay so while building our program sometimes we might want to interact with an external DL library in order to call that external code it's actually quite simple as an example we're going to see how to interact with the windows API so first we need to know exactly what we're going to be working with meaning that we need to know the exact function signature so one excellent place to see all the functions inside the windows AP API is this website pinvoke.net this is a great resource that shows all the libraries and all the functions so over here on the left side we can see all the various LLS for example we're going to be working a lot with user 32 or alternatively you can also see all of that in the Microsoft documentation so for a simple test let's do a simple Windows beep so for that we have this function called message beep this one exists inside the user32.dll library and right away on this website we can actually see the correct syntax the function is going to return bull it is called message beep and has a type which is actually we can see down here it's a u as a uent named U type so we just need to write exactly that so over here in our code let's do that so make it public make it static we're going to return Bull and it's called exactly message be like this and inside we have a u in for the U type and Y just like this except of course like this we do see this error it is telling us we must declare body but it also says here that we must declare body because it is not marked as abstract extern or partial and the way we're going to solve this is by using the extern keyword so over here just type in extern just like that and yep the error is gone basically extern this one says to the compiler that this function is external meaning it is not defined anywhere in our program but rather somewhere else and now that it is marked as external now we need to specify exactly where is it so that's where up here we're going to use the dll import attribute and this one exists inside of this namespace system. runtime. interrupt services so you use this one and this one takes in a string for the dll name in this case it's user32.dll yep yep just like this and yep we have no more errors so as you can see it's quite simple to work with external libraries the only important thing is really you just need to make sure to write the function signature exactly so now for testing this we really just call it like a normal function so over here let's just call message bam and let's PR in the default on so just zero okay so let's run this in scene and yep there's our beep there's our sound so we defin an external function and we called it all right awesome so y here everything is working and like I said the function signature this has to be absolutely exact if we give it a different name like just 1 E if we do this like this and call it right now we see no errors but if we try running this y of course we have an error it is saying entry point not found basically did not find any entry point named exactly message beep that is because the proper one has two e so again you can refer to over here on P invoke to see all of the various functions we can call you can see the exact signature this is another example let's use the message box so here we see the signature for this one or again we can just look at the official documentation right here we can see all the parameters over here on this documentation we can also see all the various values the only thing is over here on the official Microsoft this one says our C++ code whereas over here in pinoke we see some proper C code so let's copy exactly this so here we are and let's paste it so same thing so we've got the DL import and just has some extra parameters then this one is again it's static it is extern it returns an INT it is named exactly message box it has a pointer for the window then it has a string for the text another string for the caption and a u for the type so y now let's just call this so over here instead of the beep let's call our message box for the window let's leave it on zero for text let's say hello world for the caption let's say code monkey and for the type let's just go with zero okay so let's try this and if there it is look at that here's our window our title our text and our okay message okay great now let's play with this a little bit more here on the Windows documentation we can see the U type this one is actually a very special thing it says here this parameter can be a combination of flags from the following groups of flags meaning this really inim flags are really just a bit mask we already learned about those in the bitwise operators lecture so here we can just select a bunch of these options for example we can have a board to Tri agore we can have those buttons or cancel try we can have okay okay cancel or yes no so for example let's say we want yes no so here instead of zero let's put yes no just like that but this is a bit mask so let's also use another one so for example over here we can see a bunch of icons so let's go with this one and icon with the question and since this is a bit mask let's make sure to use the or again the bitwise or just one pipe just like this yep so this should say the exact same message but now it should have yes and no buttons and it should have a nice question mark icon so let's says and if there this ex like that question mark yes no absolutely perfect all right awesome now if you want another example you can watch my transparent Unity window tutorial this is exactly what it sounds like I made a Unity window with a transparent background and the way that works is Again by using some external function calls so using that I was able to make the background transparent that's how I'm able to make this live stream overlay of the characters in chat not walking around this whole thing is a transparent Unity window and another thing similar related to this one is called Library import this one is also an attribute this is actually the newer method for doing this it has improved performance and compatibility the only thing is it requires Source generation in order to work but nowadays most projects won't probably support Source generation in order to use it in terms of the code seally mostly the same so in here instead of using DL import we use Library import and since this is based on Source generation instead of using extern we use the keyword partial and if we make this function partial if so then we need to make the entire class partial as well and again make sure we have the exact same signature and this one is telling us that we need to use the Marshall L attribute marshalling is basically the concept of interoperating data between managed and unmanaged data so in this case we just need to add the attribute to define the return type Marshall as unmanaged type. B that is this bowling type make sure that it works and that's really it we have no errors and if we call it call message beep and Y we we still have the beep and we still have our message box so this is another alternate method for also calling external code all right so that's the import extern and how to work with the windows API with this you can actually do some really interesting things like for example you can show a message box or open a file download window you just call those functions you don't have to build those windows from scratch or you can build a transparent window like I did the windows API is really huge so definitely feel free to browse it to see everything it can do hello and welcome I'm your Cod Mony in this lecture we're going to learn how to use asserts this is a very interesting code validation tool and then we're also going to talk about unit testing in general okay so asserts this is an interesting way to make your code much more robust and free from errors it is really just a simple way to test for something this way we can easily validate our code to make sure everything works exactly as expected for example here is a player class and on the Constructor we receive a string for the player name now let's say the name is never ever supposed to be null basically the rest of our code is making the assumption that player name is never null so we want to make sure that rule is enforced basically if that happens then it's an error in the code that should never happen so we do want to know if it does happen and one way to do that is with an assert now they exist inside the debu class this one inside system. Diagnostics inside we can call the assert function and this one takes in a condition we want to make sure this condition is true so in this case let's make sure the player name is not null and if just like this very simple so now up here if we construct a brand new player if we do this and we pass in a valid name so a proper name if there it is Works nothing happens whereas if we pass in with null y there it is our code basically just stopped now importantly this is not an acttion error the program did not crash it is still running instead it really just paused so this assert really just acts like a breakpoint that way we can use our debug Tools in order to figure out exactly what happened and then if we want we can click on continue to continue continue running the rest of the program and if continues terminates and so on so basally asserts help you ensure that certain conditions are true if it is not true the program will pause now one extremely extremely important thing is how asserts are meant for validating code only during development this is not meant to be used during runtime in fact by default this won't actually even run during the final build it has to do with up here for the configuration manager for the various configurations by default this one debug. assert this will only run if you have the debug configuration select now I talked about these configurations a little bit more in the lecture on pre-processor directives so like this if we select debug the assert will run but if we change this to release this is what you would normally do when making the final build of your game if so then even if you're passing the wrong data if you pass in null over here nothing would actually happen if you don't have the debug configuration selected then it's as if this line of code does not exist at all it is completely not included in the compilation so keep that in mind the goal with assert is to ensure your code is behaving exactly as it should be during development and then after you verify that everything works then you make a release bill if you do want to make some verification logic during runtime for example in this case let's say the player name was a user input instead of a hardcode string by programmer if it was a user input then you would not use this if it was user input you would make a simple if so if player name equals null then do something so do remember that point the goal of the Sears is to validate your own code and then you can use regular logic to validate runtime code now if you do want to do asserts in runtime there's actually a way so over here debug. assert like I said this line will not be included in compilation if up here we have release elected but we can use Trace that assert and this one does pretty much the exact same thing but this one is included in release mode in general that's really all asserts are you just have a simple condition you add these in various places in your code to make sure your conditions are always true to make sure the code is ritten correctly and if something goes wrong then you simply know about it so you can fix it now since asserts are about testing your own code and making sure that it behaves as intended let me just briefly talk about code testing or specifically unit testing this is a huge topic so I'm just going to briefly mention a high level overview so when doing unit testing that is when you write a bunch of tests to ensure your code behaves exactly as expected so for example over here for this player class let's assume the player should never be null but then let's also say this one doesn't make that assumption it just soures the player name and then let's have some kind of function so get player name link and this one just goes inside the player name and Returns the link now naturally if over here the player name is null then this one is going to throw an exception so if this was our player class and we wanted to test this then basically just come up with a bunch of tests a bunch of edge Cas where your code could go wrong like for example here Define a player class player set it to n and then call player. getet player Nam H you would put this whole thing in some kind of try catch and if it throws an exception then simply we have the test failed and if not then test succeeded so let's test and Y this one throws a non reference exception and we can see indeed our test failed so this is a basic example of a test you set up everything to run the test and then maybe it succeeds or maybe it fails and if it fails then you know you need to fix something so you do that you would fix that like for example up here you would add if this one equals null if so then set it to an empty string and if now with that change now the test does succeed so this is really a very rough high level overview of unit testing you have a unit meaning some piece of code it can be an entire class or just a function you have that then you write some tests to test whatever you want in this case in what happens if the player has a null name and then we try getting the player name linked so you write all your tests and then if all the tests passed then the code is good and if something fails then basically you have some work to do then in order to write these tests technically you could do it all like this build it all from scratch but there's a bunch of testing Frameworks that can help simplify that process the official one by Microsoft is called Ms test there's a pretty simple guide here on how to start using it so basically you have some kind of code that you want to test then you create some kind of test project you create the class that is going to test a bunch of things for example in test over here that number one should not be primed so it makes some assertions there a bunch of things and instead of having to write all that TR catch code that we just saw it really just works based on adding a bunch of attributes so using a testing framework like this can make it much much easier to make some tests two other very popular testing perimeters for C are one of them is nunit and another one is called xunit so if you want to do unit testing it is probably wise to use a proper testing framework all right so that's asserts it's a way to validate your own code and test your own logic during development this way you make sure your code is running exactly as intended before making the final build and here we also covered a high level overview of unit testing what it is and the various Frameworks you can use hello and welcome I'm your codm in this lecture we're going to learn how to write unsafe C code this lets us disable the safety features of C so we can access raw memory and do anything we want with it okay so let's see how to write unsafe code now this is a very very Advanced topic when working with raw pointers it is extremely easy to mess up you can corrupt some memory and crash your program or you can simply end up opening your program to all kinds of security vulnerabilities so this lecture is very much just a quick introduction to the topic just so you know that it exists I myself am not an expert in unsafe code I've never really used it myself in any serious project I just know that it exists in order to properly use unsafe code you need to know exactly what you're doing if you don't you're going to cause a lot of trouble so always keep that in mind now before we cover and save how exactly C safe well C actually has a ton of safety features mainly to do with memory for example when working with a language like C when you want to create a brand new variable you need to manually allocate some memory for that variable whereas in C that is all handled automatically so if you define an in I equals something this automatically defines the memory for this integer and automatically assigns the value then when reading some memory like for example a string of text you need to know how far along to read you need to read it character by character whereas again in C you just got got a string with something and then you can easily read it and say something to it when working with pointers you can have pointers to inv Val locations in memory whereas in C you simply have no so that and tons more things basically C tries to protect you as much as possible and of course the downside of all of the safety features is naturally it makes the code a little bit slower to do all of these safety checks that is why in super performance intensive applications usually you write it with C or C++ for example while you write game code in unity in C while you do that the engine itself that one is mostly written in C++ the entire engine has an entire pipeline to basically have your C code communicate with the backend C++ and the reason why it's in C++ is exactly to have access to all that raw power without that safety overhead but again the engineers that work on the unity back end they are experts which is why they can work with pointers without causing all kinds of issues now in C in order to write some ends safe code it's actually pretty simple you just use the unsa keyword now you can mark an entire class as being unsaved you can mark an entire function as unsafe or you can simply Define a code block and just this code block is marked as unsafe now inside of this we can write any unsafe code like accessing pointers and allocating some memory although right away you can actually see an error it is saying unsafe code may only appear if compiling with the unsa so we need to first set up the project to actually support writing unsa code by default it does not support it so for that let's go onto the solution Explorer let's right click on the project itself go into properties and over here let's scroll down and over here under build we can see yep here's a checkbox to allow code that use the unsafe keyword to compile so let's enable this and yep the error is gone okay great so now in here we can use pointers for example we can define an in pointer and the way we Define a pointer is for the type int and then a little asterisk so this is an INT pointer let's call like int array pointer and in order to allocate some memory we can use stack aloc then let's allocate memory for an interray with let's say 10 elements and if this is going to manually allocate some memory for an INT array then for example if we want to read the memory location for this we can grab the int array pointer we can cast it down to this type the in pointer and let's just print this to see what this says so let's do a consant out right line let's print out this let's just do a two string to convert this into hexadecimal so two string with format of X okay let's see and if there it is we allocated our pointer our in Array and it ends up being allocated on this exact memory address now let's read the Entre memory address location so let's do a simple four 4 in I equal z i less than 10 I ++ and for this interray pointer we can access this as if it was a normal array so just access that one let's do a console that right line on this one okay let's see and yep it's all in zeros makes sense but now let's see another thing so we are allocating with 10 and over here let's actually read 20 positions and Y look at that this did work usually if you try doing this in non unsafe code in normal code if you did if you try to access this array on something bigger than the index if so then basically normal C code would have a bunch of safety and that safety would stop us from looking beyond the index bounds if we tried we would get an index R of range exception but over here when working with unsafe code we don't get that we can read the memory beyond the array and doing so we're basally going to get gibberish so the first 10 positions those have been initialized as new inter array so those are guaranteed to be initialized zero but these other ones can have really any memory this memory does not belong to the Ray it belongs to something else but as you can see over here the unsafe code does not stop us from accessing it so even though the interray only has a size of 10 we can go all the way up to 20 and even more by the way this is actually the basics for how hacking programs work things like aimbots and wall hacks usually they read memory they're not supposed to and then interpret it in some way like for example display an enemy behind the wall and the pointer itself this one is also like we saw here it's just a position in memory so we can take this one and for example let's increase it let's increase by some amount this basically means we're going to look at a memory location Ford which again is going to let us read a bunch of garbage so up here let's read just 10 Elements which without adding this one we would see everything with zeros but now yep we see a bunch of garbage values so pointers are really just numbers to a location in memory and you can increase that number you can do whatever you want to read a different location in memory now the S is cover here this one defines a pointer and then another symbol the ENT that one defines the memory address so for for example let's make over here a simple struct importantly is that pointers need to work with unmanaged memory again the entire concept of manage memory that's a c thing C automatically manages memory for you but when working with pointers when working with n safe code we are intentionally not using any of that so when working with un safe code we're pretty much limited to just using unmanaged data so that is why over here let's find a struct for some kind of game data then inside let's find some kind of value for some coins and then maybe a bow is game over something like this so now up here let's say we construct a brand new one game data equals just a new game data and now let's define a game data pointer so this is not of type game data it's a game data pointer so game data pointer and for this one let's make this pointer point to this structure right here so for that we use the ment in order to get the actual address and memory of this game data and Y so now we have this pointer and this pointer is going to point to this data and now for example for accessing data inside our struct for that we access our pointer and now normally when working with C you would do do coins something like this but over here we are working with pointers and when working with pointers or when writing some C code to access a sub element of this object for that we do a little arrow and then we access for example the coins and we can set it to something and then same thing for the other one is game over we can set it to something so this is how we can access some members of some data some type we grab the pointer using the location memory and then access those members and do whatever we want to then you can also declare pointers as function AR arguments so for example let's make here a function to raise something to the power of two so let's make a static function just because over here we're in the static thing let's make it void and call it power two and over here let's receive a pointer as a function argument so instead of an INT let's receive an in pointer yep just like this except of course we see an error we can't use pointers we can only use them in unsafe context so let's mark this entire function as unsafe and yep that does work and now we want to modify this value so to modify the value we access the pointer itself and then we're going to set it something so in this case power of two we want to basically put this value to the power of value so let's do times equals just you do the multiplication and then times equals again the value stored inside a value so not value like this this is an error we don't want to get just the pointer itself instead we want to get the data where that pointer points to so let's put a little Sisk to get that one just like that so that inside of here is going to multiply Itself by that one and that will basically do a power of two so then here let's use it let's find some kind of value so in a equal 5 so just a simple integer Now call the function so power two but now we need to pass in a pointer not that itself if over here we use just a yep we have an error it's telling is cannot convert an INT meaning just a simple integer just simple value to in Star meaning an INT pointer so we need to pass in the pointer which means we need to pass in the memory location just like this and then that's it that works now one interesting thing since we are working with pointers meaning that this is going to point point to the original position in memory even though over here we are working with an INT which is a value type and normally if we made this kind of function and over here we receive just a normal int with that if we then multiplied it we would only be modifying the copy itself and not the original data but since over here we are passing the pointer itself if we do a console now right line on this one on a if there it is it says 25 so 5 to the^ 5 so the function this one modify the DAT on variable itself even though it's an INT and the reason is because we're dealing directly with pointers then some objects might move around in memory if you have some kind of managed data like for example just a simple managed array if you have something like this this object might go into different positions in memory so if you want to do something you can use the fix keyword and this one is basically going to generate a pointer so a BTE pointer equals our bytes and you have basically this one over here the fixed this one is going to generate a fixed pointer to this object so whil inside of this fixed code block we can make sure this bite pointer is valid but when outside of it this object might move to a different position in memory okay so that's how you write unsafe code and deal with pointers like I said this is a very very Advanced topic it is very air prone so definitely make sure you know what you're doing unless you're writing some code in some embedded systems or something super hardcore like that chances are you really don't need this C has a ton of really awesome safety features that are meant to protect yourself those are really good they help you write much more error free code much more easily so only disable those one absolutely necessary hello and welcome I'm your Cod monkey in this lecture we're going to learn all about asynchronous programming specifically we're going to learn how to use the async and AWA keywords in C as well as how to use the task type okay so first of all what exactly is asynchronous programming this is how we can have code that executes in a nonlinear sequence basically it's how we can have some code pending for execution while some other code is executing one great example is simply to think about cooking for example let's say we want to cook some breakfast we want some coffee eggs bacon toast and so on now if we do it in a non asynchronous manner meaning if we do it all sequentially one task after another then first we pour some coffee after that's done we heat the pen after that's done we fry some eggs then afterwards do this this this and so on so basically we do each task to completion one by one until the end so in toal with this we would spend maybe 30 minutes but obviously looking at this example you can probably see that this doesn't really make much sense you wouldn't really make your breakfast this way there's no point in standing around doing nothing while the pan is being heated you can start some of these tasks at the same time so the synchronous method of doing a breakfast is like this so we pour some coffee and then we start frying the eggs start frying the bacon and start toasting some bread we start these three tasks at the exact same time then while those tasks are making some kind of progress we continue doing anything else as soon as the task complete we get notified and we can do more things so for example the eggs get done while bacon is still cooking then the bacon is done while the toast is ready so we start putting some jam and so on so basically we start a bunch of tasks and then in the background we wait for them to complete and while we're waiting we can do other tasks so in total by using this this method naturally we would make it quite a bit faster although here let me point out one extremely important detail asynchronous does not mean multi-thread meaning everything all of it still runs just on one thread making something asynchronous just means there's really a pining task and we're waiting for it to complete so the common example in actional code is doing something like contacting a web server we make the request and then we just sit around and wait for that request to return for the server to actually send a response meaning our CPU is not actually doing any extra work on that task it sends out the request and just waits for it to complete so always keep that in mind making our programs the synchronous helps us keep the program nice and smooth without freezing but it does not make it multi-thread okay so now that we've seen the theory behind async programming let's learn the syntax in C so for example let's say we have a function to contact a web server so up here let's make a void contact web server and now here we do something that takes some time so we would make some kind of HTTP requests in order to simulate this let's use the task. delay this function basically Waits a bunch of time it's simply going to delay execution it's not actually going to do any work it just Waits this one takes a milliseconds so let's wait for 3 seconds okay so here we're pretending to contact the web server and wait for a response let's just do un log here so conso let's do a right line and let's print out contacting server so we're contacting and then we contact then let's say by this the server has finished getting a response let's say got response okay just like this and for testing let's run this although this won't actually quite work but let's test any that said just basically ran both them at the exact same same time so it then actually wait any time that's because over here task. delay note how this one says awaitable and returns a task so this is an as synchronous function this task object itself this is what contains the data for the pending action if we want to wait until this action completes then we need to await it so right before it we write the keyword await if just like this this will basically pause the execution right here on this line until this task ends and when task hands then it continues going on to the next line again remember this does not make multi thread when we use a way this Logic for the test delay that one is still going to run on the main thread it is simply just going to wait until it is completed before continue and also here we do see an error this telling is the weight operator can only be used within an async method so in order to make this work we need to mark this function as async yep just like this so now let's test like this except but also didn't quite work we can see it did start contacting the server but the program just end before we got a response so let's make sure we keep our program live we keep it running while we wait so for that we can just do a while true just an infinite Loop just so it keeps running forever then we can forcefully close it so like this if we test okay there it is and contact the server right away and now after 3 seconds yep there you go we've got our response all right awesome so this worked here we have the main asynchronous syntax we Mark our function as async and then inside it when doing some kind of a synchronous work whenever we want to wait for something to complete we use the keyword wait and doing so basically to pause the execution of this function right here and we'll only continue after this task completes however very important L Note how up here that did not pause so down here on this function when we got to this it paused and waited for 3 seconds before it ran this line but up here we ran this line of code right away and we went inside the well true immediately we can actually put a console.log over here just to see exactly and let's see and if there it is it's constantly printing out dashes so that code is running this is very important so we ran this line of code which in turn started this action and then waited for it to complete but whilst waiting for this one the code over here on the main function that one can continued executing so it did not stop on this function it continued going on to this one and continued going on forever so with that we had two branches of code running at the same time except they were not really running at the same time again this is not multi-thread we have just a single thread what we had was essentially two pending tasks so whil working on the main thread our code was constantly testing is this task done just doing a quick check and if not then just continue running the same code as normal and then when this task completed then continue going on to this it finished this function execution and everything else ran the same however also one very important thing which is how up here like we saw the code does not stop so we start counting the web server and then we continue running some logic so if we do this if over here our code does not stop how exactly can we know when our task has been completed so in this example how exactly do we know in here when have we finished conding the server when can we actually get some data back so let's say we get some data so let's just Define a string for the for the server return data so you have this and over here after we contact the server let's get some data back okay so now the the question is how do we know over here in this code inside of this while how do we know that this data has been returned if we just try reading it right away so let's get some in for some kind of data length let's just access the Ser return data and get the length just trying to access that object if we do this naturally it won't work since the data will not be set right away it has to actually wait for the server so if we test this yep obviously we get a non reference exception the data has not yet been returned so this one is still just defaulting to null so essentially we need to know when is this task done executed and for that we can use the same test type ourselves so over here on this function instead of returning void let's make it return a task and up here when calling it let's grab our task and then inside of this one we can access all kinds of things so here we can get a bunch of stuff and the main one is really over here these properties so like is completed this one is going to be true when the task actually completes so let's just check for this one so if the task is completed if so then let's get the data link let's just do a print on that yep so now while the task has not been completed this code is not going to run and when it does complete then we have our Ser return data and now we can run this logic also by the way alternatively we could just call task. weight this one would work but this would block our main thread so our code would not keep executing like this it would stop right here until the task actually completes whereas like this this well is going to constantly running over and over again until the test completes and then it's finally going to run this logic so let's test and up here we are contacting server and after a while we should be able to see yep there you go we've got our link okay great so here we can see that our our function waited until we were finally able to read some data however usually you actually don't want to use this method the method of doing a while true and then waiting for the task completed usually the proper way is ex like we did it down here with the task. delay meaning we should use the await keyword like we saw here that won't pause the execution of R rest of the function until it completes so over here instead of grabbing the test manually and then manually waiting for it to complete instead of that let's just await this function call just like this and then any code after here we can assume this function has been finished which in turn means we do have our return data so we can get rid of these checks we don't need them just like this it won't work so it starts cting the server and only continues running this code after the server has returned a response however again when you use awake we need to mark this as asnc so we have to do it like this but if we try this if we try making main async if there it is we actually have an error and the error is telling us program does not contain a static main method suitable for an entry point so making this function signature async void main this is not valid for a main function however we can definitely make Main into a sync we just need to make sure that for the type instead of void we return task and Y like this it should work so let's test so here we are content the server and we are indeed waiting and after 3 seconds yep we get response we get the four and everything works perfect so y just like this it worked we did not have any errors because again the program stayed on this line it did not continue down until this function was completed then when this one is completed then down here we can make the Assumption this has been set because we do know this task has completed successful so now that we've seen this syntax let's actually see that breakfast example so for example we have our functions to do all kinds of things so let's do a static a sync let's return task say like cook eggs and in here let's we conso that right line in order to say that we are starting cooking our eggs then let's do the same thing let's pretend this is doing something so let's use test. delay just wait for a little bit let's say the eggs take 3 seconds then a Conant out right line saying our eggs are done okay great like this let's make two more so let's make one for cooking bacon and for bacon let's say it takes a bit longer so it takes for second and then finally let's make toast and this one is quite a bit faster than let's say one okay great just like this so we have our breakfast functions and now up here on our main in order to start running those functions let's first actually see the sequential non asynchronous method so let's first cook our eggs but let's await it in order to make sure the eggs fully finished cooking then let's do the same thing cook our bacon and let's also await for it to finish and same thing for make toast let's also wait for it to finish so this is essentially going to be our synchronous method meaning we're going to fully cook the eggs then fully cook the bacon and then fully make the toast so let's see this and okay there it is eggs are starting to cook and after a while eggs are done now starting to cook some bacon and after a while bacon is done starting to make toast and T toast is done so with this we met our breakfast but we also wasted a ton of time we can essentially do all three of these SS at once assuming we have two pans there's really no need to wait for the eggs to finish cooking before we start cooking bacon or before we start making toast so instead of this synchronous code where we fully finish one task before starting another one instead we can start them all at once meaning they all start cooking right away and then we just need to wait for all of them to be completed so instead of waiting it let's grab the task from that so the eggs task and over here task for the bacon task and finally a task for the toast task so we have all three of our tasks and again this code is going to run sequentially right away so we're going to immediately start cooking eggs immediately cook bacon immediately make toast and then after starting all these tasks now we do want to wait for all of them to finish so in order to basically await multiple tasks we can use inside the task class there's a when all function this one takes an array of tasks so let's wait for the X tasks the bacon tasks and the toast tasks and Yep this one is going to be an awaitable call so let's wait on this which means the code is going to pause execution on this line until all three of these tests are done and then down here we have our breakfast done so console let's right line our breakfast is done okay so yep just like this let's test and see any further way we can see cooking eggs bacon and toast all of that starts and toast ends right away eggs done and finally bacon done and we have the full breakfast done all right awesome so we got our breakfast done and we made it much faster because we started all our tasks right away and we just had to wait for them to complete so instead of cooking each task individually instead of that we start them all and then they all finished so this is really how async works you start doing some work and then while waiting you can go do other work now with all this there's really only one thing missing which is how do we return data from one of these functions right now this just returning a task meaning it's actually not returning anything but we can indeed return some data so on the test type we have a generic version for exactly that purpose then over here we use whatever type we want so for the contacting web server let's say we want to get a string back just like this so instead of setting some kind of field let's just return our data and yeah just like this so now here the way that we call this is we call the function but we want to wait for it to complete so let's await it and in order to get results we really just put it over here here so server return data just set it equals to that one and now we can do a console outright line on this one and since we awaited it's going to pause in this one before going into this one so this one should have the correct data received from the web server so let's see and okay it's G the server it's waiting for a little bit and after a while yep got a response and response was indeed data okay great so this is how a synchronous programming Works in C we have tasks we can start those tasks right away and then we can wait for all of them which will essentially pause the code execution till those finish completing and then it continues running the restly code then if we use a weit on some kind of function we also need to mark it as async and when using asnc we can either return vo which usually doesn't make much sense usually you want to return whatever task you are winning so you usually want to return either task or the generic in order to return some more data now like I said many times and let me repeat once more just because something a lot of people get confused about asynchronous programming is not multi-thread all of this code right here all of it is still running just on a single main thread we're actually going to learn all about m multi threading in the next lecture all right so that's a synchronous programming using async await and task and C it's how you can keep your program running and not freeze while waiting for some kind of external result to arrive this is extremely important in order to make sure your application stay nice and responsive hi there so quick intermission are you enjoying the course are you learning quite a lot I really hope so I hope you're paying attention I hope you're taking it slow and really learning everything also remember to pause at the end of each lecture and dive deeper into each topic I made sure to include the titles for all the frequently last questions all the quizzes and interactive exercises those only show up at the end of each lecture so you can use that to guide yourself or you can pick up the premium version of the course to get all that info in the really nice companion project so if you can't afford it you can use that page to dive deeper into each topic but if you can't afford it the companion project makes it really easy to keep on learning all right so let's keep going hello and welcome I'm your Cod monkey in this lecture we're going to learn about multi-threading in C this is how we can create seate worker threads to do all kinds of work on multiple threads at the same time when then correctly we can improve the performance of our program by a massive amount by utilizing all the cores to their Max okay so multi-threading right away let me say this is a huge topic with many potential pitfalls this is very much a definition of an advanced topic writing properly multi-thread code is actually quite difficult it is very very easy to make mistakes so here we're going to learn just the basics but then do make sure you dive deeper into this topic before you start using it in production code so let's let start with the absolute Basics first what exactly is a thread now a thread is really just a unit of execution within a process it does not automatically match up to a core in your CPU we can technically create as many threads as you want but usually you want to create as many threads as a processor has cores and then you want to try to split your workload evenly in order to achieve 100% CPU core usage that way all the cores will be busy doing something instead of doing everything just on a single main thread which is actually how a lot of cod runs and also I should point out what exactly happens if you create too many threads or if you have multiple programs all of them running multi-thread code if you do that then the answer is actually quite simple the CPU will schedule the threads to run on different cores if possible and if not possible then it will simply queue up the threads so if you have 10 cores and you make 20 threads 10 of those will be cued waiting for a core to be available to do some work it won't magically create 20 cores if you make 20 threads it will use all the cor as much as possible but naturally it can't use things that don't exist that as well like I said usually first you check how many cores your CPU has and then then you define the number of threads to create based on that now here in C in order to create a thread to do some work it's actually quite simple now first we Define the function where we want to do some work for example one very common use case in game dab is doing some kind of pathf finding you want the main game logic and all the UI and all of that to be running on the main thread you want that to be super smooth and not freeze while waiting for pathf finding and then you want to take advantage of all the cores of the CPU to make the pathf finding super fast running at the same time so for that let's start off by making a simple function so let's make a static void call it calculate path finding and now here let's just start calculating path finding and to simulate that let's use thread. sleeve and thread like it says here exists inside of this namespace system. threading so thread. sleep this function simply keeps the CPU busy for a certain amount of time let's say for 3 seconds so basically this is going to be simulating as if the CPU is doing some complex pathf finding algorithm let's just do some logs just to see so cons on that right line over here calculating path finding and then over here let's say path finding done okay so this is our function this is the work that we want to do on a separate thread basically we want to be running this logic while the main thread is doing something else so here instead of manually calling the function this would just run it on the main thread so instead of this instead let's create a brand new thread so we do new thread and now inside we pass in the function we want to call or alternatively we can be more explicit we can construct a new thread start and inside use our Cal path finding now this function here takes in a delegate it has to return void and have no parameters so yep exactly the same thing sure we Define here now this is going to construct our thread so let's define this is our worker thread so we have this but just like this it won't actually run just yet all we're doing here is just creating and setting up the thread in order to run logic we need to go inside of this one and call start and yep now this will start executing this function on that second worker thread and then after here we can run some code that is going to run on the main thread so here consant our right line doing some main thread work and then afterwards when we want to do something that depends on whatever result we have in this thread after that we can once again use the thread and call the function join and this will basically block the calling thread meaning the main thread it will block it until this thread that is doing some work until this one terminates so we call join and now down here we can run some code on the main thread whil assuming that the second thread has completed so for example if we were culating some path finding then over here we could assume the path finding has been calulated correctly and we could use it to move some unit or something like that so over here let's just do something like this just print another log and let's test and okay there it is main thread is doing some work we're cating path finding after a while pathf finding done and Main thread done all right awesome so everything does seem to be working however right now you might also be thinking this looks a lot like what we covered in the previous lecture on async programming if we replace what you used with the a weight and async then this would actually look quite similar however like I mentioned in that lecture async programming is not multi-threaded in Asing programming we were waiting for an external service to do some kind of work like contacting a web server all we were doing is really just waiting to get a response back whereas here we are actually doing some work on both threads at once we can verify that by actually printing some more messages so over here on the path finding let's do a four to print a bunch of messages so let's do a thread do sleep and let's do a right line okay so like this and then on the main thread let's do pretty much exact same thing so over here we're going to be doing some kind of main thread work and let's make this one a little bit faster okay so light like this and if there is cating path finding and we can see both the main thread and the pathfinding thread both of those are working at the exact same time again this is the really big difference in Asing programming that we saw in the last lecture there is really just one main thread we simply have some tasks that are waiting to be completed but we don't actually have two threads doing work at the exact same time whereas over here we do we can see the main thread is doing work and the path finding is also doing work at the exact same time whereas if we were just using the main thread without any extra threads then we would basically be doing this so this is fully main thread work with no extra threads and you look at that it's first doing the main thread work doing all that and only then starts doing the pathfind work so right away you can see the massive speed up difference we can get literally double the performance by using multiple cores at once so this here is really the basics of multi-threading it sounds pretty simple you create a b new thread to do some work then you set it to do a bunch of work and then you can do some other work on the main thread so it looks like simple but beyond this super basic example it actually becomes quite complex one very common problem is what is known as a race condition that when two threads are trying to do work on the same data at the same time so let's actually intentionally create a risk condition just to see so up here let's define a static in for some kind of resource amount and then let's make a function that is just going to add a ton of resources so add resources and over here let's just do a giant four let's say by 10,000 something like that something super huge then let's first grab our resource amount then we increase it by one and then we update the resource amount to this temp resource amount okay yep so we're really just going to be increasing the resource amount by 10,000 and now up here let's just create a whole bunch of threads so let's create a thread array for some kind of thread array new thread array of let's say 10 threads then let's go let's second through that array and let's construct a brand new thread so just do a new thread and pass in the add resources function tip here we are going to create all of our threads then let's simply start executing all of them and then let's call join on all of them to make sure they all finish and after this let's print out the resource amount so conso the right line on our resource amount and just print the resource amounts okay so yep just like this super simple we construct 10 threads all of them running this same function and on this function we're going to increase the resource amount by 10,000 so 10 threads increasing by 10,000 means that the final number that we see printed here that final number should be 100,000 so let's see if that's the case let's test and nope right away we don't see that we see 72,000 let's try again and nope now we see 80,000 and now we see 83,000 and now 87,000 and so on so nope we do not get 100,000 and every time we run we actually get a different number so what we have here is what is known as a race condition basically all of these 10 threads all of them are running this function at the same time they're all doing work at the same time on multiple course and they're all working on the same shared variable so what happens is for example thread a starts running this line of code so thread a reads let's say 15 resources and Source them in here but then let's say thread B already ran that line of code so thread B already read 15 then thread B incremented it to 16 and then thread B updated the variable to 16 but then thread a which again has already read the value 15 then thread a is going to increase to 16 and save it again so because of that we essentially lost one resource and it's all because of a RIS condition it is because we had one thread just reading some data while another thread was already doing some operations on it because they're both trying to ex Ute code at slightly different times we end up with different read and write values so that is why the result is always less than 100,000 it is because some resources are going to be lost to race conditions now you can imagine this would be very annoying to the player of the game losing resources for no fault of their own just because of threads all R logic at the same time that's pretty annoying so this is really one of the big problems of multi-thread code it is very easy to end up with race conditions and mess up all your data now to solve this problem we have a very useful tool it's called a unlock and to use it we write the unlock keyword and then within parenthesis we put some kind of object that we want to work as our unlock now importantly this one has to be a reference type so if we use the resource amount we can see an error int is not a reference type so the lock over here has to be a reference type so usually we just create a basic object so let's go up here make a private static make it of type object and just call the resource lock and let's construct it just to a brand new object okay yep we have this lock now importantly is this loog should be shared meaning we should not have have one lock per thread that would kind defeat the purpose we want the lock to be shared between all threads so we Define lock we constructed and down here we use that lock and afterwards we just open and close our code block and yep that's it and just like this let's test and there you go the resource amount the total isn't the correct 100,000 try again and there it is 100,000 once more and yep 100,000 so it always works perfectly basically over here this lock what this is doing is like name implies it is locking this part of the code to a specific thread so for example thread a goes through this line of code and when doing so it essentially registers this object as being locked it is being locked as being actively used by thread a and then thread a starts running all this code and now here's the really important part if thread a is in the middle of executing these lines of codes if then thread B comes along and tries to grab the lock as well if so then thread B cannot get it the lock is already in Ed so thread B has to wait for the lock to become available it cannot run any of this code until that lock is available so basically thread a which has the lock that one does its thing reads updates the value and so on then when thread a exits then it releases the lock and then thread B sees that lock has been released so thread B registers the lock and starts running the logic on that thread and same thing again any other thread cannot go inside this code block until the lock is released so by using the lock we are making sure that only one thread can be running this code at once now naturally this does mean that you lose the benefits of multi-threading all threads are waiting for this loog to become available and only one of them is actually going to do some work so this is yet another reason that makes multi-threading so difficult technically you can avoid all race conditions by just putting everything inside of lock but then of course you also have no benefit so you have to be very clever as to how you use your logs use them as little as possible in order to make your code as parallelized as possible you don't want to overuse them but you definitely want to use them to avoid race conditions basically knowing what parts of your code need to be locked versus unlocked that is definitely a skill you need to learn in order to write proper multi-thread code now another potential issue is something called Deadlocks so this is where two locks are each waiting for the other one to be unlocked so here's an example of that we've got two locks then we Define two threads So This Thread opens up lock one and then inside it tries to open up lock two and then this thread opens up lock two and then tries to open up lock one then we start the threads and then we join them so if we call this let's see what happens let's see if our program ever exits or not let's just return okay let's see and if there it is then our program is basally stuck the issue that is happening is over here thread one this one immediately grabs lock one and then thread two immediately grabs lock two but then they are both waiting for the other lock and that is never going to happen because thread two is stuck waiting for lock one and thread one is stuck waiting for lock two both are waiting for the other one to do something so nothing really happens so when working with multiple locks you also need to take care of this make sure you don't have interlocking locks that in turn means that your program ends up Frozen then another potential issue of multi-threading is simply how it makes your debugging much more difficult usually if you have some kind of bug in your code like for example path finding is cating some wrong path usually you can just follow these St trays figure out exactly what went wrong you can see exactly what call this function where that came from and so on but when you're using multiple threads those will not run in a deterministic fashion they will run at different times depending on whatever else your CPU is doing so you can have bugs that appear randomly every once in a while because the threads ran in one specific order because that it is really difficult to replicate the bug which in turn makes it really difficult to debug yet another potential issue is simply the cost for overhead so making threads this is not free creating a thread has some sort of overhead cost both in creating it and in the CPU managing all the active threads so in some cases multi-threading can actually end up making your code slower the CPU might be so busy trying to keep T of all the threads that it actually loses more time than doing some actual work like I mentioned There's No Limit you can create a th threads on a 10 core CPU but then they're going to run worse than if you just use a main thread because of all the contact switching involved now if you want to just do some simple work without the overhead of creating an entire thread for that c has something called a thread pool basically it has a pool of threads that is automatically maintained by the net runtime it efficiently manages all the threads allowing you to easily reuse them so you can queue up a bunch of work and then thread pool also automatically scales upward and down depending on the man now to use it is quite simple so instead of creating a brand new thread instead of that we just use thread pool and then we just call Q a user work item and then we just cue something this one takes in a weight callback this one essentially a delegate that returns void but has an object so over here let's make some kind of function for that let's call it just do work this one takes an object and over here let's print the thread ID so let's do a right line go inside the thread grab the current thread and grab the manage thread ID and let's say this one's starting then do some work and then finished so thread. sleeve for something okay yep so we're going to do this work on this Rend and out here we can essentially just queue up multiple of these so let's just go for end let's just queue up 10 of these to do this kind of work again we are not creating threads we are just queuing up some work to work on the thread p and then since we don't have a reference to some kind of thread that we can do on join let's just do a while through just to stop our program so we can read our code okay let's see like this and Y there it is we can see a bunch of threads started and a bunch of threads finished so we can see we did a bunch of work on multiple threads at the same time and doing all this without us having to manually create and start some threads so thread pull is really great but it is really meant for small use cases only if you want to do some complex work on a worker thread meaning something that does work in parallel for a long time for that you should probably use a normal thread and manage it yourself but for small things thread pool is super easy to use now here we've been talking about C multi-threading how you can create your own threads do any kind of work but if you want to purly use it you need to make some sort of thread scheduler so something that keeps track of a queue of work to do and then each thread PS something from that Q when idle but if you're working inside of unity you don't actually have to build something like that from scratch in unity you can just use the unity job system this one is really easy to use and unity handles all that complexity for you it automatically creates a bunch of worker threads and then manages them it manages those threads alongside a pull of jobs so then you just create some jobs and add them to the queue and the job system will pull some jobs and do some work this one has a bunch of features it has tons of safety in order to make sure you don't mess up yourself so when working with unity definitely go ahead us job system it is going to be much much easier than manually handling threads yourself you can look at my video on dots to learn how to use it or you can check out my complete. scores which also covers the job system plus ECS the burst compiler and a bunch more all right so that's how you write multi-thread code in C this is an extremely powerful skill to know it is very difficult to do it properly but if you can do it you can literally get 10x performance improvements on the exact same Hardware it has a lot of pitfalls like we mentioned but also a very huge benefit so this one is definitely a very valuable skill although also like I mentioned if you mostly work inside of unity then I recommend you use the unity job system to run that multi thread code the job system has a bunch of features to help you write M thread code whilst also avoiding a lot of those pitones hello and welcome I'm your K Mony and congrats on completing the advanced section we started off with an interesting Advanced topic that I actually only started seriously learning recently it's reflection I had to learn this myself in order to make the exercise for the companion project that's how they all work so now you know how you can dynamically inspect your code and work with it without directly calling functions or reading Fields next we had a simple but interesting lecture it's how we can make function extensions these allow us to extend a type with more functions without having to modify that type itself so this is really useful when you don't have access to that type when you don't have access to the source code then we learn about static Constructors this is kind of like the normal Constructor but they run just once for the entire class after that we learned about the type of keyword this lets us get a system. type object of any type that we have this is very important to use alongside reflection then we saw a lecture on name of this one helps us get a string name of some type this is really useful to help us ensure we don't use strings in our code as much as possible next we'll learn about the size of operator this one lets us get the size of our types so for example we can easily see how an INT is four bytes a short is two bytes and a BTE is just a single BTE so this helps us see how much memory our code won't actually use then we saw a lecture on default it's a simple and very useful operator to get the default value of some type you can get the default value of an INT a b an object and pretty much anything so this is much better than hardcoding some default values after that we saw a lecture on expression bodied members this is a really compact way to write simple short functions there's no need to write all the usual function B plate code it's basically just a Lambda then we saw a lecture on records this is a super simple simple way to create immutable types to organize our data next we'll learn about the null conditional operators this is how we can easily test for null before doing something like firing off an event then we saw a lecture on the null coaling operator this one lets us quickly test against null and return a default value after that we'll learned about the tary conditional operator this is an excellent super compact Syntax for making a simple if you have just a condition with an if and an else very tiny very useful next we'll learned about the main function in a console app and how to pass in command line arguments this was a really important lecture because there are so many interesting programs you can build that don't actually need the UI so just a simple console app that you can control with some command line arguments just that is going to be an excellent option then we saw a lecture on nullable this is how we can make any type support null even valid types like an or bll you can make them nullable to support null so this can sometimes be much better than having to predefine some special value something like minus one then we saw in lecture on span this is is a super efficient way to do Logic on arrays or slices of arrays importantly is how this does not actually create any new data it does not cost any new memory does not create any new objects it's really just basically a pointer meaning this is insanely performant then we saw a lecture on bitwise operators this is how we can work with individual bits of data in this lecture I also taught you the basics of how binary works next we'll learned about enom Flags this is how you can turn your enom into bit masks which then allows you to make some interesting combinations then we saw the lecture on pre-processed directives with this we can give orders to the compiler itself we can Define some symbols and include or not include some code in the compilation next we saw a lecture on the keywords ref out and in these are really useful they help us get more that out of a function than just the single return type and they also let us work with types as references even if they are valid types after that we learned about data boxing this doesn't have anything to do with punching people it's just about putting data inside a box this is an interesting property based on the fact that everything in C extends from object next we'll learn about Dynamic this is a really interesting very Advanced topic with Dynamic we can work with types that don't actually exist so we can define something as Dynamic and call functions or read Fields even if again that type does not exist we can write anything and we get no errors the validation logic only runs at runtime it does not execute at compile time so this is really useful especially when working with data you got from some kind of web server then in lecture on the class indexer with this we can make our own custom type support access through an index just like a list or array we can add whatever logic we want and make it read only or read right next we saw in lecture on attributes this is how we can add metadata to our code that metadata can then represent whatever you want you can then use reflection to analyze it and do something to it after that was an interesting lecture on Anonymous types this is a really quick great way of organizing some data without having to First Define a specific type you just do new open up de caric braces and it will automatically create a generated type related to that was the next lecture on tupon these are somewhat similar they also allow you to organize some data without first defining a type in this lecture I also cover the differences between Anonymous types and tupal next was a lecture on using an eye disposable this is a really interesting code Block in an interface that helps make sure you don't forget any kind of cleanup code after that we'll learn how to create custom overright operators using these we can add support to our own classes to do things like addition or multiplication so we can Define for example the logic of what does it mean to add two custom player classes together then we also Define the logic for comparing two custom types so defining what exactly does it mean to do an equals next we saw a lecture on link with link we can easily do query operations on any collection of data so that can be a list can be an array XML or some kind of database we can query for some conditions to select just a few elements we can sort something do a union do a join and so on so if you're already familiar with SQL then link was probably also quite familiar afterwards we learned about win forms this is how you can make visual C programs you have your toolbox and you just drag and drop components here I also talked about other visual program tools like WPF and net Maui and I also mentioned how Unity itself doesn't have to be used just for making games you can make normal applications with it next was the lecture on dll import Library import how to use extern and work with the windows API this was a great lecture to learn how to interact with external libraries then we saw a lecture on a c and unit testing in general so with this you can validate your own code to make sure everything is behaving exactly as intended next we saw a lecture on writing unsafe C code and working with pointers now this is a very Advanced topic technically if you know what you're doing you can make some very impressive stuff with unsafe code but C has safety for a reason so while we learn the basics of it definitely make sure you use this very wisely then we also learned about a synchronous programming specifically how to use async await and task this is how we can have some code that takes some time like for example contacting a web server and keep waiting for a response without blocking our program this is extremely important in making sure our program feels nice and responsive after that was a super important very Advanced lecture this one was all about multi-threading this is how we can take advantage of all the cores in a CPU and make them all do work at the exact same time when done properly you can get some insane performance improvements pretty much for free but it is also very very easy to make mistakes so this one is very much a definition of an advanced topic where you must know exact what you're doing in this section we'll learned a ton of very interesting very Advanced topics any all of that concluded the advanced portion of this course so congrats again on complete this section and on completing the entire course I hope you took your time and fully learned absolutely everything in this course this course really started from the absolute basics of programming like how code works by line by line and we went slowly little by little until learning some very Advanced topics so I hope that regardless of what was your starting point I hope you learned a lot and you find this course very useful C is really an extremely powerful language and now that you have all this knowledge now you you'll be able to build so many awesome things you can make games you can make console apps you can do electronic stuff websites AI iot automation really just about anything so I really hope you put all this knowledge to good use and of course remember you can always come back to this course at any time you really not expect to memorize all of this personally I Google things all the time myself and now that I actually have this course in my own words anytime that I really need to relearn some syntax I'm just going to come here and listen to my own lectures so if in the future you need to re-remember something about C just go ahead and re-watch that lecture so congrats on completing the entire course I hope you learn a lot and I wish you the best of luck with your future projects hello and welcome I'm your codm all right so congrats on watching through this entire free video I hope you learned a ton I really hope you took your time and really focus on learning all the topics in this invent section this one covered quite a lot of very interesting topics and if you watch this video I hope you also watch and learn everything from the previous two videos the one the beginner and the intered sections if you watch all three and you took your time to actually truly learn all of this if so then now you have an excellent amount of C knowledge if you want to try out that knowledge and put it into practice if so then you can check out the premium version of this course the companion project includes the interactive exercise along with frequently asked questions and quizzes for every lecture in the course remember you only actually learn by doing so make sure you put what you learn into practice now to continue on your Learning Journey if you want a course on making a specific game you can watch my free catch and Chaos course in there we build a really nice game from start to finish there's also a second video on adding multiplayer onto it for something more intermediate check out my turnbas strategy course this one is a really nice turn-based strategy game it's got lots of actions enemies very cool or if you're an advanced user if so then check out my un dots course un dos is an extremely Advanced but very powerful tool set it can literally help you write code that runs 100x faster or in general for Unity check out my ultimate unity overw course that one covers over 70 tools and features that un has all right so thanks for watching I hope you learned a ton best of luck in your Learning Journey and I'll see you next time