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
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)
Stack memory : The internal allocation and deallocation process
Stack
will operate in LIFO 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 functionB()
, then itA()
starts firstB()
but ends later, then the data in the functionA()
will be allocated first, thenB()
; When revoking, it's the opposite, the internal dataB()
is recalled first, then comesA()
Therefore, it
Stack
only contains data generated during the function call (akalocal 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 functionglobal 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 dataHeap
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 has done it for us).
Performance and size are notable between Stack
and Heap
!
Stack
is much smaller in sizeHeap
, because the Stack only needs to contain local variables, while the Heap needs to contain all "live" data in the programThe performance of
Stack
(allocate/reclaim/retrieve) isHeap
much higher , this is obvious because the functions will be called many times in the programIn addition, Garbage collector 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
In C# there are 2 data types: Value type (managed data types) and Reference type (unmanaged data types) , each type will represent a number of data types.
Reference type : it is the class (recently there is also record ), data types when declared as such
Reference type
will always be on the HeapValue type : includes the data types you often see
int
:float
, ,bool
,byte
,char
,enum
...struct
(string
yesclass
), these data can be located on the Heap or Stack depending on how they are used.
Reference type
As said, class
and record
will always be on Heap
no matter whether you declare it is local variable
good or notglobal variable
Value type
Value type ( int
, bool
, struct
, enum
) will be on the Stack if it belongs local variable
to a function.
int
, bool
, struct
, enum
) will be on the Stack if it belongs local variable
to a function.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
).
Value type will be on the Heap if it is in a Reference type
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).
ref struct will ensure a struct is always on the Stack
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
)
The code above will not work compile
, because StackOnlyStruct
1ref struct
Allocate array on Stack with Span<T>
Before ending, I want to introduce to everyone one ref struct
called Span<T> , usually it is used to point to an array in the Heap (similar to ArraySegment ), 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
)
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 allowSpan
Last updated