.Net Inheritance Hack

When I started this post I found myself writing about the history of inheritance as a technique, of how far back it goes and various languages that supported inheritance long before .Net inheritance came on the scene. Needless to say I scrapped most of that – if you’re here reading this, chances are you don’t need (or want) a history lesson; you’re looking for something new and hopefully useful to do with .Net inheritance. Ok, let’s set the stage then.

The Problem and Solutions

Let’s suppose you’re working on an application where some of the functionality is coming from classes based in assemblies you don’t have the source code too (they’re “secret”). That pretty much describes all .Net applications to some degree since the .Net framework itself meets that description. However, for the purposes of this discussion let’s suppose you’re working with business objects or an API wrapper around remote data.

A common practice when working with 3rd-party libraries, whether locked away in compiled assemblies or not, is to create a sub-class of your own before creating any concrete types. This sub-class “layer” is your extensibility point, it’s where you can easily go back and add methods, fields, or properties that will be available to all other sub-classes and it’s a good practice when thinking in terms of extension points for long-term maintenance.

Sure, since C# v3 (2008) we’ve had Extension Methods as a nifty means of adding methods to classes that we don’t have source to (or to our own classes as an alternative to inserting a new sub-class and re-parenting all derived classes). But what happens when you want the same methods to be available in more than one base class? You can have multiple implementations of those Extension Methods of course, one for each class you want to add the methods to, but wouldn’t it be better if you could somehow just “inherit” those methods into multiple base classes?

This idea of inheritance from multiple parent classes (multiple inheritance) is often looked at as the coolest feature ever…at least by those using languages that don’t support it. C#, as you might know [or guess by now] does not support multiple inheritance. In fact, all across .Net inheritance is of the single-parent variety. The closest we get to it is the ability to reference multiple Interfaces which does give us some of the goodness but we’re still stuck having to add the concrete implementations of the Interface methods to each class. At this point you may be asking yourself why .Net Inheritance doesn’t include this powerful sounding feature. What could MS be thinking?

It’s not all Rainbows and Unicorns

There are some rough edges around the both the concept and the various implementations out there. It’s beyond the scope of this article to go into very much but a lot of challenges have to do with the solution to the “diamond problem” where A is your base, both B and C inherit from A and D inherits from both B and C (multiple inheritance). Now from within concrete D you want to call a method defined in A which may [or may not] have been overridden in B or C. In C++ you overcome the issue by specifying the path you want to take to the base method (e.g. B::A.Foo) but in Python, Java, and others there are different strategies that each result in specific tradeoffs.

So, what does all this have to do with what we started out to do? Since we are working within the confines of .Net Inheritance, how are we going to get our new functionality to show up in multiple classes, with lots of duplicate Extension Methods, and still have those methods respected within the .Net Inheritance framework? Well, that’s where the “hack” part of the topic comes in. Don’t worry, we’re not going to anything particularly dirty and it’s fully supported functionality. In fact, we’ve already discussed all the mechanics involved in this article, but like most articles touching on this subject we haven’t put all the pieces together in a cool new way…until now.

It turns out that you can apply Extension Methods to Interfaces in .Net. Go ahead and let that sink in for a moment…it was a huge “ah-ha!” moment for me when I first learned about it from one of my mentors at Magenic (thanks Douglas!). Like many developers, I had learned about Extension Methods to solve a specific problem and never fully learned all that could be done with it. When I did finally hear about it the topic was really just in passing, we weren’t talking about .Net Inheritance, LINQ, or anything in particular, it was just one of those “hey did you know…” sorts of comments and we moved on. For me though it was an unexpected answer to a puzzle I had been mulling over for quite a while – how to safely “simulate” multiple inheritance in .Net for those cases where it really would be the most elegant solution.

The “Hack”

Ok, so let me spell it out with a really simple example; let’s suppose you have two base classes, A and B, which you’ve inherited into C and D respectively. Life is good until you look at the v2 backlog list and realize that what’s needed is functionality that would be common to both C and D. If you had source for A and B you might be able to create a new common base class and re-parent A and B to use it (C and D, and their progeny, would never need to know). But as luck would have it that path is closed to you. The closest thing you can do in .Net Inheritance at this point is to create a new Interface (E) that represents the implementation of the new features, reference that Interface in both C and D, and of course add the concrete implementation of those features to each class too…crap. Ah, but wait, what was that I said about Extension Methods and Interfaces? Yes, that’s right, you could create an “empty” Interface and a set of Extension Methods attached to that Interface, reference the Interface normally in C and D, and suddenly you’ll find yourself being able to call those methods from both classes! What’s more, if you later sub-class C into G then G will also have the methods picked up from Interface E.

Show Me the Bits

Let’s see what all that looks like in practice. I’ve put together a sample project (available here) that illustrates everything I’ve talked about. The code map [below] for the project shows the class inheritance and how each class contains an implementation of the “ShowName” method.

The implementation in classes C and D also call into their base class:

In the code map you can see the Main method of this Console application calling the methods on C, D, and G, as well as a method named “SaveStuff”. This is the method we’re “injecting” into our class hierarchy by adding it as an Extension Method of the IWorkingExtensions interface [which you can see that ClassC is referencing in addition to its inheritance base class, ClassA].

Looking at the Main method of the Console application itself we can see how this comes together:

And the output from the console, probably not surprising anyone, looks like this:

The only difference to note between the three classes is that the “ShowName” implementation in ClassG doesn’t include a call to base.ShowName() [which ClassC and ClassD both have] so you only see the hello text from ClassG itself. Finally, I wanted to mention that you’ll need to be careful about including the necessary using references in order for all this to work. I know that seems obvious but it may not be intuitive to find that, in my example, you need to include the Extensions reference in both the classes that reference the IWorkingExtensions Interface and the [console] program that’s calling methods on the instances of those classes. Because they’re ultimately calling static Extension Methods they need to be referenced explicitly whenever an Extension Method might be called, even if that appears to be down inside a sub-class that has its own references.

I hope you find this to be a useful new tool in your bag and come away with a deeper understanding of the flexibility of Extension Methods and Interfaces.


Tagged , , , , . Bookmark the permalink.

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.