Why all your classes should be sealed by default in C#

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
hello everybody i'm nick and in this video we're going to take a look at the sealed keyword in c-sharp and explain why it is a keyword you should be applying to every single one of your classes with some exceptions that i will be talking about in this video to gain the benefits of doing so if you like a lot of content and you want to see more make sure you subscribe during the summification bell and for more training check out nicktraps.com all right so let me show you what i have here and first we need to understand what we will be talking about so first i'm going to create a new class over here and call that test types because we will be running some tests here to demonstrate not only the functional aspect of the keyword but also the performance aspect because believe it or not it is a huge focus of the dotnet team the dotnet team at this point by default is applying the silk keyword on every internal class that they have they retroactively went and they changed their existing code and also most of the new public ones are sealed by default and it's a very specific reason why they do that let me just add a few types here to demonstrate what the seal keyword is and what it is doing so first we have this base class over here with a couple of virtual methods and now every class by default is open to inheritance so if i wanted i can go ahead and make a class that extends the space class so i have something like this i have an open class that extends the base class and in this case i'm overriding both of these methods however i can also have a closed or sealed class to do that i'm just going to create the same thing as an open class and i'm going to go ahead and apply the sealed keyword and now i cannot go here and say public class extend the extended class and try to extend the sealed class it just doesn't allow me to do that it says that hey you cannot inherit from a sales class so sealed is preventing me to inherit any further now in my opinion this is a flaw in the design of the language it shouldn't be that you explicitly close your classes sealed your classes instead it should be that they are sealed by default and you explicitly open them up this is something that kotlin does in kotlin everything is closed by default it is sealed by default and you have to specify public open class to allow it to be inherited and it makes sense because you want things to be inherited if they're designed to be inherited not everything should be inherited by default this is a bit of a flawed design and since it was something that was there since version one they couldn't really change that and this isn't a niche idea or a new concept in programming or c-sharp someone you might be very familiar with has actually talked about this in a stack overflow post all the way back in 2008 drumroll yes it is actually just john skid of course it is john skit so all the way back in 2008 someone asked why are we doing this why aren't classes sealed by default and he explained he thinks it's a mistake it shouldn't be like that he knows at least a couple of people in the design team that are uh backing him up in this idea and i think he mentions eric lippert and cyrus now it doesn't matter this is 13 years ago it's a long time ago but this idea that everything should be sealed by default is not new it's been like this for a long long time and i'm pretty sure that if you ask more of the c-sharp language designers at this point they would agree with this idea because it makes sense because once something is open for extension then changing that aspect of the class is a breaking change so if you're building a library and you didn't close or seal something when you pushed it out then you cannot take that away without having to create a new major version now this is great and all but it is not why people like steven tobe has been going around sealing every internal class in the dotnet sdk and runtime the reason why they've been doing that is because of performance and believe it or not there is a performance difference in non-sealed and sealed classes and if you are doing that on the sdk level or the runtime level where well everything runs on then even though it's a small performance gain it will actually add up to every service that is using.net let's go ahead and see what those differences are we're going to go ahead and add benchmark.net in this project here we go i'm going to install that and i'm going to create a benchmarks class and add my memory diagnoser because i want to know what's happening with memory now spoiler alert not much but i still want to show you that this is the case and then we can start writing our benchmarks we're going to start with the three classes the base class the open class and the seed class all that is over here and first we just want to take a look at invoking those methods is there a difference between calling the non-sealed class over here and the sealed class here so we're going to go ahead and add those benchmarks so first we have the two void methods so open class void method call and sealed class void method call and i'm going to go ahead and add the open int method call as well and then add something just to show some differentiation that i'm doing something with this call basically and for now that's it all i'm going to do then is go in the program.cs say benchmarks or or benchmark runner actually and then benchmarks here here we go and i'm just going to run those four tests and see what we get everything is in release mode so it will be running in the optimized code version and this is running on dot net seven rc two at this point all right so results are back and let's see what we have here so the open avoid method point two of a nanosecond again we're talking about super super small numbers but you have to understand the differences and the sealed void is 38 times faster than the open void just by sealing the thing that wasn't supposed to be inherited in the first place so that's a big increase but then you have the open int method and the sealed end and this is a thousand times faster that's a lot so you have to understand that even though you know we're talking about very very small levels of performance very small numbers it is still a lot between the two cases and it isn't something you have to really put effort in if something is internal or private just seal it by default you can change it if you ever need to extend it and your public api obviously don't break anything that is public already if you have consumers but if you want you can and you're gonna gain some benefits now this is not the only thing that you're gonna get a benefit on i'm gonna comment this out and i'm going to add a few more benchmarks for example if you have ease check so you have a base class and then you say is it open class or is it sealed class then those checks both the is and the as will be faster how much faster well let's run these benchmarks and see how much faster so results are back and let's see what we have here so the open the ease check 1.6 nanoseconds the sealed version is check 0.1 so 10 times faster just by sealing it and it doesn't end there i'm gonna go ahead and comment this out and i'm going to bring in a couple of arrays this has sealed classes and it only has one item and same thing with the open class so we're gonna have an array of each type and i'm gonna go ahead and add one benchmark for each where the only thing i'm doing is i'm storing something in this array so i'm gonna go ahead and run that and once the results are back explain why they are the way they are so results are back and let's see what we have here so as you can see the open one 2.3 nanoseconds the sealed one 1.6 not quite as big of a performance difference but it is there and the reason for that is because arrays of that type now don't have to have a covariance check when you're setting the value so they can be faster the last thing i want to show you in terms of performance has to do with spans and a very implicit operator from an array to a span so the benchmark would look something like this this is where we're getting an array the same arrays as before and we convert them into a span to operate of them and in a in a different way and with that i'm going to go ahead and launch these tests and see what's happening so results are back and let's see what we have here so as you can see the open one that's converted to a span 0.2 nanoseconds the reason for that happening is because there is no longer a need to validate the type coming in matches the type of the generic type of the span so that's why it's so fast now i'm going to go ahead and uncomment all that in case you want to grab the code and do something with it but i want to pull up an issue on github from the dotnet repo to show you that this is something that is getting a lot of attention and in dot net seven we're getting a special analyzer to look for these types of cases where you can convert something into a shield and even warn you and hint you or suggest to you that you probably should change that to a sealed class instead so this is the github issue on the runtime it is made by steven tobe of course the master of performance in the dotnet team and all of these things are touched on in this video are here i'm going to put a link of the issue in the description in case you want to grab it and take a look at how things are faster even on um jit asm level so i'm going to scroll all the way down over here and show you that yes this is an analyzer they are adding and in fact if i look for the number it should be ca 1852. here you go so this now the seal internal or private rules has been added in the main branch and it's something you can enable in dot net seven in fact i'm gonna go ahead and go back to the project and create a new file over here a dot editor config file i'm going to paste this to treat this specific code ca1852 as a warning so if i go ahead and i build now the analyzer will kick in and say hey this should probably be sealed in this case it's talking about the program.cs which is internal now obviously we cannot change that but if i go back and i change everything let me just go ahead and comment this out for now so go to test types and change these to internal so internally here internal here and internally hero if i go ahead and i say build i'm going to get a warning on this open class now this warning pops up saying hey open class can be sealed because it has no subtypes in this containing assembly and it's not externally visible so nothing technically can inherit it so why don't you just change that to seal then the moment you do that it goes away now again in my opinion you shouldn't just stick to internal types you should also see public types unless that public type is specifically made to be inherited from if it is not seal it you're getting performance and your code is better because no one that you don't want to inherit the type will be able to do so you can always open up something in the future if there is a need for that but you shouldn't really do it by default the default behavior should be it should be sealed by default well that's all i have for you folks thank you very much for watching special thanks to my patreons making videos possible if you want to support me as well you're going to find the description down below leave a like if you like this video subscribe my channel like sharing the bell as well and i'll see you in the next video keep coding you
Info
Channel: Nick Chapsas
Views: 82,425
Rating: undefined out of 5
Keywords: Elfocrash, elfo, coding, .netcore, dot net, core, C#, how to code, tutorial, development, software engineering, microsoft, microsoft mvp, .net core, nick chapsas, chapsas, dotnet, .net, seal, sealed keyword, c# seal class, c# seal, inheritance, c# inheritance, composition over inheritance, Why almost all your classes should be sealed in C#
Id: d76WWAD99Yo
Channel Id: undefined
Length: 11min 43sec (703 seconds)
Published: Mon Sep 12 2022
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.