Last Updated on June 7, 2022
There are 2 main categories of types in C#: value types and reference types. Structures and classes represent the main types of these 2 categories. Structures are value types and classes are reference types. In this article, we will look at the key differences between these 2: C# struct vs class.
What is a struct?
The struct keyword represents a structure type, which is in fact a value type containing data members and methods. Usually, those data members are simple data types like int, double, bool, or other built-in structures like DateTime.
Declaring a variable of type struct does not require a memory allocation in the heap. A struct variable is allocated directly either in the stack or inside the containing type (i.e. if the variable is a member of a class for example).
Even though it is possible to declare a reference type field or property inside a struct, this is not a common use case. In fact, declaring a reference type member inside a struct, makes it mutable, which is not an ideal use-case for a struct. Therefore, it’s recommended to only put value-type members inside structures.
It’s important to note that in C#, simple data types like int, double, bool, or Datetime are also structures themselves.
For example, here is a struct declaration in C#:
public readonly struct CarFeatures { public bool HasBluetooth { get; init; } public bool HasRearViewCamera { get; init; } public bool HasTractionControl { get; init; } public bool HasHeatedSeats { get; init; } public bool HasBlindSpotMonitoring { get; init; } public bool HasNavigationSystem { get; init; } }
When you pass a struct type as a parameter to a method, a copy of the structure will be created for that method. In other words, a struct type is always passed by value to methods. The same mechanism happens when you assign a structure to a variable or when a struct type is the return value of a method. To keep it simple, structures are always copied by default, like all value types.
What is a class?
The class keyword is one of the most used keywords in object-oriented programming. A class is a reference type that represents a blueprint or schema of an object. For instance, if you need to manipulate objects representing cars in your code, you will create a Car class that contains members and functions (methods) of a car. Basically, an object is just an instance of a class.
For example, here is a class declaration in C#:
public class Car { public string Make { get; init; } public string Model { get; init; } public int NumberOfSeats { get; init; } public int Mileage{ get; init; } public CarFeatures Features { get; init; } //Todo: implement the Drive method public Task Drive() => Task.CompletedTask; }
Creating an instance of a class requires an allocation of memory in the heap to store the data of the newly created object. In addition, the variable referring to that object will contain only a reference to the address of the object in the heap. Since class instances reside in the heap, the garbage collector will collect them at some point in time. Also, contrary to the structure data type, a class instance (i.e an object) is always passed by reference.
C# Struct vs Class: Stack vs Heap
Let’s look at a practical example to show the difference between storing data in the stack versus storing it in the heap. Here is a console application code that uses the Car class and the CarFeatures structure that we created previously.
static void Main(string[] args) { CarFeatures myCarFeatures = new CarFeatures() { HasBluetooth = true, HasRearViewCamera = true, HasTractionControl = true, HasHeatedSeats = true, HasBlindSpotMonitoring = false, HasNavigationSystem = false }; Car myCar = new Car() { Make = "Camry", Model = "Toyota", NumberOfSeats = 5, Mileage = 10000, Features = myCarFeatures }; //TODO: do something with the car }
And the following picture gives you an idea about how the data is stored in memory:

As you can see, the variable myCar contains the reference to the Car object that was created in the heap. And the CarFeatures property of the Car class resides also in the heap, inside the memory allocated for the Car class. On the other hand, the local variable myCarFeatures resides in the stack. This example describes both scenarios: the first scenario where the struct data is in the stack and the second scenario where the struct data is inside the containing type in the heap.
C# Struct vs Class: Key differences
The following table is a summary of the key differences between a struct vs class.
Struct | Class | |
Type | Value type | Reference type |
Parameterless constructor | Not allowed before C# 10. Starting from C# 10, it is now possible to define an explicit parameterlsess constructor in a structure type. C#10 has been released as part of .NET 6 and Visual Studio 2022. | Allowed |
Static constructor | Allowed | Allowed |
Assignation | A new copy of the struct is created. Changes in one variable do not affect the other. | A copy of the reference is created. The two variables will point to the same object in the heap. Changes in one variable affect the other. |
Instantiation | You can instantiate a struct with or without the new operator. Contrary to a class, when you declare a struct variable without the new keyword, the value cannot be null: an instance of the struct will be created will all members set to their default values. | The new operator is used to create an instance of a class. If you declare a variable without instantiating it, the value will be null, which is the default value for reference types. |
Implicit Inheritance | A struct type implicitly inherits from System.ValueType. Also, structs are implicitly sealed. | All .NET classes implicitly inherit from System.Object. |
Explicit Inheritance | Inheritance is not supported. A struct cannot inherit from another struct or a class. Therefore, struct members cannot have the protected or protected internal access modifier. A struct can only implement interfaces. | Allowed |
Abstract keyword on the type | Not Allowed. Struct types cannot be abstract. | Allowed |
Virtual methods | Not allowed | Allowed |
Override keyword | Allowed only to override the System.ValueType’s methods. | Allowed |
C# Struct vs Class: When to use one or the other?
As a C# developer, most of the types that you will declare will be classes. Of course, you will surely use the built-in value types in the .NET framework, but most of the time, you don’t need to declare your own structures.
In a nutshell, here are some of the scenarios where you should use a struct instead of a class:
- The type is an aggregate of value type members only and the data is immutable.
- The footprint of the type in memory is small. In other words, you are manipulating small values.
- You don’t need to box and unbox this type frequently.
The weird case of implementing IDisposable in a struct…
Since struct types can implement interfaces, some developers are tempted to implement the IDisposable interface. Even though the framework does not prevent you from doing it, it’s a very bad practice because the footprint of a struct in the memory should be small and live in the stack. In addition, if you follow Microsoft recommendations, your custom structure should be immutable and should not have a reference to an unmanaged resource.
As a rule of thumb, if you see a structure implementing IDisposable during your code review, then you really need to discuss with the developer to understand the purpose of such implementation. That is to say, in the strong majority of the cases, it’s really not necessary.
I hope you enjoyed this article from our fundamentals series. You can find other articles with the fundamental tag here.
Leave a Reply