Most people’s first try at multiple inheritance in C# looks like class Thermostat : Device, WifiModule. It won’t compile. The .NET 10 compiler stops with CS1721, because a C# class can have only one base class.
Quick answer: keep one base class and implement as many interfaces as you need: class Thermostat : Device, INetworked, ISchedulable. When you need shared code, not just a contract, use default interface methods or composition. I ran each snippet on .NET 10.
Why Doesn’t C# Support Multiple Inheritance of Classes?
Here’s the exact code I see in questions all the time. A smart thermostat for an Austin, Texas installer is a Device and it has Wi-Fi, so it inherits from both:
var hallway = new Thermostat();
class Device { public string Serial { get; init; } = "TX-1042"; }
class WifiModule { public void Connect() { } }
class Thermostat : Device, WifiModule { } // two base classes
Output:
C:\DotNetDemo\MultiInheritDemo\TwoBases.cs(6,28): error CS1721: Class 'Thermostat' cannot have multiple base classes: 'Device' and 'WifiModule'
The build failed. Fix the build errors and run again.

The reason is the diamond problem. If Device and WifiModule both inherited a Reset() from a shared parent and each changed it, which version would the thermostat run? And which copy of the parent’s fields would it hold?
C++ answers that with virtual base classes and scope rules. C# avoids it: one base class for state and code, any number of interfaces for contracts. The single chain is covered in my guide to inheritance in C#.
How to Achieve Multiple Inheritance in C# with Interfaces
An interface in C# is a contract with no instance fields. A class lists one base class first, then any interfaces after the comma, and must implement every member they declare. Same thermostat, fixed:
var hallway = new Thermostat { Serial = "TX-1042" };
hallway.Connect("HomeNet-Austin");
hallway.SetSchedule(68, 76);
Console.WriteLine($"Device: {hallway is Device}");
Console.WriteLine($"INetworked: {hallway is INetworked}");
Console.WriteLine($"ISchedulable: {hallway is ISchedulable}");
interface INetworked { void Connect(string network); }
interface ISchedulable { void SetSchedule(int heat, int cool); }
class Device { public string Serial { get; init; } = ""; }
class Thermostat : Device, INetworked, ISchedulable
{
public void Connect(string network) =>
Console.WriteLine($"{Serial} joined {network}");
public void SetSchedule(int heat, int cool) =>
Console.WriteLine($"Heat {heat} F, cool {cool} F");
}
Output:
TX-1042 joined HomeNet-Austin
Heat 68 F, cool 76 F
Device: True
INetworked: True
ISchedulable: True

Thermostat TX-1042 joined HomeNet-Austin, took a 68/76 schedule, and all three type checks print True for Device, INetworked and ISchedulable. That’s the polymorphism you wanted from multiple inheritance.
Note: the base class must come first in the list. Interfaces can also inherit from several other interfaces, e.g. interface ISmartThermostat : INetworked, ISchedulable { }.
Default Interface Methods and Multiple Inheritance (C# 8+)
Plain interfaces only describe behavior. Since C# 8, an interface member can carry a body, so you can share code across classes without a common base class. Same thermostat, two interfaces that each ship a default Describe():
var hallway = new Thermostat();
INetworked net = hallway;
ISchedulable plan = hallway;
Console.WriteLine(net.Describe()); // default body from INetworked
Console.WriteLine(plan.Describe()); // default body from ISchedulable
// hallway.Describe(); // CS1061: Thermostat doesn't inherit default bodies
interface INetworked { string Describe() => "Networked over Wi-Fi"; }
interface ISchedulable { string Describe() => "Runs a weekday schedule"; }
class Thermostat : INetworked, ISchedulable { }
Output:
Networked over Wi-Fi
Runs a weekday schedule
Two things surprise people here. First, Thermostat compiles even though both interfaces have a Describe() body, because the two members are unrelated. Second, the class doesn’t inherit those bodies.
You call a default member through an interface reference. Uncomment hallway.Describe(); and the build fails with CS1061, which I checked on .NET 10. Interfaces still can’t hold instance fields, so defaults can’t keep per-object state.
The Diamond Problem with Default Interface Methods (CS8705)
Default methods bring a small diamond back. Give ISmartDevice a default Status(), let IWifi and IZigbee both override it, and implement both:
var hallway = new Thermostat();
interface ISmartDevice
{ string Status() => "Device online"; }
interface IWifi : ISmartDevice
{ string ISmartDevice.Status() => "Wi-Fi connected"; }
interface IZigbee : ISmartDevice
{ string ISmartDevice.Status() => "Zigbee paired"; }
class Thermostat : IWifi, IZigbee { } // which Status() wins?
Output:
C:\DotNetDemo\MultiInheritDemo\Diamond.cs(10,20): error CS8705: Interface member 'ISmartDevice.Status()' does not have a most specific implementation. Neither 'IWifi.ISmartDevice.Status()', nor 'IZigbee.ISmartDevice.Status()' are most specific.
The build failed. Fix the build errors and run again.

The compiler refuses to guess which override you meant. The fix is to give the class its own implementation, which is always the most specific one:
ISmartDevice hallway = new Thermostat();
Console.WriteLine(hallway.Status());
interface ISmartDevice
{ string Status() => "Device online"; }
interface IWifi : ISmartDevice
{ string ISmartDevice.Status() => "Wi-Fi connected"; }
interface IZigbee : ISmartDevice
{ string ISmartDevice.Status() => "Zigbee paired"; }
class Thermostat : IWifi, IZigbee
{
// the class's own member is the most specific one
public string Status() => "Wi-Fi connected, Zigbee paired";
}
Output:
Wi-Fi connected, Zigbee paired
Calling Status() through an ISmartDevice reference now prints the class’s text. It’s the same rule as method overriding in C#: the most derived implementation runs.
Explicit Interface Implementation When Two Interfaces Clash
Sometimes two interfaces declare the same signature with different meanings. The US wall display wants Fahrenheit, and a cloud API wants Celsius. Explicit interface implementation lets one class answer both:
var hallway = new Thermostat(72);
var f = ((IFahrenheit)hallway).Read();
var c = ((ICelsius)hallway).Read();
Console.WriteLine($"Wall display: {f} F");
Console.WriteLine($"Cloud API: {c} C");
// hallway.Read(); // CS1061: needs an interface
interface IFahrenheit { double Read(); }
interface ICelsius { double Read(); }
class Thermostat(double fahrenheit)
: IFahrenheit, ICelsius
{
double IFahrenheit.Read() => fahrenheit;
double ICelsius.Read() =>
Math.Round((fahrenheit - 32) / 1.8, 1);
}
Output:
Wall display: 72 F
Cloud API: 22.2 C

The same object returned 72 F and 22.2 C. Explicit members have no access modifier and don’t show up on the class itself, so hallway.Read() won’t compile. That keeps the public surface clean, which ties into encapsulation in C#.
Composition Instead of Multiple Inheritance in C#
Interfaces give you the types; composition gives you reusable code with state. Instead of inheriting from WifiModule, the thermostat has a radio and a scheduler, and delegates to them:
var radio = new WifiRadio("HomeNet-Austin");
var hallway = new Thermostat("Hallway", radio,
new Scheduler(dayF: 72, nightF: 66));
hallway.Connect();
hallway.Tick(7);
hallway.Tick(23);
class WifiRadio(string network)
{ public string Join() => $"joined {network}"; }
class Scheduler(int dayF, int nightF)
{ public int TargetFor(int hour) =>
hour is >= 6 and < 22 ? dayF : nightF; }
class Thermostat(string room, WifiRadio radio,
Scheduler plan)
{
public void Connect() => // delegate to the radio
Console.WriteLine($"{room} {radio.Join()}");
public void Tick(int hour) => Console.WriteLine(
$"{hour}:00 -> {plan.TargetFor(hour)} F");
}
Output:
Hallway joined HomeNet-Austin
7:00 -> 72 F
23:00 -> 66 F

At 7:00 the target is 72 F, and at 23:00 it drops to 66 F. The radio and scheduler are plain objects passed to the primary constructor, so you can swap a Zigbee radio in without touching Thermostat.
Pro Tip: combine both ideas. Let the class implement INetworked and forward the call to a private radio field. That’s how the decorator and strategy patterns get multiple-inheritance-like reuse.
Multilevel vs Multiple Inheritance in C#
You’ll see these mixed up in interviews. Multilevel inheritance is a chain, and C# allows it as deep as you like, because every class still has exactly one parent:
var hallway = new Thermostat();
for (Type? t = hallway.GetType(); t is not null; t = t.BaseType)
Console.WriteLine(t.Name);
class Device { }
class NetworkedDevice : Device { } // level 2
class Thermostat : NetworkedDevice { } // level 3: still one base class each
Output:
Thermostat
NetworkedDevice
Device
Object
| Multilevel | Multiple | |
|---|---|---|
| Shape | A chain: Device > NetworkedDevice > Thermostat | One class, two or more parents |
| Classes in C# | Allowed | Not allowed (CS1721) |
| Interfaces in C# | Allowed | Allowed |
| Diamond risk | None | Only with default interface methods (CS8705) |
Every chain ends at Object, as the output shows. Mark a middle class abstract when it should never be created on its own; my abstract class in C# guide covers that.
Can a Struct Implement Multiple Interfaces in C#?
Yes. A struct can’t inherit from a class or another struct (try it and you get CS0527, “Type ‘Device’ in interface list is not an interface”), but it can implement any number of interfaces:
var readings = new List<Reading> { new(72.5), new(68.0), new(70.1) };
readings.Sort(); // uses IComparable<Reading>
Console.WriteLine(string.Join(", ", readings));
Console.WriteLine($"Equal: {readings[0] == new Reading(68.0)}"); // IEquatable<Reading> from the record
readonly record struct Reading(double F) : IComparable<Reading>
{
public int CompareTo(Reading other) => F.CompareTo(other.F);
public override string ToString() => $"{F:0.0} F";
}
Output:
68.0 F, 70.1 F, 72.5 F
Equal: True
The readings sorted to 68.0, 70.1 and 72.5 F through IComparable<Reading>, and the record struct added IEquatable<Reading> for free. Assigning a struct to an interface variable boxes a copy, as I show in boxing and unboxing in C#.
Common Multiple Inheritance Errors and How to Fix Them
| Error | What triggers it | Fix |
|---|---|---|
| CS1721 | Two classes in a class’s base list | Keep one base class; turn the other into an interface or a field |
| CS0527 | A class in a struct’s or interface’s base list | Implement interfaces only |
| CS0535 | A listed interface member isn’t implemented | Implement it, or mark the class abstract |
| CS8705 | Two interfaces override the same default member | Implement the member in the class |
| CS1061 | Calling a default or explicit member on the class variable | Cast to the interface first |
Interface, Abstract Class or Composition: Which Replaces Multiple Inheritance?
My rule on client projects: use a base class for the one “is-a” relationship that shares state, interfaces for every capability on top, and composition when you need to reuse code from more than one place.
Reach for default interface methods mainly to add a member to a published interface without breaking implementers. For the bigger design picture, abstraction in C# and the four OOP pillars in C# are good next reads.
If you’re working through the rest of the object-oriented side of C#, these fit well:
- Split one class across files with partial classes
- Give one method several signatures with overloading
- Pick between a struct and a class
- Pass behavior around with delegates
Frequently Asked Questions
Does C# support multiple inheritance?
Not for classes. A C# class can inherit from only one base class, but it can implement any number of interfaces, and an interface can inherit from several interfaces.
How do you achieve multiple inheritance in C#?
Inherit one base class and implement several interfaces, for example class Thermostat : Device, INetworked, ISchedulable. Use default interface methods or composition when you also need shared code.
What is the diamond problem in C#?
It’s the ambiguity when a type gets the same member from two parents. Classes avoid it by allowing one base class. With default interface methods it shows up as error CS8705, which you fix by implementing the member in the class; see interface implementation errors on Microsoft Learn.
Can an interface inherit from multiple interfaces in C#?
Yes. interface ISmartThermostat : INetworked, ISchedulable { } is valid, and a class that implements it must implement the members of all three interfaces.
Why can’t I call a default interface method on my class?
Default interface members aren’t inherited by the class. Call them through an interface reference, such as ((INetworked)hallway).Describe(), or implement the member in the class.
Is multilevel inheritance the same as multiple inheritance?
No. Multilevel is a chain where each class has one parent (Device, NetworkedDevice, Thermostat), and C# allows it. Multiple means one class with two parents, which C# allows only through interfaces.
Bijay Kumar is a renowned software engineer, accomplished author, and distinguished Microsoft Most Valuable Professional (MVP) specializing in SharePoint. With a rich professional background spanning over 15 years, Bijay has established himself as an authority in the field of information technology. He possesses unparalleled expertise in multiple programming languages and technologies such as ASP.NET, ASP.NET MVC, C#.NET, and SharePoint, which has enabled him to develop innovative and cutting-edge solutions for clients across the globe. Read more…