Click here to Skip to main content
13,260,181 members (53,161 online)
Click here to Skip to main content
Add your own
alternative version


15 bookmarked
Posted 13 May 2008

Getting Closer to Multiple Inheritance in C# 3.0

, 13 May 2008
Rate this:
Please Sign up or sign in to vote.
How to implement multiple inheritance in C# 3.0


Many people out there may not be impressed or happy about this, but yes, there is a way to simulate multiple inheritance in C# 3.0. And more importantly, it is incredibly simple to implement.

Using the Code

All you require is an interface to use as a marker and some extension methods.

Here, we have the simplest of scenarios, a Logger “class” that any class can “inherit” from.

public interface Logger
public static class LoggerImpl
    public static void Log(this Logger instance, string msg)
    public static void LogError(this Logger instance, string msg)
        Debug.WriteLine(string.Format("ERROR: {0}", msg));

Figure 1. Implementation using the Interface and Extension methods.

public partial class Form1 : Form, Logger
    private void button1_Click(object sender, EventArgs e)
        this.Log("Button1 Clicked");
    private void button2_Click(object sender, EventArgs e)
        this.LogError("Button2 Clicked");

Figure 2. WinForm usage.

public class Car: Vehicle, Logger
    private override void Drive()
        this.Log("I’m driving now!");

Figure 3. Business Object usage.

I don't believe it can get any easier than this. Obviously, you can get much more complex and sophisticated as the solution necessitates. The key is to understand the new feature of C# 3.0, extension methods. I won't go into the specific of this C# feature as it is well documented in many places.

There is one caveat to the implementation which is that you must use the 'this' keyword to access the extension methods from within the class itself. Not a hefty price to pay for this feature.

Points of Interest

As a further example, I've used this approach in ASP.NET for a custom Session handler class (SessionSupport) which leverages generics, constraints and lambdas to manage a specific type of business object derivative. This particular implementation is also aware of the fact that the SessionSupport class is always applied to ASP.NET Page classes and therefore can safely cast the ‘this’ instance parameter to a Page type and access all of the Page specific members. I opted to document this feature using a basic Logger sample to keep things as focused on the issue at hand as possible.

Another approach would be to include a few methods on the interface forcing the consumer base class to implement these functions providing some access to pertinent fields, properties, or methods of the base class and avoiding the blind cast.

Follow Up

I suppose the simplicity of the example has worked against me. :)

In this situation, assuming you wanted every class to expose the Logging methods, as Patrik_J points out, which isn't unreasonable, you could simply add the extension methods to the 'object' class. But that misses the point of the demonstration - my bad.

The ASP.NET Session code that I've applied this technique to is far too complex (and proprietary) for this forum, but I can try to give another example of the usage.

Let’s say, for example, that you want to have an automated security feature that could be applied to a subset of selected Windows controls in a WinForms application.

For example:

public class MyForm : Form, SecurityMgr

The problem is as such; you want a method exposed from certain custom controls called ‘ApplySecurity’ which takes a security token and dynamically enables/disables child controls contained on it. I won't go into the details of how the tokens and controls are related. I'll leave that for another day. You have classes derived from System.Windows.Forms.Form and from System.Windows.Forms.ToolStripContainer and other classes that are derivatives of System.Windows.Forms.Control which contains the Controls property. You obviously don't want to derive a class from Form and from ToolStripContainer and from those others, simply to embed the new method. And then derive your custom Controls from it. Nor would you want to implement ‘ApplySecurity’ as an extension method on all System.Windows.Forms.Control as other classes have no context for this usage. So, at this point, you can apply this pattern.

I hope this adds some clarity to the benefits of this technique.

Polymorphism Addressed - Kinda Short

public interface Logger2 : Logger

public static class Logger2Impl
    public static void LogError(this Logger2 logger, string msg)
        System.Diagnostics.Debug.WriteLine(string.Format("NEW ERROR: {0}", msg));

I've made an attempt to address the polymorphism issue that was mentioned by Nick Darnell.

This solution still needs some thought - but it immediately interested me as it allows for reuse of the 'overridden' method. The code is again fairly straight forward and I'm using the simplest of scenarios to illustrate the point. By simply inheriting a new interface from the existing interface and 'overriding' the method of interest, you can mimic the desired behavior. Now all that is left is to switch your consumer class to derive from Logger2 rather than Logger and you can leverage this custom implementation in other classes (the additional benefit of interest). The actual code in the consumer class or the consumer of the consumer class invokes the LogError and Log methods in the appropriate base/derived classes (LogError in Logger2Impl and Log in LoggerImpl) without knowing the difference.


  • 13th May, 2008: Initial post


This article, along with any associated source code and files, is licensed under A Public Domain dedication


About the Author

United States United States
No Biography provided

You may also be interested in...


Comments and Discussions

GeneralMy vote of 3 Pin
Nick Alexeev19-Sep-14 14:46
memberNick Alexeev19-Sep-14 14:46 
GeneralNot impressed (feedback) Pin
Oleg Shilo26-May-08 15:30
memberOleg Shilo26-May-08 15:30 
GeneralAwfully clever. Pin
Ashaman15-May-08 11:08
memberAshaman15-May-08 11:08 
GeneralHere's a bone...=) Pin
Member 345750613-May-08 11:40
memberMember 345750613-May-08 11:40 
GeneralRe: Here's a bone...=) Pin
Shane Battrick13-May-08 13:02
memberShane Battrick13-May-08 13:02 
QuestionWhat do you win? Pin
Patric_J13-May-08 10:06
memberPatric_J13-May-08 10:06 
AnswerRe: What do you win? Pin
Shane Battrick13-May-08 11:28
memberShane Battrick13-May-08 11:28 
GeneralNot impressed Pin
Nick Darnell13-May-08 8:33
memberNick Darnell13-May-08 8:33 
GeneralRe: Not impressed Pin
Shane Battrick13-May-08 9:18
memberShane Battrick13-May-08 9:18 
GeneralRe: Not impressed Pin
Shane Battrick13-May-08 12:48
memberShane Battrick13-May-08 12:48 
GeneralRe: Not impressed Pin
Nick Darnell13-May-08 13:41
memberNick Darnell13-May-08 13:41 
GeneralRe: Not impressed Pin
Shane Battrick13-May-08 14:56
memberShane Battrick13-May-08 14:56 
GeneralRe: Not impressed Pin
Nick Darnell13-May-08 16:19
memberNick Darnell13-May-08 16:19 
GeneralRe: Not impressed Pin
Shane Battrick13-May-08 17:11
memberShane Battrick13-May-08 17:11 
GeneralRe: Not impressed Pin
S. Senthil Kumar13-May-08 22:28
memberS. Senthil Kumar13-May-08 22:28 
GeneralRe: Not impressed Pin
ttuBrant18-May-09 20:44
memberttuBrant18-May-09 20:44 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

Permalink | Advertise | Privacy | Terms of Use | Mobile
Web03 | 2.8.171114.1 | Last Updated 13 May 2008
Article Copyright 2008 by Audaxis
Everything else Copyright © CodeProject, 1999-2017
Layout: fixed | fluid