Why don't structs support inheritance?
Object-Oriented Design practice on Codemia
Turn requirements into classes, and defend the design, on the problems that come up in OOD rounds.
Introduction
This question is language-specific, which is why it causes confusion. In C++, struct does support inheritance because it is almost the same construct as class. In C#, struct is a value type, and user-defined struct inheritance is intentionally disallowed.
First Clarify the Language
In C++, the difference between struct and class is mostly the default access level. Inheritance works normally:
So if your mental model comes from C++, the premise of the question is false.
In C#, the story is different. A struct implicitly derives from System.ValueType, cannot derive from another struct or class, and cannot be a base type for other structs or classes.
Why C# Structs Avoid Inheritance
C# structs are designed around value semantics. Copying a struct copies the value. That makes them useful for small data carriers like coordinates, ranges, and timestamps.
Inheritance clashes with that model for several reasons.
Fixed Size Matters
The runtime wants the size of a value type to be known by its declared type. If one struct could inherit from another and add fields, assignment and storage would become much harder to reason about because different "versions" of the value could have different sizes.
Copying Would Be More Error-Prone
When a value is copied, developers expect the whole value to move with it. In an inheritance hierarchy, the language would need rules for base-value copying, slicing, and conversions. Those rules are already subtle in object-oriented code; adding them to value types makes the model harder, not simpler.
Layout and Performance Would Suffer
Value types are meant to stay lightweight. They are commonly embedded inside arrays, other objects, and generic containers. Keeping them simple helps the runtime optimize storage and copying. Allowing arbitrary inheritance would complicate layout and undermine those benefits.
What C# Lets You Do Instead
C# structs can implement interfaces, which gives you polymorphism without building a value-type inheritance tree.
This keeps the data flat and predictable while still allowing shared behavior through an interface contract.
Use Composition Instead of Inheritance
If you want to "extend" a struct, wrap it inside another type instead of inheriting from it.
Composition is usually clearer anyway. It says directly that one value contains another value, instead of implying an "is-a" relationship that may not really exist.
Reference Types Solve a Different Problem
If you truly need inheritance, virtual dispatch, and substitution through a base type, you probably want a class. That is not a limitation of structs so much as a sign that you are asking for reference-type behavior.
This rule helps API design. A good struct is typically:
- small
- immutable or close to it
- logically a single value
- free of deep inheritance concerns
Once the type becomes large, stateful, or polymorphic, a class is usually the cleaner choice.
Common Pitfalls
- Assuming all languages treat
structthe same way. C++ and C# do not. - Using mutable structs for complex models. Copies become hard to track and bugs get subtle.
- Reaching for inheritance when composition expresses the relationship better.
- Boxing structs through interfaces without realizing there may be allocation and copying costs.
- Treating structs as "always on the stack." Storage details depend on usage, not only on the keyword.
Summary
- In C++, structs do support inheritance.
- In C#, structs do not support user-defined inheritance because they are value types.
- Value semantics, fixed layout, and predictable copying are the main reasons behind the restriction.
- C# structs can still implement interfaces for shared behavior.
- When you want to extend a struct, composition is usually the right tool.
Related reading
- Why exactly isn't MEF a DI/IoC container?
- Why is 0 a type in Microsoft Intermediate Language MSIL?
- Why is IoC / DI not common in Python?
- Why is my Spring @Autowired field null?
- Why is there no multiple inheritance in Java, but implementing multiple interfaces is allowed?
- Why is Thread not an abstract class and start not final?
- Why no ICloneableT?
- Why not inherit from ListT?

OOD Fundamentals
Master object-oriented design from first principles, SOLID, design patterns, and classic interview problems with hands-on coding.
View the courseTrack what you have practised
A free account saves your progress, solutions and study plan across every problem on Codemia.
Object-Oriented Design practice on Codemia
Turn requirements into classes, and defend the design, on the problems that come up in OOD rounds.