Primary Constructors in .NET 8

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
one of the new changes to the C language is the primary Constructor now there's been some confusion around this topic about why it exists what purpose it serves and how you'd use it for various scenarios in this video we're going to look at what primary Constructors do and how we can use them safely and effectively now before we dive in I want to share a couple things with you first if you're interested in improving your C skills be sure to subscribe to this Channel with over 500 C videos and Counting is the perfect place to learn and grow your skills second if you're looking for free C resources head on over to IM timc cory.com and check out the resources tab there you'll find my podcast my C projects page and much more and finally if you ready to dive deeper into a specific topic I have a variety of courses that can help not only will we receive a worldclass education but you'll also help me fund the free content so that everyone have a great education in C not just those those who can afford it so let's Dive Right into what primary Constructors are and how they work now to do this what we're going to do is create just a simple console project we don't need anything complex here we're just going to say uh primary Constructor uh Constructors and I'll call it primary Constructors demo we'll hit next and net 8 Okay so so once this gets created what we're going to do is create a few different examples with before and afters so I'm going to create a a new file we're going to call this uh simple which is a simple demo um these we're not going to be necessarily running this application as much as demonstrating what these things do so the difference here is that this isn't about creating a application that does something but rather it shows off what we're learning learning here okay let's clean it up a little bit um and make this a public we're going call this simple before now normally I I name the the class the same as the the file name but we're going to have a simple after as well this is the before and after before the primary Constructor and after the primary Constructor so one example of a Constructor might be that we're capturing the the first and last name so we're going to say uh CTR for Constructor and in here we're going to say let's capture string first name and string last name now let's say we're not going to create properties for these we're just going to create them as as Fields so we're GNA say Okay I want to control dot here to create aign a field for first name and we'll do the same thing for last name okay and notice it's already asking for primary Constructor options but let's ignore that for a minute now maybe don't want these read only so we'll just mark them as as private okay so they're private strings and we can come down you know into a method and actually use them so you can say something like um private or public uh void test like so and ignore the suggestions from uh GitHub copilot it's not known what I want to do but we could just say you know actually let's return a string and let's just say full name this is probably a property but we'll call it a method and we're going to say return and we'll say first name plus last name okay that would be how we work with these title values where we're passing in values to our Constructor meaning we're we're saying when you instantiate a CL class you have to give me a first name and last name and when you do I'm going to store that somewhere so I can access that value somewhere else okay so that's what we had from C 11 before this is you know pre.net 8 release pre C2 okay so what does it look like now with our primary Constructor we can say public class simple after okay so instead of having a Constructor and passing in parameters we're just going to copy this right here and put it down here and we're done with all of this okay in fact we can copy this um string full name and there's no underscores but there we go this definition right here is the functional equivalent of this definition it's a lot more compact but what's happening well what's happening is just like with records records have have this structure right here right so if we were to create a um a public record uh simple record we could say whoops wrong paste um we could do the same thing only we actually name them something else we'd say string first name String last name like that okay that's that's a record definition and it's similar what we're doing here but it's not the same notice we're using capital F and capital L because in a record these become properties but in the uh and we can commment this out now um in this the uh primary Constructor example here these do not become properties they become they become parameters that are passed into the constru structor so these parameters though are available throughout the entire scope of the class so first name is available in the full name method same with last name it's available in the full name method so what we're doing is we're saying these are available internally and we don't have to bring them into a Constructor like this because remember if we bring them in here they only last for the scope of the Constructor when the Constructor is closed you can't access uncore last name anymore that doesn't work because this last name uh parameter only lasts for the scope of the Constructor well with primary Constructors like this they last for the entire scope of the class they're available everywhere that you want to access them if you want to set it up that way we're going to talk about how to change that in a little bit but this also means that these are mutable or changeable meaning I could set the last name value I could say last name equals test and that would work which also means if anywhere else in this class relied on that last name value well it's now been updated if You' call this method first so just note that they are changeable that's why up here I kind of reflected that by saying private string first name because these are also now changeable um whoops I clicked on that link um so these are also changeable because they're not readon and we're going to talk about how to make it read only because you cannot declare them right now you cannot declare these as read only now there's there's talk about in the next version of C uh C 13 which would come out next year so it be come out in uh November of 2024 with net 9 um there's talk about maybe making these read only but how do they read only if they um they read only you know throughout the entire life or how does that work they're gonna figure that out okay but for right now there is no ability to mark them as readon meaning when they come in they'll be read right so that's the primary Constructor and its job is to say hey you know what we don't need to do all of this setup work when we can just declare and use them okay so this is not a solution for every problem and if you try and approach every single class by using a primary Constructor you'll probably create some problems but there are instances where this makes sense now I do want to point out that if you use a primary con Constructor like we're doing right here if you decide hey I want to have a another uh Constructor maybe I want to have an empty Constructor like this guess what right now it doesn't work well why doesn't it work well we we must have an initializer for our primary Constructor and how we do that well we say this and pass in a first name and last name value maybe we pass in two empty strings that would work so but every Constructor has to call the primary Constructor now so it's no longer we have different options we always have to call the primary Constructor if we're using one so if we have an empty Constructor like so then it has to call the primary Constructor and pass in values for first and last name and you could put in you know uh test and value like you could put in whatever values you want but you have to initialize these two variables because these variables will live throughout the entire lifespan of this class and so you're putting something in to start them out now it might make sense to make them empty strings or something like that so you can have multiple Constructors if you want but you always have to pass in the OR call to the primary Constructor using the this keyword and calling those parameters now the question is going to come up where do these live like are they just private Fields well yes and no they're they're kind of private Fields but not really private Fields meaning you can access them anywhere in any method but if you were to try and say thist first name you wouldn't find it it would error out and say no that that's not that's not available so it's it's still a parameter but yet it's kind of a private field it's a little bit of magic they're doing behind the scenes but just kind of know that it's you know Microsoft is taking care of for us The NET Framework is taken care of for us um about where those are but they do kind of exist now what if you wanted to make them a a private field with all the um the available to a private field well you could do that you could say private string and let's get the same exact name first name so PRI string first name equals first name okay so now if you notice there is a um there's a slight shift here but this first name is no longer being accessed when we say first name in any the methods it's going to be assigned to this field and now this field is going to be accessed so now we can say things like this. first name and that's available because it now is a true field we've we've kind of elevated to the field status now let's look at another example just to kind of bring out some more of what this means a little bit so let's create a a new file since this one's kind of clogged up now we'll call this one props for properties and we going to again clean this file up so that it's a little more usable props before and we're gonna say whoops my goodness um prop string first name and last name I'm going to take the sets off so it only has Getters now you can still set a value through a Constructor so you can say Constructor and we'll say string first name String last name and I don't if you know this but you can also do control dot here and say initialize property first name and then control dot here and say initialize property last name well there we go that's we've got this ability to uh initialize our properties this is before this is we're not using primary Constructors here so how can make this a little uh better well we can do our after so public class props after and we're going to say this is the same signature line and that's it okay now we can create those properties though so we can create these same properties but instead of having to have a Constructor to assign the values we can just say equals first name and equals last name so they're initialized with the Constructor so just like up here where we're initializing this G only property with an initial value from The Constructor we're doing the same exact thing down here by using the primary Constructor so that allows us to start things up properly for our class and in much cleaner format instead of you know lines 3 through 13 what 10 lines we have lines 15 through 19 so we got you know five lines of of text or four lines of text so a lot cleaner but I also want to point something else out so let's just say I created a a public void uh test method again just as a demonstration and I want to say console right line and I'm gonna access the first name value so I to say first name and notice it doesn't show up an intellisense now first name the property does but not first name the uh parameter being passed into the Constructor so what if I just overr it anyways and just did it and that works but now notice we have a green squiggly under our first name up here and it says parameter string first name is captured into the state of the enclosing type and its Valu is also used to initialize a Field property or event so what is this error message and why does it matter well what it's saying is hey you you captured the value right here and put it into this property but then down here you're not using that property you're using the again the parameter and maybe that's not what you intend to do and it probably shouldn't be if you're already capturing it somewhere else you should use that other place for all of your usage so so in this case we should probably be using the the first name property in this test method and then life is good so this allows us to instantiate our our um our Pro our our Properties or you know set them up when they first get instantiated with the class and it allows us to then kind of give some warnings when we try to use again this mutable value instead of maybe what we were intending to use which was is the value we or the um the property we assigned it to so this again is how you could use your um Constructor parameters I mean sorry your primary Constructor to um to instantiate or set up your your properties and then make sure that you're using that throughout the rest of your code now there's one we haven't gotten to yet and that's read only I mean this this technically makes it readon when you put into a property like this if we use that property everywhere but we don't we don't have to we can we can use we can say first name and just Escape out and say test and that would work um and that could cause some messy issues but you know we we don't want to do that so what how you make this thing read only well there's some ways of doing that and what we're going to do is look at that next we look at setting up a dependency injection config duration so let's call this from di for from dependency injection again we'll clean up here and we'll make this public and we're gonna say before and here we're going to do is whoops boy the um it's really messing with me with the U GitHub co-pilot might want to turn that off in fact I'm going to do that so um um let's disable okay and it's still going to be intell code but it'll be a a little bit less than having copot on as well so what we're going to do now is we're going to create a a prop and we're whoops not a prop a Constructor there we go Constructor and we're going to say we want to bring in ey logger I loger type from di before and we're call this logger now we don't have logger installed in a um a class or a console application how you control dot here and I want to install a package Microsoft extensions. log. abstractions I'll do that and then I will do control dot again to add that using directive and there we go now we have logger and with the logger I'm going to do the control dot to create a set of field called logger now as you note this is read only and that's a good thing because I don't want my values coming from depan injection to read right I don't want to mark them that way first of all it's more efficient to make them read only but also it's the correct thing I do because the fact that if I accidentally overwrote that value that could cause a significant problem if it's say a shared um a shared value so I definitely want Market as read only well how do you do that with our primary Constructor so public class from di after and we're gonna say that I want to have this same logger only I'll change the from di after um on the same kind of logger but how I mark this as read only because right now I could say public void test and say logger equals null and that would work okay now it's saying here yeah you're it's not null here trying to assign a null value um but it would work now I don't want that so what I want to do is Mark this as read only like I said before there is not a way to mark them as read only in the primary Constructor but that does not mean that you can't mark it as read only anywhere in fact we can do is say private readon I logger of type from di after and call it logger equals logger and notice I gave it the same name so by giv the same name I'm actually saying no whenever you use it anytime in this class you're going to use the private read only value notice down here it's a readon ey logger and it's saying a read only field cannot be assigned to so you can't do this anymore we've stopped you from being able to modify this loger now we could have called this underscore logger like we would would do up here but then we could still technically do this because we're assigning it to the uh parameter not to the newly created read only field so by nameing the same thing we're able to enforce that this is in fact readon so now just to kind of clear things up a little bit our class definition is like this if we were doing um depan the injection versus like this really I mean you know we can ignore this down here so let's just get rid of it temporarily so this is before this is after and the same exact thing okay we've got the same exact setup now that allows us to make things a little more clean and compact the only thing you have to remember again is if we have another Constructor we have to call this primary Constructor but if you're using dependency injection youa don't have a a different Constructor that doesn't take in the dependency injection stuff so you're still good so that's how you'd use dependency injection and also ensure that you're marking things as read only and just again to make things a little bit easier if we were to do control dot on this logger there is create assign a field now mine again starts with logger and I just want to make sure that still it's it's logger um instead of underscore logger but that allows us to use these tools very quickly and easily because we have the those quick actions and refactoring so yes there's going a little bit of a change in how we do things with dependency injection if you're used to using the underscore for your private readon fields and you know having this this change from underscore logger to logger um or logger toore logger but now I recommend just giv the same name that way you force people to use the read only version as opposed to the read WR version now this doesn't just work for what we have here if we go back to our simple demo I'm going to make some changes to the simple demo but I could say you know what this private string first name equals first name which we again overwrote um I can make this private readon and now first name is readon and again notice down here it's using the readon string version not the uh the parameters being passed in so so this allows us to Mark things as read only if you want and allows us to say hey you know what I want to uh instant or initialize some properties and yet if we want to go really simple we can just have this and just start using them so if you don't mind the fact that they're changeable or mutable values we can just say public class the name of the class and whatever uh values you want to bring in initially just again note that those values always have to be brought in then okay so if you have all Constructors you have to start from the um from you have the primary Constructor unless you then you know override it with passing in you know dummy values or sample values or something like that so that is primary Constructors and how they work I think that you know this does clean up the code quite a bit and I think that there's a a lot of you know smart choices in here in how they work and I'll probably using these more throughout my code however I don't think that you have to use primary Constructors first of all they're not for everything for instance there are times when you on a class that doesn't have a a Constructor that has parameters that takes in for example all of your models where you're past you know it's it's a data model you probably don't want to have a Constructor that has no parameter or has some parameters you might want to have an empty Constructor in which case you wouldn't want to have a primary Constructor also it does not hurt anything for example our dependency injection here this syntax is just fine it works the same way it's just a matter of do you want to do this more compact syntax are you okay with it and are you okay with how it's set up so what I wouldn't do is I wouldn't go around to all your existing classes and just change them over because you might be introducing new problems or new issues so instead what I do is i' you know moving forward yeah go ahead and use primary Constructors think about it and if you're already working in a class maybe you do switch it over to the primary Constructor if it's cleaner if it you know makes things more readable remember codes meant to be read by humans so if it makes it more readable great and use it and if it doesn't make it more readable then don't do it you know if it makes it more complex on the Constructor side of things then don't don't bother with it just because it's a new thing to do okay and again we talk about the idea of having you know multiple Constructors and where was that Constructor a simple one you know having multiple Constructors and having to you know use this syntax it might not work if you are you know heavy on overloading Constructors so just you know think it through make sure that it makes sense for your scenario but I think this is a great addition to language as another option people get kind of caught up in well there you know the right way of doing things I don't think there's is a right and a wrong way here I think what it is is another option for us and options are great because they allow us to make choices and allow us to do what's best for our specific situation and that's what this allowing us to do is make a choice that works a little better for our some situations just like you know the record is an amazing tool for certain circumstances and when it works it's awesome and I would not change it for anything I love this way the record syntax works and how it how it's designed and really that's where we have we have now with the class it's very similar to the record structure only it's somewhat simplified doing less things but at the same time it was more complex to implement I think um so you know we've got this now in classes we can use this to simplify how we do things uh for the creation of our our classes just make sure that you understand why you're doing it and what it does okay so that is the primary Constructor in C2 now if you want the code for this it's there's a link down the description thanks for watching as always I am Tim Cory [Music] [Applause] [Music]
Info
Channel: IAmTimCorey
Views: 20,212
Rating: undefined out of 5
Keywords: .net, C#, Visual Studio, code, programming, tutorial, training, how to, tim corey, C# course, C# training, C# tutorial, .net core, vs2022, .net 6
Id: y3--fmLLmQA
Channel Id: undefined
Length: 28min 42sec (1722 seconds)
Published: Mon Dec 04 2023
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.