Sealed Classes and Extension Methods
Have you ever been working with someone elses code and needed to add functionality to a class but the code author has unkindly created their class as sealed?
Not nice eh? I have seen colleagues working with such controls in asp.net and hooking into the rendered html and modifying that just in time with string manipulation!
Thers is a neater way of extending such sealed classes and under the hood its all smoke and mirrors but it looks good and works well and that's all that matters.
What I am talking about is Extension methods.
Extension methods allow you to seemingly add new methods to existing classes so lets look at some examples and see how this works.
Consider the following class:
This class is sealed but suppose we wanted to give our person some musical abilities and enable him to play the piano.
Well normally we might create a sub class called PianoPlayer which inherited Person and simply added a PlayPiano method or two. Not possible when the class is sealed though. Therefore there is some trickery built into the compiler which allows us to achieve the same kind of result even though the class is sealed.
What we need to do is write a static class as follows:
So what we do then is create a new class with a sensible name - a name which describes what abilities we are adding. The class has to be static. The static keyword when used with a class just means that the class contains nothing but static members and so you cannot create an instance of this.
We then write the methods we require to be added to our sealed class. These also need to be static and the first parameter of the method must be the type we are extending. It must also be preceded with a "this" keyword. The p in our example is of course just a variable name.
And that is all we need to do. We can now run this code:
The output from running this will then look like this:
And if we look at our intellisense in Visual Studio we see the following:
So our class is behaving just as if we really have given it new methods. Now I'm pretty sure that under the hood there is some smoke and mirrors going off but that doesn't really matter as long as it works.
We can even add these methods to intrinsic classes. Lets give musical abilities to a SqlConnection object! Microsoft have made this class sealed so we can't extend it but with extension methods its easy - we just add another method to our static MusicAbilities class which refers to a SqlConnection as follows:
We can then run this:
And that will work fine.
Now supposing our method needs to interact with other class members? Well we can do this since our extension method receives a reference to the class we are extending. For example we can do this:
So this works fine and we get the following output:
However there is a snag. Consider the following code:
This code won't even compile as it says that:
Changing this to protected too gives the same result but with an extra error message since declaring a protected field in a sealed class makes no sense! So our reference passed in to our extension method appears to be just a normal reference. In other words our extension method is not really running in the context of the actual sealed class otherwise it would be able to access the legs field. So I guess this is the smoke and mirrors I was hinting at.
So in summary Extension methods can be useful but should generally be a last resort and only used with sealed classes. If a class is not sealed then simply sub class it. You can also consider extending a class using composition but that will be in another article.