Convert ANY Of Your C# Types Without Casting Using Implicit Operators
C# is a strongly-typed language, and if we want to convert between various types in our code, we're often required to use explicit casting operators. This expresses that we want to go from one type to another very explicitly to readers of our code, and the compiler.
But what if we want to be able to convert between types without casting? We can leverage implicit operators in C# to do this -- but we need to be aware of the pros and cons of doing so!
View Transcript
if you've been programming in c for a while you've probably noticed that we can do type casting to be able to go between types but you've probably also noticed some situations where we can go between two different types without any casting at all and it might seem a little bit magical to you so how does that work my name's Nick centino and I'm a principal software engineering manager at Microsoft in this video I'm going to teach you how you can use something called implicit operators to be able to do type conversion without having to explicitly cast things between two different types just a quick remind you to check that pin comment for a link to my free Weekly Newsletter and my courses on dome train and with that said let's jump over to visual studio and check these out okay so we're going to walk
through an example and I've written an entire blog post about it that you can check out here and I'll have a link to that in the description as well and what we're going to be doing in this example is converting between two different types that aren't going to lose resolution and I wanted to call this right out in the beginning because if you're interested in being able to leverage something like this one of the big risks and I think it's important to call call it out in the beginning is that sure you can go add these implicit operators to convert between different things but if you do that you need to make sure that you're not losing information when you do that conversion and what I mean by that is if you're automatically able to go from one type to another and not explicitly having
to put in a cast you might have it such that people using the code that you're writing are converting things accidentally and they're not realizing that once they go automatically from one type to another if they try to go back they might go oh crap some of the information that I was storing in this object is now gone and maybe it's not gone but it's been rounded down and you can't get the information back you start to lose the resolution of whatever you were trying to capture in the beginning a really simple example of this would be having something like a double Precision floating Point number so like you know 12.34 if you automatically could go to an integer with that you'd be going to 12 basically right if we could automatically do that conversion if you tried to go back from 12 to get
a double you would be at 12.0 and that's not 12.34 and that means you've lost data so I just want you to keep that in mind as we go through these examples and I wanted to mention it at the start so you're aware of some of the risks with this in this example we're going to be going between megabytes and gigabytes and you could extend this pattern to kilobytes and other things as well but this is a pretty simple example to get the idea of how this works we're going to make a struct called megabytes and I made a struct cuz want it to be a value type it's very simple and then we're only going to have this value property on here but the magic is right here and we have this method that has these keywords at the front so it's public static
and then an implicit operator as well the name of the method in this case is really just the return type that we're able to do the conversion with we're going to be able to go given megabytes and convert that to gigabytes and that means that we take in a megabytes instance here and that's because it's static we're not operating on this current instance or anything like that we need a megabytes instance passed in and then what we're able to do is the conversion right so inside here if we divide megabytes the value that we have for megabytes by 1024 that would give us the value in gigabytes so then we can return a whole new gigabytes here and as you might expect we're going to go look at the next class and it's going to be very similar right it's just going to work the
opposite way so we have a gigabytes class it also has a value very much like we just saw on the megabytes struct that we created and then here the implicit operator is just reversed right so we are returning megabytes we're passing in gigabytes and then this logic works the opposite way instead of dividing by 1024 we're going to multiply by 1024 and recall that example I gave you at the beginning with the double and integer right because I'm working with a double we should not be losing Precision because if this was an integer and if I go back up we did this division right here we'd be in for a world of pain because doing this your division would mean that we end up truncating that data and then we could not convert backwards to get the resolution back out these two methods right this
operator here and the inverse that we saw in the first struct these are what's going to allow the magic to happen where we don't directly have to cast between these two things there's no other relationship between these two types so that means because there's no inheritance hierarchy or anything like that we shouldn't really be able to convert between them except for the fact that we have these operators is added so let's go look at the example of how we can use this okay so this example code that we have at the top here is going to make a megabytes up so we're having some type of storage that's going to be uh 248 megabytes and that's going to be hopefully 2 GB in storage when we go to do this conversion but you'll notice line 11 we're declaring gigabytes right so we have this variable
called gigabytes it's of type gigabytes and I'm directly assigning storage which is megabytes into here if we go write that information out we should should be able to see that gigabytes is just going to Output two and that's because if we have 248 and inside that conversion is doing a division by 1024 we should get two printed out when we look at the value for gigabytes but we want to be able to go backwards right we want to make sure that we can do this conversion backwards and it's all going to work without losing resolution so line 16 is also like line 11 where we're able to take gigabytes as the type and implicitly convert it to meab you'll notice that I don't have any cast operators where we have the type in parenthesis we can just implicitly do that conversion thanks to the operator
and then from there I'm just going to write out to the console the value of megabytes and we should get back 248 just like we started with so let's go run this and see if this works okay and here is the output I figured you didn't doubt me but when we look at the first line that's printed out here this number two comes from line 13 here where we're getting gigabytes which is going to be just two because we started with 248 megabytes and given that if we look at the last output in the console here 248 that comes from line 17 because we were able to convert back properly and there you have it it's very simple to be able to add implicit conversions just like we saw but I want to bring up the disclaimer that I added in the beginning of this
video because I do think that if you use this properly it can make some nice readable code but I think that it's very easy to abuse things like this because it's not really a natural way that we're using types in C so the biggest things that I'd recommend keeping in mind are number one that you don't want to lose data resolution when you're doing this conversion and number two I want you to think about these conversions making sense so just because you can convert something like megabytes back to maybe a double implicitly once you do that you are technically losing some data resolution because what's the unit of the double right it's maybe not a good conversion in general maybe in situations it might be helpful for you so just something to think about because once you introduce this it means that anyone using your
type can do these conversions implicitly and it might be dangerous to them if they're not aware that that's happening and potentially losing some resolution now C has plenty of things that we can use that are very powerful and often get misused so if you're interested in seeing another thing like that I recommend you check out this video next thanks and I'll see you next time
Frequently Asked Questions
What are implicit operators in C#?
Implicit operators in C# allow you to convert between different types without needing to explicitly cast them. This can make your code cleaner and more readable, as it enables automatic type conversion when the conversion is safe and doesn't lose data.
What should I be cautious about when using implicit operators?
When using implicit operators, it's crucial to ensure that you don't lose data resolution during the conversion. For instance, converting a double to an integer can result in losing the decimal part of the number, which may lead to unexpected behavior when trying to convert back.
Can I use implicit operators for any type conversion?
While you can define implicit operators for your custom types, it's important to ensure that the conversions make sense and are safe. Not all conversions are appropriate, and you should avoid introducing implicit conversions that could lead to confusion or data loss for users of your code.
These FAQs were generated by AI from the video transcript.