> For the complete documentation index, see [llms.txt](https://huy312100.gitbook.io/software-development/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://huy312100.gitbook.io/software-development/everything-anyone-should-know/comparison/data-structures/class-vs-struct.md).

# Class vs Struct

Coming to C#, Struct is actually very similar to Class, it is very difficult to distinguish the difference between Struct and Class and when to use Class and when to use Struct.

Similarities between Struct and Class:

* Both cover internal information with member data as fields.
* Both contain methods and properties.
* Both can implement interfaces
* Both have constructor functions
* ...

Differences between Struct and Class:

* Struct's constructor must have parameters
* Struct is a reference data type that is contained in the Stack memory area and Class is a reference data type stored in the Heap memory area
* Struct does not support inheritance from another Class or Struct
* Struct does not support destructor
* ...

Because there are many similarities like that, so Struct is considered a "lightweight Class" and can be used to replace Class in some cases. Therefore, you should consider when planning to create a new class of objects. If in case Struct can meet the requirements, you should use Struct rather than Class because objects created by Struct take less space. more memorable than Class due to referencing.

In basic OOP, there is not much distinction between Structure and Class, but when we go deeper into OOP to implement class libraries that can be inherited and extended later, then we will use Class. more than Structure and will see a clear difference because Class is designed for OOP.

## **Class is Reference Type and Struct is Value Type**

## Stack vs Heap <a href="#stack-voi-heap-0" id="stack-voi-heap-0"></a>

Programs need to use RAM when operating. First, let's remember the concept of allocating and deallocating memory areas

* The program cannot arbitrarily access the memory area but must "ask permission" from the operating system, then the program "owns" this memory area and the operating system ensures that no other program will interfere. This process is called memory allocation`(memory allocation)`
* After using the allocated memory, the program needs to "return" it to the operating system (so another program can use it), this process is called memory reclaiming.`(memory deallocation)`

![](https://images.viblo.asia/534ae64d-a910-481e-aca2-4a29ee598fdf.PNG)

Basically, the memory area of ​​a program has two main types: `Stack`and `Heap`(there are also Global segment and Code segment, both of which are fixed size so we won't discuss it ![😃](https://twemoji.maxcdn.com/v/14.0.2/72x72/1f603.png)).&#x20;

* **Stack memory** : The internal allocation and deallocation process `Stack`will operate in [LIFO](https://en.wikipedia.org/wiki/Stack_\(abstract_data_type\)) style , meaning that data allocated first will be deallocated later, why is that so?

  * **Because the Stack was created to serve the process of calling functions** : for example, a function `A()`calls a function `B()`, then it `A()`starts first `B()`but ends later, then the data in the function `A()`will be allocated first, then `B()`; When revoking, it's the opposite, the internal data `B()`is recalled first, then comes`A()`

  ```csharp
    // Allocate after A()
    // Deallocate before B()
    public void B() { 
        int b = 5;
    }
    // Allocate before B()
    // Deallocate after B()
    public void A() {
        int a = 3;
    }
  ```

  * Therefore, it `Stack`only contains data generated during the function call (aka `local variable`), the data in the function will be recovered after the function ends. However, a program must generate data that is outside the scope of the function `global variable`(not revoked after the function ends).`Heap`
* **Heap memory** : Allocated data will **not have a specific order** , to access internal data `Heap`it is necessary through the address (when allocation is complete, the operating system will return this address)

  * The purpose of Heap is to create data `global variable`, so the above data `Heap`will not be automatically recovered after the end of the function (the recovery process needs to be done by the program itself, but the [Garbage collector](https://learn.microsoft.com/en-us/dotnet/standard/garbage-collection/fundamentals) has done it for us).

  ```csharp
    public class AllocatedClass { }
    public void A() {
     // Variable "a" will not be automatically revoked after A() ends
     // The recovery process will be handled by Garbage collector
      var c = new AllocatedClass();
    }
  ```

Performance and size are notable between `Stack`and `Heap`!

* `Stack`is much smaller in size `Heap`, because the Stack only needs to contain local variables, while the Heap needs to contain all "live" data in the program
* The performance of `Stack`(allocate/reclaim/retrieve) is `Heap` **much** higher , this is obvious because the functions will be called many times in the program
* In addition, [Garbage collector](https://learn.microsoft.com/en-us/dotnet/standard/garbage-collection/fundamentals) is a component that greatly affects the performance of the program, the more data there is, the `Heap`more it will need to be processed.

So the lesson learned is... **Take advantage of the Stack, and limit the Heap as much as possible to temporary values**

## Value type và Reference type <a href="#value-type-va-reference-type-1" id="value-type-va-reference-type-1"></a>

In C# there are 2 data types: [Value type (managed data types)](https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/builtin-types/value-types) and [Reference type (unmanaged data types)](https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/reference-types) , each type will represent a number of data types.

* **Reference type** : **it is the class** (recently there is also [record](https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/builtin-types/record) ), data types when declared as such `Reference type`will **always be on the Heap**
* **Value type** : includes the data types you often see `int`: `float`, , `bool`, `byte`, `char`, `enum`... `struct`( `string`yes `class`), these data can be **located on the Heap or Stack depending on how they are used.**

### Reference type <a href="#reference-type-2" id="reference-type-2"></a>

As said, `class`and `record`will always be on `Heap`no matter whether you declare it is `local variable`good or not`global variable`

```csharp
public class MyClass { }
public record MyRecord { }
void HeapOnly()
{
    // Class/Record instance will always be on the Heap even if it is a local variable
    var onlyHeapClass = new MyClass();
    var onlyHeapRecord = new MyRecord();
}
```

When running the function, `HeapOnly();`it will show that there are 2 data allocated on the Heap\
![](https://images.viblo.asia/2d5bcadf-377a-4c56-9aa6-a34df6f2611d.PNG)

### Value type <a href="#value-type-3" id="value-type-3"></a>

#### Value type ( `int`, `bool`, `struct`, `enum`) will be on the Stack if it belongs `local variable`to a function. <a href="#value-type-int-bool-struct-enum-se-nam-tren-stack-neu-no-la-local-variable-cua-1-ham-4" id="value-type-int-bool-struct-enum-se-nam-tren-stack-neu-no-la-local-variable-cua-1-ham-4"></a>

```csharp
public struct StackOnlyStruct { }
void StackOnly() {
    int stackOnlyInt = 5;
    AnotherStackOnly(stackOnlyInt, ref stackOnlyInt, false);
}
void AnotherStackOnly(int valueParameterWillBeCopiedIntoTheFunction,
    ref int useRefModifierForPassingByReferenceToAvoidCopying, //Pass by reference
    in bool useInModifierForPassingByReferenceAndReadonly)  //Pass by reference and readonly
{
    var stackOnlyStruct = new StackOnlyStruct();
}
```

![](https://images.viblo.asia/489c1bbb-f01c-4980-9ef4-d8647d0893d9.PNG)\
We can see that when calling the function, `StackOnly()`the above will not be allocated `Heap`because all of the above are used `Value type`(the image below shows that there are no instances of the `StackOnlyStruct`above `Heap`)\
. We need to pay attention that `Value type`when sent into functions, they will be copied into the function (automatically create 1 similar new variable in the function), to avoid this process, you need to use [ref (Pass by reference)](https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/ref) or [in (Similar to ref but readonly)](https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/in-parameter-modifier) (this process is called `Defensive copy`, in the next article I will show you how to limit it)

If `struct`it contains `class`, it is only `class`allocated above `Heap`, but `struct`still above `Stack`(and keeps the address of the class instance inside `Heap`).

```csharp
public struct StackOnlyStruct
{
    public MyClass AReferenceDoesNotMakeTheStructStayOnHeap;
}
void StackOnly()
{
    var stackOnlyStruct = new StackOnlyStruct {
      AReferenceDoesNotMakeTheStructStayOnHeap = new MyClass()
    };
}
```

![](https://images.viblo.asia/c412a7e1-3d52-4354-87ea-7c5e3a6f6b80.PNG)\
![](https://images.viblo.asia/f86beb1d-12ac-4f4e-859b-5695185d1c44.PNG)\
It can be seen `MyClass`that only on `Heap`is `StackOnlyStruct`still on`Stack`

#### Value type will be on the Heap if it is in a Reference type <a href="#value-type-se-tren-heap-neu-no-nam-trong-1-reference-type-5" id="value-type-se-tren-heap-neu-no-nam-trong-1-reference-type-5"></a>

When a `Value type`becomes a field of `Reference type`it will be on `Heap`, this of course, because it needs to "live" with this instance (cannot be revoked at the end of the function).

```csharp
public class MyClass {
    public StackOrHeapStruct AStructFieldWillBeOnHeapToo;
    public int IntAlso;
}
public struct StackOrHeapStruct {
}
void HeapOrStackStruct() {
    // StackOrHeapStruct is a Value type that should be on the Stack
    var onlyStack = new StackOrHeapStruct();
    
    // Now AStructFieldWillBeOnHeapToo will be on the Heap because it is a field of the class
    // Even if it is a Value type
    var myClass = new MyClass {
        AStructFieldWillBeOnHeapToo = new StackOrHeapStruct(),
        IntAlso = 1
    };
}
```

![](https://images.viblo.asia/22ace309-2800-46c7-a3e8-bc1f4e4ada2d.PNG)\
![](https://images.viblo.asia/b3a7b4ec-a0c9-4556-aa79-a0a826688f41.PNG)\
If we check `Heap`the program, we will see that it is not only `MyClass`available but also `StackOrHeapStruct`distributed `int`in general

#### ref struct will ensure a struct is always on the Stack <a href="#ref-struct-se-dam-bao-1-struct-luon-nam-tren-stack-6" id="ref-struct-se-dam-bao-1-struct-luon-nam-tren-stack-6"></a>

Occasionally you will see a declaration type `public ref strut MyRefStruct`, actually it is nothing special, this is just a declaration that ensures `struct`this cannot be a field of 1 `Reference type`(so it cannot be above `Heap`)

```csharp
public ref struct StackOnlyStruct {}
public class MyClass {
  public StackOnlyStruct AReferenceTypeCanNotEmbedARefStructField;
}
```

The code above will not work `compile`, because `StackOnlyStruct`1`ref struct`

#### Allocate array on Stack with Span\<T> <a href="#cap-phat-mang-tren-stack-voi-spant-7" id="cap-phat-mang-tren-stack-voi-spant-7"></a>

Before ending, I want to introduce to everyone one `ref struct`called [Span\<T>](https://learn.microsoft.com/en-us/dotnet/api/system.span-1?view=net-7.0) , usually it is used to point to an array in the Heap (similar to [ArraySegment](https://learn.microsoft.com/en-us/dotnet/api/system.arraysegment-1?view=net-7.0) ), we will see another interesting way to use it\
with the type Sequential data (linear sequence), then you will use `[]T (array)`or `List<T>`, but both of these are class ( `Reference type`) and will be on top. `Heap`\
If you want to use array on Stack, you need to combine `Span<T>`and `stackalloc`(note `T`must be `Value type`)

```csharp
public struct Struct {}
public void StackAllocSpan() {
  // It is necessary to declare the size of the span
  // T must be Value type
  Span<int> notPlayWithHeapIntSpan = stackalloc int[3];
  notPlayWithHeapIntSpan[0] = 0;
  Span<Struct> notPlayWithHeapStrutSpan = stackalloc Struct[3];
}
```

When calling the function, `StackAllocSpan();`there will be no need to allocate above `Heap`. However, attention must be paid! `Stack`has a small size, when used `Span`, the internal elements `Span`are also located on it `Stack`(instead of just 1 pointer to data like a normal array), so **allocating Span too large can lead to** StackOverflow\
. `Span<T>`The performance is much better, but it must be noted that it can `stackalloc Span`only be used within the scope of the function, it cannot be `return`leaked `out`, and the methods `async`also do not allow`Span`


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://huy312100.gitbook.io/software-development/everything-anyone-should-know/comparison/data-structures/class-vs-struct.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
