Share via


Why doesn't C# support multiple inheritance?

This answer is from Chris Brumme via the following post. I've copied the text in here in case the post disappears.

***

There are a number of reasons we don't implement Multiple Implementation Inheritance directly. (As you know, we support Multiple Interface Inheritance).

However, I should point out that it's possible for compilers to create MI for their types inside the CLR. There are a few rough edges if you go down this path: the result is unverifiable, there is no interop with other languages via the CLS, and in V1 and V1.1 you may run into deadlocks with the OS loader lock. (We're fixing that last problem, but the first two problems remain). The technique is to generate some VTables in RVA-based static fields. In order to deposit the addresses of managed methods (which probably haven't been JITted yet), you use the VTFixup construct. This construct is a table of triplets. The triplets consist of a token to a managed method, an address in your image that should be fixed up (in this case, a slot of the VTable you are creating in the RVA-based static), and some flags. The possible flags are described in corhdr.h and they allow you to specify 32- vs. 64-bit pointer sizes, control over virtual behavior, and whether some reverse-PInvoke behavior should be applied in the form of a thunk that eventually dispatches to the managed method. If we are performing an unmanaged->managed transition, you also have some control over which AppDomain should be selected for us to dispatch the call. However, one of these options (COR_VTABLE_FROM_UNMANAGED_RETAIN_APPDOMAIN) doesn't exist in V1. We added it in V1.1.

There are several reasons we haven't provided a baked-in, verifiable, CLS-compliant version of multiple implementation inheritance:

1. Different languages actually have different expectations for how MI works. For example, how conflicts are resolved and whether duplicate bases are merged or redundant. Before we can implement MI in the CLR, we have to do a survey of all the languages, figure out the common concepts, and decide how to express them in a language-neutral manner. We would also have to decide whether MI belongs in the CLS and what this would mean for languages that don't want this concept (presumably VB.NET, for example). Of course, that's the business we are in as a common language runtime, but we haven't got around to doing it for MI yet.

2. The number of places where MI is truly appropriate is actually quite small. In many cases, multiple interface inheritance can get the job done instead. In other cases, you may be able to use encapsulation and delegation. If we were to add a slightly different construct, like mixins, would that actually be more powerful?

3. Multiple implementation inheritance injects a lot of complexity into the implementation. This complexity impacts casting, layout, dispatch, field access, serialization, identity comparisons, verifiability, reflection, generics, and probably lots of other places.

It's not at all clear that this feature would pay for itself. It's something we are often asked about. It's something we haven't done due diligence on. But my gut tells me that, after we've done a deep examination, we'll still decide to leave the feature unimplemented.

Comments

  • Anonymous
    March 07, 2004
    For me, MI is interesting when:
    - you want to inherit the default behavior of an interface
    - you want to have an object which can interact with two libraries.

    If I could specify within an attribute the default implementaiton for an interface, that would be great.

  • Anonymous
    April 07, 2004
    From theoratical point of view MI is an nessecity. In many situations we need to make a decision whether to define an interface or an abstract class with same signatures. An interface and abstract class are exactly the samething except abstract class would allow some non-abstract members which can act as shared common code plus it can have protected overridable members. If MI is not supported then I have to really think whether to put my signatures in interface or an abstract class and decision would be based on limited knowledge whether client classes could have been already been derived from other class. So in nutshell, if there is no MI, my ability to share common code along with abstract members gets limited.

  • Anonymous
    May 12, 2004
    If I run into the problem of sharing common code as Shital described above, I use a mix of multiple interfaces and the Bridge Pattern. The class that needed to have multiple inheritance implements multiple Interfaces. Then, that same class will contain the Concrete Abstraction of the Bridge.

  • Anonymous
    May 14, 2004
    Personally, I would love mixins, as it would most elegantly address many of my issues with the implementation inheritance system of the CLR.

    Also, I have the gut feeling that mixins would fit better into the philosophy of the .Net framework; in one swoop it would address the lack of multiple inheritance and the inability of doing template meta-programming ATL-style with the CLR generics.

    Besides, I would love the AOP aspect [pun] of mixins; I imagine the mixin implementation would function better, smoother, and perform better than messing with Context bound objects and message sinks…

    Since we are discussing single (implementation) inheritance versus multiple inheritance, what about single dispatch versus multiple dispatch? :-)

  • Anonymous
    May 14, 2007
    PingBack from http://arnulfoperez.com/blog/2007/05/13/do-bemol-y-el-grano-de-cafe/

  • Anonymous
    May 14, 2007
    PingBack from http://arnulfoperez.com/blog/2007/05/13/database-answers/

  • Anonymous
    July 18, 2007
    PingBack from http://michaelsync.net/2007/07/18/weekly-qasw-questions-and-answers-in-software-development/

  • Anonymous
    October 13, 2007
    PingBack from http://michaelsync.net/2007/07/18/weekly-qasw-questions-and-answers-in-software-development

  • Anonymous
    November 05, 2007
    PingBack from http://www.bautforum.com/off-topic-babbling/66682-computer-programming-thread.html#post1105762

  • Anonymous
    January 04, 2008
    Extension Methods - Extension or Confusion?

  • Anonymous
    November 22, 2008
    PingBack from http://megos.wordpress.com/2008/11/22/mehrfachvererbung-2/

  • Anonymous
    October 07, 2009
    In object-oriented programming languages with multiple inheritance and knowledge organization, the diamond problem is an ambiguity that arises when two classes B and C inherit from A, and class D inherits from both B and C. If a method in D calls a method defined in A (and does not override the method), and B and C have overridden that method differently, then from which class does it inherit: B, or C? For example, in the context of GUI software development, a class Button may inherit from both classes Rectangle (for appearance) and Clickable (for functionality/input handling), and classes Rectangle and Clickable both inherit from the Object class. Now if the equals method is called for a Button object and there is no such method in the Button class but there is an overridden equals method in both Rectangle and Clickable, which method should be eventually called? It is called the "diamond problem" because of the shape of the class inheritance diagram in this situation. In this article, class A is at the top, both B and C separately beneath it, and D joins the two together at the bottom to form a diamond shape.

  • Anonymous
    January 15, 2010
    Hi Balaji Birajdar, Your explanation is fantastic. Thanks Sarnendu De

  • Anonymous
    March 29, 2010
    Thanks Sarnendu De You can google for the term 'diamond problem in multiple inheritance' and you will get lots of images for visual representation of the problem which will make your understanding crystal clear.

  • Anonymous
    May 11, 2010
    The diamond problem is extremely easy to solve and you end up with a similar problem with conflicting names when doing multiple interface inheritance.

  • Anonymous
    May 11, 2010
    Also, the complexity argument no longer holds any water as we've added linq, var, extension methods, lamdba expresions, metadata based frameworks, etc... the language is already complicated.

  • Anonymous
    July 07, 2010
    I know this post is old, but I have to say this explanation was great. I've been looking heavily into the design of C# since it's pretty much everything I want from a language (except garbage collection, bleh!) and the reasoning you've given explains quite a bit.

  • Anonymous
    December 23, 2010
    The comment has been removed

  • Anonymous
    June 09, 2011
    Thanks, for thorough answer!

  • Anonymous
    January 23, 2013
    I understand that implementing this is not trivial but the answer of "it's too hard" or "it's too involved" is an impractical. Go big or go home... or at least make better excuses.

  • Anonymous
    July 17, 2013
    hi All, Good stuff, I hope c# doesn't support multiple inheritance, but have stupid doubts, in every class has been inherited from Object Base class. How we accept it hasn't support?

  • Anonymous
    May 11, 2014
    Thanks for the very good explanation . Read more C# interview questions in skillgun.com/.../interview-questions-and-answers

  • Anonymous
    May 19, 2014
    Today I have this difficult task to do, MI is what I was looking for, but ..... Please do something about this

  • Anonymous
    September 04, 2015
    More about multiple inheritance in C# net-informations.com/.../inheritance.htm Dov