Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Multiple Inheritance in C#

People also ask

Is multiple inheritance possible in C++?

Unlike many other object-oriented programming languages, C++ allows multiple inheritance. Multiple inheritance allows a child class to inherit from more than one parent class.

What is meant by multiple inheritance?

You can derive a class from any number of base classes. Deriving a class from more than one direct base class is called multiple inheritance.

What is multiple inheritance and multilevel inheritance?

The key difference between Multiple and Multilevel Inheritance is that Multiple Inheritance is when a class inherits from many base classes while Multilevel Inheritance is when a class inherits from a derived class making that derived class a base class for a new class.


Consider just using composition instead of trying to simulate Multiple Inheritance. You can use Interfaces to define what classes make up the composition, eg: ISteerable implies a property of type SteeringWheel, IBrakable implies a property of type BrakePedal, etc.

Once you've done that, you could use the Extension Methods feature added to C# 3.0 to further simplify calling methods on those implied properties, eg:

public interface ISteerable { SteeringWheel wheel { get; set; } }

public interface IBrakable { BrakePedal brake { get; set; } }

public class Vehicle : ISteerable, IBrakable
{
    public SteeringWheel wheel { get; set; }

    public BrakePedal brake { get; set; }

    public Vehicle() { wheel = new SteeringWheel(); brake = new BrakePedal(); }
}

public static class SteeringExtensions
{
    public static void SteerLeft(this ISteerable vehicle)
    {
        vehicle.wheel.SteerLeft();
    }
}

public static class BrakeExtensions
{
    public static void Stop(this IBrakable vehicle)
    {
        vehicle.brake.ApplyUntilStop();
    }
}


public class Main
{
    Vehicle myCar = new Vehicle();

    public void main()
    {
        myCar.SteerLeft();
        myCar.Stop();
    }
}

Since multiple inheritance is bad (it makes the source more complicated) C# does not provide such a pattern directly. But sometimes it would be helpful to have this ability.

C# and the .net CLR have not implemented MI because they have not concluded how it would inter-operate between C#, VB.net and the other languages yet, not because "it would make source more complex"

MI is a useful concept, the un-answered questions are ones like:- "What do you do when you have multiple common base classes in the different superclasses?

Perl is the only language I've ever worked with where MI works and works well. .Net may well introduce it one day but not yet, the CLR does already support MI but as I've said, there are no language constructs for it beyond that yet.

Until then you are stuck with Proxy objects and multiple Interfaces instead :(


I created a C# post-compiler that enables this kind of thing:

using NRoles;

public interface IFirst { void FirstMethod(); }
public interface ISecond { void SecondMethod(); }

public class RFirst : IFirst, Role {
  public void FirstMethod() { Console.WriteLine("First"); }
}

public class RSecond : ISecond, Role {
  public void SecondMethod() { Console.WriteLine("Second"); }
}

public class FirstAndSecond : Does<RFirst>, Does<RSecond> { }

You can run the post-compiler as a Visual Studio post-build-event:

C:\some_path\nroles-v0.1.0-bin\nutate.exe "$(TargetPath)"

In the same assembly you use it like this:

var fas = new FirstAndSecond();
fas.As<RFirst>().FirstMethod();
fas.As<RSecond>().SecondMethod();

In another assembly you use it like this:

var fas = new FirstAndSecond();
fas.FirstMethod();
fas.SecondMethod();

You could have one abstract base class that implements both IFirst and ISecond, and then inherit from just that base.


With C# 8 now you practically have multiple inheritance via default implementation of interface members:

interface ILogger
{
    void Log(LogLevel level, string message);
    void Log(Exception ex) => Log(LogLevel.Error, ex.ToString()); // New overload
}

class ConsoleLogger : ILogger
{
    public void Log(LogLevel level, string message) { ... }
    // Log(Exception) gets default implementation
}