BrandGhost

Beginner's Guide To C# Record Equality - How & Why To Use Records

In this video, we'll look at how record-type equality varies from class-type equality! We'll discuss the reasons you may want to care about this along with an interesting "gotcha" situation! Stay right until the end! For more videos on programming with detailed examples, check this out: https://www.youtube.com/playlist?list=PLzATctVhnsghN6XlmOvRzwh4JSpkRkj2T Check out more Dev Leader content (including full in-depth articles with source code examples) here: https://linktr.ee/devleader Social...
View Transcript
hey thanks for checking out this video today we're going to be looking at equality comparisons with the.net record type and if you stay right to the end of this video if you're stuck on older versions of.net and you want to see how you can use the newer record type in the older versions of net stay tuned I'll show you how to do that and one more thing towards the end of this video I will show you an interesting comparison trick to work around with record types so let's jump right over to visual studio and get started alright I'm here in visual studio and I have a project that's called record type a quality demo this will be up on GitHub in my Dev leader repository I'll link to that in the description so you can go check that out if you want to play around with this but it should be simple enough that if you just want to follow along and visual studio that'll work too okay so the record type that we have accessible to us in C sharp you can declare such as a record my record and then we have this Constructor type that actually allows allows us to have positional properties so we can say like int X and I guess their property so we'd give them a capital um and the same thing technically on the naming here right we want Capital so this actually gives you a a type that would have a property X and a property y on it but what's the difference between something like that and something that just looks like what we're used to seeing which might be like my class and then we have um co-pilot was trying to help out their public int X there we go thanks copilot so what's the difference between these two things right A lot of the time if you're not used to using records you haven't seen them you haven't had an opportunity to play with them you're used to writing code that looks just like this and if you were to actually check these out they look very similar right um the difference I guess is like um when we instantiate This Record you might be arguing okay we can pass in X and Y we could also put a Constructor on on this class up at the top and pass in X and Y but both of them have properties X and Y that are integers well what I want to look at today is actually doing equality checks with record types and I'm going to contrast that with classes and then as I mentioned right in the beginning of this video I'm going to show you a little trick that we might have to to think through and how to work around that when we're doing comparisons with record types so let's start by actually doing um like checks around my class so we're going to start by doing class comparisons just so we can set the stage for what we're working with historically and why something like my record might actually be useful for a lot of the work you're doing so when we look at a class if we wanted to declare my class and I'm going to say first and I'm going to make a new one I'm going to instantiate the X and Y values here so we'll do X is 1 Y is 2. cool if we wanted to and we had two of these right so copilot's actually really good I should have just kept pressing Tab and letting it finish the video for me if we had first and second here you can see the X and Y values are the same but we do have two instances right we have new and new as we see on line one and six if we were to go check if these are equal and I'm going to write out wow this is incredible um thanks copilot I feel like it's listening to my microphone too I was going to say we can actually do um two checks for this so we can do that and we can also do we'll do object equals just so people can um if you're more familiar with the different equality checks that exist in C sharp this might get you thinking about different things so we'll do a double equal sign and then we'll do object equals and then I wanted to also put um that and then we'll say object Dot okay so if I go to run this as we can see and probably as we expected we would have false and false um and that's because and actually maybe some people did not expect that but these are false in terms of equality because they are two different instances and what happens a lot of the time historically is that people are checking code like this and they're going oh man that's not what actually what I wanted maybe I'd switch this over to a struct and actually in this case um using a struct might not be a terrible idea just because we have what looks to be a really simple value type it kind of looks like a point um you know a two-dimensional point with integer values maybe a struct is okay here but if you wanted to stick with classes probably at this point what you would start doing is implementing your own equality operators you'd you'd have to go do a get hash code implementation and these things are stuff that people mess up all of the time it's not totally straightforward there's guidelines and stuff from msdn on how to do that but if you're just looking at code online there's so many copy paste variations and errors that people just don't do it right and that makes it kind of dangerous because when you want to have something like an equality check you really want that to be Rock Solid okay so if that's what we're used to having historically um and as I was saying people would start to go into like okay well maybe I want to actually override the equal operator um and then you have to go override get hash code so you're gonna have to have these two things implemented in your code to actually start to get what you want now this is where the record type comes in and I think it's really awesome um I think I've been using C sharp for uh probably about half my life now which is kind of scary to say and I remember when they announced the record type I didn't really catch on to why it was valuable um and then when I started realizing in like one use case I was going through my entire code base and changing a bunch of classes to be records so let's go back up to the top and instead let's try looking at what we can do with a record so I'm going to say my record um I guess yeah we'll call it third whatever we'll call it like first record sorry co-pilot close but not quite um and then I'm gonna do let's see second record thank you co-pilot I'm gonna copy these two lines um and just make sure I update them properly so this should say my record and then we will do the first and second record here awesome okay so let me go run this so this is interesting right because all that I have done is changed the uh Class Type to be a record um as we discussed we still have the same two integer properties X and Y there's still one and two respectively for the first and the second class and first and second record but the equality checks that we have on the record actually come back as true and this is because the built-in record comparison type is actually doing it more like a value type comparison now if we go back to visual studio let's talk about this for a second why is this really valuable for us and what use cases do we have around this well in my opinion A lot of the time we want to be using records instead of classes for things like data transfer objects dtos and data transfer objects if you're not totally familiar with what that means maybe you've heard the you know dto or data transfer object kind of being thrown around these are just objects or types that are really intended to just carry data around inside of your application maybe in something like Entity framework you could compare it to something like an entity where it's really just a type that holds data and a lot of the time when we're trying to do comparisons with these things we don't actually care if it's the same instance of the of the type that we're looking at we actually just care I'm going to use air quotes here that you can't see but we actually care that it's like the same shape and what I mean by shape is like we have the same values in the same positions right so we have one assigned to X in both of these and then we have two assigned to Y in both of these so for us a lot of the time with data transfer objects we don't care that they're not the same instance we just care that they look the same and that's why when you're doing equality checks and you're using dtos I really think that records are much better suited for that but that's it for the most part I just wanted to show you a very simple uh difference between these two because again these types my class and my record look very very similar but let's talk about something that's a little bit more complicated because we just had integer types as the properties what we're going to do on our record is actually Implement another property and we're going to call it strings with a Z on the end just to spice it up a little bit but it's a list of strings we're passing that in is our third property so let me go ahead and get this example fixed up all right so all that I've done here is actually added in another property so we're inserting this list of strings and you'll notice between the first record and the second record I actually have the same set of data being passed into the list here and again when we're looking at this record type I mentioned the the phrase or the word shape right these have the same shape right we have one and two being passed in then a list of strings that has first and second and it's the exact same in both cases but what's going to happen when I go run this all right so maybe this is a little bit surprising for you maybe not based on what I was showing so far but now the equality checks are coming back as false and even though we have what looks like the same two lists it's coming back as false because the list is a reference type and when it's trying to do an equality comparison on these lists it is not doing an equality comparison by value conversely the X and Y properties are integers and it was doing a comparison by value on those and as a result now we have a bit of a mishmash of what we might expect to have for inequality check if instead we pass in the exact same instance of the list into both of these what do we expect to happen when we go run this now well based on what I was saying before right before I ran this when we're doing an equality check and we have the reference type of list of strings it was doing it by ref and not by value for comparison now that we actually have the exact same reference of the list I'm just going to move this over and you can see that we have the strings passed into both of these record types it truly is the exact same instance and when it goes to do a comparison it is going to come out as true so unfortunately I would say that if you're building complex record types and you want that equality comparison to kind of be handled automatically for things like lists or other reference types that you're dealing with then you might have to get back into overriding the get hash code and the equality operator but for the most part when you're dealing with record types and all of your properties are actually just by value types that can be compared this will work perfectly for you out of the box and one more super awesome thing is that we can actually call tostring on these records and instead of you writing a custom two string for your class to be able to Output all of the properties when you go to call tostring on these things they just work perfectly out of the box well I said perfectly but I mean it's almost perfect out of the box so when we look at the two string calls that we have right here we actually have X and Y called out pretty straightforward but the actual collection of strings unfortunately is not a pretty printed for us it's not printing out you know like a a Json structure for the entire collection so again it starts to break down when you have reference types in there but when they're value types it is super clean Super straightforward and literally no extra work for you to go deal with you're just declaring things as a record instead of a class alright that was just a really basic one for today so just to recap on what we touched on the record type is actually a very useful type for you to use in C sharp when you're trying to work with data transfer objects and you're trying to build well you want to avoid building your own equality comparisons and this is because a lot of the time when we're dealing with data transfer objects we have really simple types that have other simple types with them right so we're going to have like in this example we looked at we had integer properties so going to write your own equality comparisons and stuff like that it's just a ton of extra work and very error prone and then I quickly showed you that you could actually have the two string call work out of the box so you don't have to go write your own of those anymore super handy and then the quick little thing that we looked at was that if you're dealing with reference types within your records that's where your equality checks might start to break down so you're going to want to pay attention to that in your travels okay so hopefully that was useful thanks so much for watching and because you stayed right to the end if you watch this video right here we'll talk about how you can deal with record types and earlier versions of.net

Frequently Asked Questions

What are C# records and how do they differ from classes?

C# records are a new reference type that provide built-in functionality for value-based equality checks, which means that two records with the same property values are considered equal. This is different from classes, where two instances are only equal if they reference the same object in memory.

Why should I use records for data transfer objects (DTOs)?

I recommend using records for DTOs because they simplify equality checks and reduce the amount of boilerplate code you need to write. With records, you don't have to manually implement equality operators or hash codes, which makes your code cleaner and less error-prone.

What should I be aware of when using reference types within records?

When using reference types, like lists, within records, the equality checks may not behave as expected. They will compare references rather than values, so if you want two records with the same list to be considered equal, they need to reference the same list instance.

These FAQs were generated by AI from the video transcript.
An error has occurred. This application may no longer respond until reloaded. Reload