Intro to Records in C# 9 - How To Use Records And When To Use Them

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
c sharp ni is out and with it comes a new and somewhat confusing feature records in this video we're going to look at what records are how to use them effectively and then we'll talk about when they would be useful and just as importantly when you should not use them now if this is your first video you've watched of mine my name is tim corey and it's my goal to make learning c-sharp easier i provide videos twice a week here on youtube to help you grow as a developer i also have a full set of training courses on iamtimcory.com i encourage you to check out all the resources i have to offer in this video as with most of my videos i'm going to create some source code if you'd like a copy of my source code use the link in the description also in the description it's a link to sign up for my mailing list next week i'll be rolling out my annual black friday sale make sure you're on the mailing list so you get all the details now let's get started looking at records i'm in visual studio 2019 this is a 16.8.1 which is the latest general release version it's not the um the pre-release or anything like that it's the latest general release let's create a new project or create a simple class or console application so console.net core and we'll call this our record demo and record demo app and once it's created i'm not going to create a top level class here i could but what i want to do is because this is a demo and i want to show you more than one thing on a screen at a time i'm going to cheat a little bit and by that i mean i'm going to put my record creation right down here starting on line 13 instead of putting them in their own classes i would definitely recommend you create your their own class files that is of their own class files for um the records but because i want to show you on screen both the same time this just makes it a lot cleaner so let's start off with a very basic straightforward pretty common declaration of a record we can then see and then talk about and compare with what that might look like if it's a class so public record it's going to yell at you and say no i don't have this if you mouse over it says that record does not exist in the current context that's because we're in by default.net core 3.1 if you right click on your your project and go to properties you'll see target framework of net core 3.1 the cool thing is you just select net 5.0 and save oops not open save and you're good to go now what that does behind the scenes just so you know is in the um the cs proj file if you either right click on it you click on it singly it'll go here or you can right click and say um edit project file but either way this is the project file very very simple which is awesome and the target framework right here is net 5.0 that's the the big change that we had for you it said before i believe net core 3.1 and now it says net 5.0 so that was a big change in our project file that's it so with that we can now use record now i'm going to name these records uh with numbers we're not going to we're not going to get into trying to simulate a real world thing here i want to be very clear as to what each is and it's always a demo so recall this record one it makes me cringe doing it but it makes sense when we look at how we're gonna try and keep track of everything so record one string first name string last name semicolon that is a declaration of a record you've got the record declaration instead of class we have our name like normal and here what i've done is it looks like a constructor right where we've passed in in parens or parentheses i say parens for short just you know we pass in first name and last name and notice i'm not using camelcase here meaning a lowercase f in a lowercase l for first and last name i'm using pascal case where each word gets its capital letter and the reason for that is because what this does is it actually behind the scenes there's a whole lot of work for us in the record declaration and this is where the power of records comes into play so let's talk about what is happening behind the scenes here let's first start with the a bit of the confusion you've probably heard it say that records are like value types and if you don't know that means there's value types and reference types and normally classes are reference types always the reference types and what that means is when you copy a class from one or pass it around you're not passing the actual class data around you're passing a reference to that location it's kind of like when you build a house you pass the address around of the house not the physical house copying it that's what a reference type is a value type you're actually making a physical copy of that data and passing that around well records act like value types but they are not value types they are reference types in fact this is a very important thing to understand that a record is just a fancy class that's it it's a class with extra stuff that's all it is so don't get too caught up in value types versus reference types and how oh value types are better because they're faster no they're it's a reference type that's what this is it's just that records have a whole lot of things going on behind the scenes that are happening for you it's kind of like some pre-built code to make your life easier and we're going to see how you use all that pre-code today let's start with the very basics by creating a class that is similar not the same but similar public class we'll call this class one again in order to indicate that it's the same as record one and in here we'd say prop string first name prop string last name at a very high level this declaration right here is similar to this declaration right here where we have two different properties that have been created this is going to be a property and so is this now to get closer to a record this class should actually have init instead of set now if you watched my previous video you know that init means that you can only set this value in a constructor or when you create the class using the curly brace syntax so that brings us to the next feature of a record and that is it's immutable i think that's how you spell it we're going around with that one immutable which just means that it cannot be changed the values cannot be changed all right so what that means is that once you set the values in a record they can't be changed by default by design so think of a record as a read only class that's pretty much what it is it's read-only now there are ways of getting around this you can make it mutable which means you can mutate it or change it but that breaks the design of the record and really hurts some of the benefits that the record provides you if you need your values to change inside the class then you really need to clap i'm sorry inside the record you really need a class so a class we can change the first name later if you want to normally this would be a set here that's a standard class well you can change those values in a record we basically lock it down to be read only that's the immutability of records now we'll see a little bit how to make copies so that when you want to change the state you actually create a new version of that class or that record so we'll see how to do that a little bit but that's one of the other things about records is they're immutable now i said that this representation of a class is similar to this record but it's definitely not the same there's a lot more that goes on behind the scenes in a record so we're gonna keep adding to this class and kind of see what else we can see out of it well one of the things is that this is actually the constructor signature so let's create constructor for class one that's similar ctor and we'll say that you need to pass in string first name comma string last name notice i'm using camel camelcase here because that's what we do with parameters which these aren't quite parameters they're more like a definition therefore they get the the pascal case so here's a tip i've learned recently i don't know how soon this was put into visual studio if it's recently or not but control dot here i can say initialize property first name click on that and now it says first name equals first name really awesome feature here so control dot that's a little bit of boilerplate code that i've had type over and over again for years it's nice to build control dot and just do it automatically so now we have closer to what the record provides in just this one line in these what 10 lines of code see we've got the the two properties we've got the constructor that assigns the values we've got all that in record but also record has a lot more like a deconstructor an override for equals and not equals and an equality check and so on we're going to see all that right now let's start by coming up to our static void main we're going to get rid of our initial line i'm going to create three records and three classes so they're all going to be record one is the class or the record name and we're gonna call it r1a equals new and we'll say tim corey and then we'll have a copy this this line right here i'm going to say paste it two more times we'll call it r one b and r one c these are horrible variable names in normal cases but in our case i think they're a little clearer so r1 refers to this is a record one meaning this is a a record object and a b and c are the three different ones we've created this last one here we're going to change to be sue and storm i create three classes that are exactly the same except they'll say well you'll see class 1 c 1 a equals new tim corey like so let's copy this paste it two more times and we'll say b and c this last one is sue storm all right so just to recap real quick i have three record objects they're all record one type i've got the i call them a b and c and i've got three class objects which the class and the record are going to act similarly so we have our first name and last name we even made them inits so they're it's similar but not quite the same and i've got class a b and c as well the first two so a and b for both of these the values are the same so tim and corey tim and corey for both a and b record for both record and class the last one for each is sue storm instead so now we have our test cases i want to show you a quick setup so i say console.writeline record type and then we'll do a so space is down here we'll say console right line that's empty console right line that has a whole bunch of stars in it to differentiate and then another blank console right line and we'll say console.writeline and this will be class type so what i do is some comparisons of how the record behaves versus how the class behaves in our console writelines the first one is really simple console.writeline dollar sign we're essay 2 string and then in double quotes we'll say r1a that's it just r1a so we'll do the same thing for our class so instead of r1a we'll say c1a so we're going to print out just the actual object itself now if you're familiar with classes you'll know that when a class gets printed it's going to say our namespace this was record demo dot class 1. where it does for our record so as you can see there's our class it says two string is record demo dot class one our two string for our record is record one and then curly brace first name equals tim last name equals corey close curly brace that's a lot more readable that's one of the benefits of a record is it actually overrides the two string method and it gives you this nice neat uh value of everything in the object personally i wish that classes would do this but they don't so this is a the first value or the first bonus of using a record type is that nice to string if you've ever used a drop down and you put objects into it and forgot to assign the display value and you just it just decided to do a two string on each of your objects and they repeat over and over and over again record demo dot class one and you go what's the matter well that's why you've done a two string on your object at least with the drop down it would now say oh yeah that's my objects it's just not printing out properly but at least i can see the values so little thing there there's definitely some uses for that whether it be if you want to you know very quickly log something you don't want to go through the hassle of grabbing every property just do a two string on the object we'll get you that without having to do a right now we do a json serialize i'm sorry yes json serialize and then capture that string but um yeah so it's just a nice little feature there to override a two string so that's the first thing to look at here we get into some more interesting territory though console write line and let's say whoops dollar sign which is our string interpolation it will say are the two objects equal all right and the object we're going to compare where i say equals r1a r one b and close credit braces so we're gonna compare this object right here and this object right there let's say are those two equal well they are two different created objects i can tell you what a class will do let's copy this and paste it down here and change it to class and class so c1a and c1b which again they have the same values too a class equality looks at the place in memory it is remember that when you create a class it's kind of like building a house off of blueprints you build the house and then you record the physical address of that house the location where the house lives and then when someone says hey where is that that class you go it's one two three sesame street there's the address you pass that address around but they're all pointing to the same house but when you build another house off of that same blueprint it has a different address so equality is going to say no let's look at records so there's our equality equals false for our class but up here it says true those two objects are the same well how are they the same because they have different they were created differently they were created two different types in two different objects they weren't just copied well the reason why this is where that um that concept of records act more like value types comes in because if you say is you know if a variable a has one in it and variable b has one in it and you say are a and b equal it's going to say yes because the values are the same well this is one of the ways that records act like a value type because it compares the values inside the object to identify if the two objects are equal okay so that's another thing here and that is that behind the scenes this is something that our class down here is not doing i'm not going to write the code to do it but essentially what happens is there's another method in our record that's not seen but what it does is it overrides the equality and says we're going to compare every property to each other in the in the same object and if in our case first name from object a equals first name from object b and last name from object a equals last name from object b then the two objects are equal that's what it's doing we don't have that override of equality in our class it's just comparing the address of our class instance now just to be clear here let's copy this one more time and we're going to say objects reference equals now what reference does is it looks at the address on disk for anything not just the value it's gonna look at the actual location where this is stored and say is the location where this is stored the same as location where this is stored and let's go ahead and copy this and come down here and we're gonna say um c1a and c1b so now we're do the um the reference equals for both records and classes and notice that no they're not in the same location they are the same object as far as value goes but not as far as location goes whereas down here both are false because they're neither in the same location nor are the same when you say equals because again still it's still a location so they are equal in value not equal in where the data is stored now this this method right here is doing an i equality check there is another way to check equality and that is if we let's copy this line because it's easier to try and retype this over and over again um let's say double equals so instead of equals like this we're going to take this code out and say does r1a double equal r1b like you would in an if statement so this is a different equality check than this is just so you know they do slightly different things but microsoft the developers at microsoft have thought this through and say you know what we're going to do i equality all the way down and so they've overridden both this and the not equals so we're going to see that this still works let's make sure he changes to class 1a and class 1b if we run this again you'll see that double equals is true here and false here again it's doing that e i equality check and it's going to compare the values here not the reference location so even double equals works you could also flip the script if you want to let's do that just to show it um not equal in this case we're going to do r1c because remember c is sue storm so again we'll do c1 oops c1a and c1c and we're doing a not equal here and again this is not equal and yes this is not equal as well because this checks for the location on disk of course they're not the same this checks for the value not matching so we've overridden this this and this in our record type but that's not all let's do another console right line here and we're gonna do our string interpolation and we're gonna say hash code of object a and we'll say r1 a dot get hash code there we go and we'll do the same thing for b and c so object b got ahead of myself there and object c and we'll change this to b and this to be c it'll come down here and we'll paste it again but this time oops got an extra line there this will have class 1 a and we'll do the same thing for actually let's copy these because it's easier to change it one time class 1 b and class 1 so there we go now we're going to check the hash code now if you're not familiar with the hashcode what it is is it takes all the stuff in the object and it creates this unique code based upon what's in the object and that code can be used to identify if the object has changed because whenever you change anything inside the object the hash will change but that does mean that normally you would look at it based upon its location on disk as well but they've overridden that for records so now two hashes we notice here notice down here for all three objects the hashes are different even though these first two objects have the same values that's because it bases it also on the location in memory when you're talking about class but in our records these two right here are the exact same and the reason why is because they've overridden that hash code to be about just the value inside the object so that you can say that yes object a is the same as object b that can be really useful when you talk about the idea of what if you want to have a list that has no duplicates in it well just do a link query based upon the hash code and say give me all the unique ones that would do that it would eliminate all the duplicates so let's close that out so we've seen here in this this testing section that records over on the tostring they override the eye equality check which also means they override the double equal and the not equal they override the hash code and they allow us to create essentially all of this code plus all those overrides with just this one line of code but it gets even better than that because let's go down below our our last console writeline we're gonna do some work down here that we don't need to write out necessarily but we probably will just to demo what it does so let's put a a blank a blank line in between just we know that there's you know other stuff coming that's not in this uh head-to-head comparison i'm going to leave this almost here for you so you can kind of see and and look over the source code remember you can download it from the description um but the one of the other benefits of this type of declaration of a record is the fact that we can say var let's do f uh fn ln this is a tuple so i've declared this is a var instead of trying to give a type name i said var i'm going to declare this anonymous tuple i don't need to give it a name i can just give the name of the object inside so fn and for first name ln for last name equals r1a what did i just do well if we do a console.writeline we can say string interpolation so our dollar sign the value of fn is fn and the value of ln is ln like so so you can see exactly what i just did let's run this and the value of fn is 10 and the value of ln is corey how did it get those values well this is a this uses what's called a destructor and so what it does is or deconstruct i guess is probably a better word what it is it deconstructed this back into its constituent parts because we've declared it with these two values therefore we can deconstruct or d yeah deconstruct it based upon the same pattern so the first value coming in will be first name the second value coming it'll be last name because that's the order we declared them in when we created the record therefore they go right back out the same way so i can use a tuple as the the capture value and just say equals and my object and deconstruct it back into its parts if i want to do something similar in my class i won't do all the overrides and all the other stuff that they do but let's just talk about that deconstruct method um it looks similar to this public void deconstruct out string uh well first name out string last name yeah that that's the variable names will come out as and say first name equals this dot first name and last name equals this dot last name so what that would do is it create these out variables which would turn into a tuple and this is actually what the the um the il code will look like um the intermediate language code that c-sharp is compiled into um it'll create this deconstruct method it will have an out for every property in the order of the constructor and then it will send the property values out those out variables so that's essentially what it's doing if we had to write it ourselves we don't have to write ourselves we have to write that one line of code and again now we have all of this code plus those overrides we talked about up here but we're not done yet because we can also create copies of these remember these are kind of these are read only so if you wanted to maybe change the state of the object you really can't they're kind of stateless but what you can do is create a new object with most of the old values but maybe one changed value and with a class that's kind of hard to do you have to list all the properties copy them over one by one and then change that one value but now with records with records we say is record one and let's say one d you don't have a d yet um equals r one a with first name equals john well now we have taken r1a made a copy of it and just changed the first name value to be john now i don't have a lot of properties in there so we only have the last name being corey is the only difference but let's console rightline and just say john's record and we'll use that nice syntax of to string r1d that's it notice i'm not saying dot to string this is implicitly what it's doing but i don't have to specify that because by default if i don't specify it and i'm putting in a string like this it's going to print out that string so that's what it's doing but if i run this we'll see that john's record is first native john last name of corey it made a copy of my record it just changed the value of john that's another thing that records allow us is to say hey take another another record and use most of it but then this width here anything you put in this syntax any property you change will change the original value um that copy so we're a copy first name over but no we're not because we're gonna override that first name copy but we're gonna copy last name over because there's no override for last name so that's what it's doing it's making a photocopy of this and putting it here and that's another reason why they're like value types records are like value types because we make copies of them when we want to change their values so those are the big benefits or things that a record provides you over class remember again records are classes this have extra stuff around them and so that brings up one of the questions that i get asked is well what's the difference between a struct and a record it seems like they're the same thing nope they are not because remember a struct is a value type is not a class it cannot be instantiated it cannot be inherited from or inherit we can inherit with records and we'll talk about that in just a minute and it's it's not it's kind of apples and oranges here a record is much much closer to a class than it is a struct and we're gonna get into when we would use records near the end but first i want to go over some questions i'm sure you have around creating records we only created records one way and that is this way right here and so you may say well let's minimize class one you may say yeah but tim there's just so much they need to know here like what about methods can a record have methods absolutely well can it what if i want to modify how this property gets created can i do that absolutely what if i don't want to use this syntax to create a record when i want to create like a class can i do that absolutely what if i want to inherit from one record to another can i do that absolutely what if i want to inherit from a class to record or record to a class can i do that no records have to inherit from records classes have to inherit from classes so let's see some of the scenarios i talked about to kind of clear up some confusion public record record two and we'll start off by initializing the same way we did record one so first name last name cool there is our our new way of you know our new record record two against new record type but may i say you know what i want to make a modification to how first name is uh created as a property no problem what you do is you take off the semicolon you open some curly braces so you still have this declaration up here but then you have curly braces and i can say you know what i want first name to be changed the type instead of being public because since this is public then this is public as well but maybe i don't want that maybe i want to be internal no problem internal string first name whoops first name get init remember it's init not set equals oops equals first name like so so what you're doing is you're declaring this property explicitly and you're assigning the values being passed in now there's an interesting little quirk here about this i'm not sure if it's intended this way or if this is a little bit of a bug i think it's intended this way but not positive and that is let's come down here after john's record we're going to do a let's do a console right line just an empty one to clean these up we're going to say record 2 r 2 a equals new we're going to say again tim corey now let's do a console write line and say our string interpolation record or r to a value r to a like so so now just create that record and print out its value let's run this and when i say r2a value is record to last name equals corey where's the first name it's not there but yet it's actually in the object in fact if we were to do this and say console writeline again and let's say r2 a fn for first name r2 a dot first name and space space ln colon r2 a dot last name just to print out manually those properties realize again you'll notice that the first name is tim and the last name is corey and yet it does not show up in the signature and that's because we have overridden that that property now there may be some type of code i have to write in addition to this in order to get this back into that tostring method i'm not positive maybe it's a decorator or something else i have to add i have not found that yet though so just know that that does make a little bit of a quirky change to your code now let's talk about what if maybe you don't want to do that but maybe you want to add another property cool no problem prop string full name and that's full name property instead of having get a set we're going to do is we're going to say get arrow and we'll say string interpolation first name space last name like so with a semicolon at the end oops semicolon at the end not that end wow there we go so what this is it's a read-only property which remember records are designed to be immutable unchanging therefore this is perfect perfectly fine because it's not going to change anything but what it's doing is it's providing you that full name which is first name space last name let's run this again not changing anything else and if you notice now the full name shows up in the the signature so you have last name and full name i'm wondering if let's make a quick change even though we made it public even though this is basically overriding the original value with the same exact value let's just see if this will in fact give us back uh tim or actually john in this case yeah or tim nope first name is tim last name is corey it's out of order that doesn't matter and full name is tim corey so it does give us back our value if we make it public so that internal is throwing off i'm not quite sure why because internal still should work in the entire assembly so it must rely on a public uh since it's public as the uh as a type of record it must not want to potentially leak information outside the class that it should not know or also the assembly they should not know about so maybe that's why i was doing that maybe that's just my my quirk there but it's now put this value in the signature so it's going to compare those which of course it's get only it's based upon the values inside the class not a problem but that's how you would add your own property if you want but what if you want to go even further and say well i want a method not a problem you can say public string say hello return our string interpolation and say hello first name like so really complex method we have there but we can console rightline at the end and actually let's be honest console.line and r2a dot say hello call that method let's run this and hello tim so it has read that and and executed that method not a problem so even though by default this syntax is so simple if you need to you can make changes to it now let's just one more thing i want to touch on because it it may come up as a question as well we we've said that this is basically the same thing as what you would have gotten if you took this out so let's make a tweak to this let's say prop full for a full property string underscore first name call it first name like so this is a full property and let's set this instead of a set we need to say init there we go and for our get instead of returning the full first name let's do this where we say first name dot sub string and we'll start position zero and we'll go one in length meaning only give us one character so there's our our substring of one meaning we're only gonna return back t for tim and we have to assign this value so in the private string first name we're gonna initialize it to first name which i know this is confusing we have first name here we have first name here we have first name here what's all this about well this initializer is going to read this as the parameter string name first name we have to name these two things the same thing in order to make sense but unfortunately it does mean that it looks like we're stepping on toes but we're not c sharp is smart enough to know okay that object actually goes that's actually the parameter and that's going to be put into our private backing field this is the the actual property name therefore that's what's going to use to again get and only init not set so with that changing nothing else let's run this again and you'll notice that the last name is corey first name is t full name is t corey because we're referencing that that property that says hey when you get something only get back just the first letter and again the first name is t and hello t so this could be useful if you are storing let's say a social security number or a credit card number please be very careful how you do those things but if you were or something similar where it's sensitive information but you want to say that yes i've got it but i'm not going to show you normally well you could say you know for a social security number there is you know three numbers and a dash then two numbers and a dash and then four numbers well typically we show the last four numbers but that's it well you can return instead of just those last four numbers you could say star star star dash star star dash and just the last four numbers there's a lot of things you could do like that to mask most of it but show that yeah i've got it but i'm not going to show you and then you can have a special method that got the full value that only used for you know high security stuff where you've passed some clearances so lots of stuff you could do there with full properties and this still works with records just make sure you do init not set here and man was that ever a lot of stuff to cover all at once we have covered and let's go back and just kind of touch over again records are by default immutable meaning they do not change their read only once they're set we can declare them very very easily by just doing this type of syntax but if we wanted to override it with our own values we could still use this syntax but then put more values in here now if we don't use this syntax we can still create like a regular class like we did in this class and then create a constructor like so that would take the values in if we wanted to or we could just use the curly brace syntax but if we do that and don't use this syntax right here then we don't get the nice destructor which is this type of thing right here so that kind of limits what you get out of your record if you don't use the full syntax now we've talked about how it's overrides the tostring it overrides the eye quality it doesn't change reference equality meaning that they will be different places on disk and yet the same uh value comparison just not the same reference comparison it does override the equals and then not equals it does change how hash code works in order to make sure that that if the two values are the same then the hash codes are the same the last thing i want to talk about before we oh and we can use the with statement wow there's a lot more stuff deconstructor and the width statement we can use as well the wisdom allows us to copy from one object to another that's actually behind the scenes hiding a constructor that takes in itself like a type its own type and then it does the copy behind the scenes but that allows us to override one of the one or more of the values if we want to and after all of that we still have one more thing to cover and that is inheritance so right now we have record one but what if you wanted to create a a user record okay so record one pretend that's a person this is a person with just first name and last name but now we have um an employee database where public record user one which is going to be have an int id and then these values as well it would seem like you'd want to inherit from record one which we can do oops don't need the strings in front that's how you inherit from another record so record or i'm sorry user one inherits from record one meaning we now have this constructor which has the three values and we're saying okay two of those values need to get passed into your base class to initialize it and now we'll just have one additional property in user 1 and that's the id again you can still use this curly brace syntax if you wanted to where you say let's go ahead and do some extra stuff inside of user 1 and apply all the same type of logic inside of or modifying this record but just this syntax right here will allow user one to inherit from record one the keys remember here are first of all a record cannot inherit from a class can't but a record can inherit from another record you do need to pass the values in for the constructor in the object you're inheriting from so this case i'm asking for three parameters you may say well tim isn't that duplication shouldn't you just ask for id and then pass in the values of first and last name to record one well where you get those values from you have to get them from somewhere well you ask for all the values in this object the only thing will be added or created is the id property because we're inheriting from record one which has the first and last name and we're passing those values in from our constructor on user one so these two values go over here to record one and then this value gets put into the user one class so that's the i hate to say basics because it's much more than the basics but that's the introduction to records and all the things they can do and and how they do them but let's talk about why so far we've seen this cool new thing and yeah it's fun but why would you ever need records and that's always a good question to ask whenever you see new shiny stuff is yes but why do we have this because oftentimes especially a mature language like c sharp we are not getting brand new things that are so amazing and we need it for everything we do because mostly those things are already covered the one exception i think in c sharp nine is the not that thing we needed that since c sharp one but just now in c sharp nine it came out where we can say is not null i've been waiting for that for a long time but records aren't one of those things where i've been saying oh man i've been waiting for this but they are useful so let's do this let's go back to the very top and i'm going to put in here some some comments my thoughts on records let's start with the the benefits of records i can type and the first benefit that i see is they're extremely simple to set up i mean if you go look let's minimize this that right there declares a record compare that to all of this stuff that is super simple i love it so that's it's simple to set up thread safe since it's immutable a record is by definition thread safe now if you make it mutable is no longer necessarily thread safe and what i mean by thread safe is if you have two different threads operating in parallel and they're both working on the same object at the same time if they both change the value of last name at the same time that can cause a conflict that's where you have problems because you're both trying to write at the same time and it basically blows up since we can't change the value of any object or any property inside of a record by default i keep saying by default because yes you can force it to do the wrong thing but by default if since you can't change the values then there they there's no problems because you can read from the object more by more than one thing at the same time it's only the rights that cause problems with threads so therefore they're perfectly thread safe another benefit here is they are easy let's say easy slash safe to share meaning i can pass these things around all day long and not have to worry let's take a scenario for for a minute let's say let's look at our class 1 here if i were to pass this instance of class 1 around to another method and say hey i want you to print out the values in this and that does it and then it comes back well it didn't actually copy this class what it did is it passed the address that class and says this class instance lives at 123 sesame street well because it passed that address around that calling method could change the first name of timothy and then that would affect this method that would be a problem i can't stop that well with a record i don't have that problem i can pass around all day long it's a reference but just because you can see it doesn't mean you can change it because it's immutable therefore i can pass it around to other methods and not have to worry about the value changing the the information inside of it changing unexpectedly it just can't so let's talk about now those are the benefits of records but let's talk about the when to use when to use records and this is a tough one because there's not this overwhelming pool of of things we can pull from there's not like this this list of a hundred reasons why you would use a record the class instance there's hundreds of reasons why you use a class instance but with records one of the reason areas is if we are capturing external data that doesn't change for example if we read from that weather service you know the um in blazer we have that demo uh code that's in there in the template where it says weather service and it's technically just pulling from random data but if you pulled from a real weather service where it said okay the high today is x and the low is x and it's gonna be cloudy and and so on you don't need to change that data do you well no that's that's just informational data that you go you gathered another one is a swappy by the way it's um i've used swappy before it's now swappy.dev um and now it's dev um but swappy is a star wars api it's a really commonly used sample api to display data and so it you can look up a person and say hey which movies do they appear in so on but if you looked up let's say han solo and it comes back with here's the movie the han solo here's the movies that han solo was in and here's the other characters he's interacted with and here's the you know the ship he flies and his co-pilot and all the rest you would not expect to change that data therefore a record is a great option for that because not only does a record mean it's read only but again it's really easy to declare and it gives you all those benefits like comparing value types and making sure that you can have that nice two-string print and the hash code is the same and you know all this other stuff you can do with it the destructor all that comes with that record and it allows you to have that nice experience when working with the data from the external api or this external api or something else like that and speaking of apis another time when these are valuable is when you have your own api calls because a lot of times what happens is you get data from a database and then send it out the api you don't modify it in between you just get it and send it and when data comes in you might not modify it either you just get in and then you send it into the database well probably most of those could be records you have to look at is there any time where we mutate or change the data and is that done in the api itself not the user doing it is the api itself doing it another case would be whenever you are processing data meaning you get data from your database and you're doing something with it or based upon it but you're not changing the data and this can be really interesting one because it might be one where you merge the two concepts classes and records together there is a a potential case where you would create a class that contains a record let's think about this for a minute let's say you have a database of 10 000 people and those people you want to check to see if they have had any um incidents online that you find troubling so what you're going to do is you're going to pull down that database of 10 000 people you get get those into records those records going to look kind of like this or actually probably more like this because you'd have their id as well but then we're going to do is find any cases where you know using ai or whatever actually machine learning not not artificial intelligence but machine learning you're going to find any cases where they posted harass harassing information on you know their facebook profile twitter instagram and all the rest you're gonna do a search so you're gonna do this in parallel because you have 10 000 people to look through and you don't want to change their information in their record about who they are their id their first name and last name but maybe what you do is you create a public class that is they call discovery model where you say prop user one is the um user looked lookup user where that is user one is a record but it's a property inside a class that's fully that's fine and then you can have um incidents found like this and maybe a a list of string incidents i don't know something like that um by the way ctrl dot to add the using statement there i need for my collections um but so this this class would have your read-only information about the user and then you would populate the values of the things that you found based upon the search so you get this whole list of records from the database and then you create this class that says okay this is the user i'm talking about and here are the associated data points that i found so that might be another case where you use records basically anytime you want to work or can work with read only data anytime you work with renal idea a record might be the solution you just have to commit to the fact that this data is read only so those are the times to use records let's talk about when not to use records well the first time is when you need to change the data for example entity framework this is one of the questions i i heard asked almost immediately when i was listening to a a demonstration about records the question was asked well will this work with an entity framework and the the answer is well no not yet and they're they're thinking about c sharp 10 and maybe they've got to figure something out for this but think about that though in entity framework especially we have the idea of change tracking where you make a change to a value and it goes oh i'm dirty i need to update this value in the database well you can't do that in a record because it will never be dirty because it's never going to change dirty means it has a value has been changed so that's not a good case for this if you need to do any kind of tracking it won't work and anthony framer is really big on that so it just won't work to try and shoehorn records into entity framework i haven't tried it yet but it seems as though it should work just fine in dapper because typically in dapper we don't have the idea of change tracking unless we implement it but we could say you know what this is read-only data no problem i'm just going to use records instead and since they're essentially objects with extra stuff i'm sorry classes with extra stuff it should be fine i'm going to test it out we'll try it out probably in the future but if you have any kind of mutation of your object or any part of your object then records is not for you i think that's probably about it for when not to use it but in in general we change objects all the time so if you have to default if you don't know use a class if you are absolutely certain and you know that it's not something like this we need to have change but you're absolutely certain it's going to be read only data then go ahead and use records try them out but i would just encourage you to lean towards using classes not records unless you're absolutely sure that's the default default is class because c sharp is object oriented a class is an object that is mutable that's what they're designed to do and that's what c-sharp is designed to work with so therefore i would encourage that unless you know for certain that you don't need to have that immutability it can be immutable in which case a record might be the way to go now one final thing i want to go over in here um i debated even putting this in but i've decided it's important enough that i want to show you but i'm gonna put in big bold letters do not do any of the below okay is that clear enough do i need to put the little flower box around it i'll put the flower boxer out because i'm a very clear jump up and down don't do this i want to show you what not to do because you may say oh well i saw someone do this and it works just don't do it public record um what are we on now record two or three i think we're on record yep record two already so this is record three record record three open close create brace i've already broken the the syntax of the the constructor parameter what's wrong here why am i yelling you saying do not do this that right there set guess what this works it shouldn't in some ways i think that um this is this is very problematic for a number of reasons one you don't have that nice constructor so you have no destructor and another you have mutability you have the ability to change these values this is this will work but don't do it it defeats the purpose of a record and it makes your code smell it can cause instability because if you're expecting that hash code to not change you're gonna have a problem so two different values aren't gonna line up right it's it's gonna cause messes in your code and your your fellow developers are going to expect a record to be immutable this is not immutable this is mutable me it can change that's going to cause expectation problems that will cause assumptions about this record that aren't true so just be clear here the set makes this record mutable bad okay just to be clear here um so that's one thing that i think you should avoid i know you should avoid when dealing with records with that being said yes you can just if you can do something does not mean you should do something but there's probably some weird edge case we were like yeah but tim i know in this one squirty example that there's you know if you stand one foot and hop around and circle blindfolded that it's more important to have a mutable object in a record okay yeah i get it that's not the majority of life the majority of life is don't do this also no constructor so don't deconstructor so that's another problem um with this setup another thing that you shouldn't do and there's not really a code sample for this but um don't just make clones all over to um update state so we have this ability and let's let's get the illustration here up on the screen so it's of course inside the selection or section i collapsed but we have this right here where what we're doing is we're basically a clone of this and just mutating one value or changing one value so this this is now a copy of this but this has a different first name you could in theory say well every time i make a change to a record i'll just create a new object and mutate it over or copy over and use the with statement to change the value we need to that's making a copy of that object it's duplicating in memory the entire class that's not now to be clear it's a shallow copy meaning if you have a class instance as one of your objects or one of your properties it's not gonna make a copy of all the values of that class just the reference um but even so it's made a copy of all those values in memory so you're being not very efficient here and that's where a class is superior in the fact that you don't have to make a copy of every property you're just overwriting the one property with a new value so this syntax is is fine it's great for either making a copy in order to change one value or change a couple values to make a new object or a new type but it's not for really taking the place of mutability if you need mutability use a class don't try and force records to be mutable so just want to point that out as well so that's that's records and i would say in nutshell that's definitely not a nutshell it's taking it taking us about 70 minutes to get to this point um a lot of stuff going on records they are in a lot of ways really cool and i wish in some ways we take some of what we have and put them back in the classes you know that that to string is really nice we can't override the um the hash code but we could do some other things or make a make an extension off of class or something like that it does most this stuff because a lot of this stuff is great stuff even for objects that are mutable but unfortunately we only get it for records and records are supposed to be immutable so that's that's what records are that's how they work that's how to work with them how to use them how to tweak them and modify them and really kind of this was a deep dive not just an intro but a deep dive into records to make sure that you have a good solid foundation and how to use them effectively and also know when to use and when not to that's kind of the real world side of this thing where it's not just a nice shiny new object it's actually something you're going to use so now you're prepared to know when and how to use records if you have any questions leave them down in the comments give me thoughts leave them down in the comments if you saw i missed something let me know uh one thing i want to point out is and let's just real quick i'm going to do this i'm going to create a real quick demo very very quick it's going to take two minutes it's gonna be a console app and um top level call this is something i missed that pointer that's i'm sorry that viewers pointed out i appreciate the the shout out i appreciate you pointing this out so this is a top level call let's bring this back to the beginning and let's change our if we look at the project file notice net core app 3.1 it's um is it just net 5.0 yep so if you just change this to um net five dot oh i showed you how to change the right click and go up properties but this is the same thing and now that's a top level call we saw that and i showed it off in the previous video we talked about the new stuff in c sharp 9 that was not records but one of the things i said in there was that you don't have access to args here and that was one of the things that we looked back at um this we have this string args which are command line arguments that are passed into our application and some viewers of mine said you're wrong tim uh very nicely they said that but they're wrong i'm wrong there is a way to access that and so if i were to say cw i can say args notice that i still have access to that even though it doesn't specify it anywhere those are still available to me so i just want to point that out that um you know that's something a viewer pointed out and you know i'm i'm gonna definitely try i can't modify an existing video but i can definitely show you in the next video or the next time we have a chance to look at something like that so if you see something with these records of course i'm very new to records um just like everybody else is because they're pretty new but if you saw something like hey team missed something let me know i will try and come back and circle around to it again and um you know and showed off at that point okay so i thank you very much i appreciate you watching till the end it's been a long one but hopefully it's been a lot of value to you don't forget get the source code down in the description there's a link to get that as well as that link to my mailing list like i said next week for not very long we'll have a black friday sale that black friday sale is going to be 30 40 50 off a lot of my courses and when i say that i don't mean that most of them with 30 off actually most of my course would be more like 40 or 50 percent off a few will be a 30 off it's not gonna be every course um the and we'll talk about that more later but the uh foundation c sharp series is actually really underpriced i really try to keep it as low as possible so that's kind of an everyday low price we don't discount that um but everything else pretty much will be discounted so just you know that's coming up make sure you're on the mailing list here so you hear all about it and get those values okay thanks for watching and as always i am tim cory [Applause] you
Info
Channel: IAmTimCorey
Views: 68,058
Rating: 4.9487467 out of 5
Keywords: .net, C#, Visual Studio, code, programming, tutorial, training, how to, tim corey, C# training, C# tutorial, c# record, c# 9 new features, .net 5, c# 9, c# 9.0, c# 9 records, whats new in c# 9, dotnet core, record types, c# 9 features, whats new in c# 9.0, .net 5 features, dotnet 5, .net 5 new features, c# 9 with expression, c# 9.0 record types, c# 9 records inheritance
Id: 9Byvwa9yF-I
Channel Id: undefined
Length: 79min 44sec (4784 seconds)
Published: Fri Nov 20 2020
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.