One fairly obvious statement is that data types take up
different amounts of space. An integer obviously does not take as much space as
a Person class would. The Person class would require space for a name, birth
date, etc. We also have collection types, and with collections we do not know
how much space we will need for them. It is not defined in advance at all. We
need to consider and understand how each of these cases is handled.
As a general rule, we store value types on the stack in C#
and we store reference types on the heap. This is not entirely correct, but it is
fairly close. Value types are stored on the stack when they're within the scope
of a method. This is because methods live on the stack. If the value type for
example is associated with a class, it is being associated with a reference
type and is therefore stored with the reference type. This means that it will
be included on the heap along with the rest of the data associated with the
reference type.
Stack
The stack manages the currently executing code. The
information currently running is here. The currently executing code is here,
which means that it contains for example method-specific information. This
means local variables are stored here, which includes value types and in some
sense the reference types. The reference types are here, but they only contain
the address of the actual data here. This lets you have access to them in the
current method even though the data is stored elsewhere. The stack builds up as
we go deeper into methods. You have probably seen a "Stack Trace." It
is basically some diagnostic info showing what the current information on the
stack is. For the most part, this is just a list of nested methods. We call it
a stack because each new context stacks on top of the previous one.
Heap
The heap is a separate section of memory whose main purpose
is simply to manage the data we want to declare dynamically. The main benefit
of this memory is that it is easily allocated for objects of varying size,
collections usually. This is the area where the actual data is stored for
variables of reference type. We have a pointer to the data which we do not see
because .NET is a managed language. The pointer is the variable we are using.
It is stored on the stack. It is the way we access this heap-stored data. This
is why we call it a reference type. It is because we basically just keep a
reference to the data.
Dynamic Data Types
Some data types require an unknown amount of space. This
creates the need for memory to be dynamically allocated for this data. When we
dynamically allocate data, we are allocating this data in the managed heap of
C#. As I have said previously, our collections are the primary form of dynamic
data in C#. Lists, stacks, queues, etc. are a few of the collections which we
use. These are obviously all reference types. If you tried to store collections
on the stack it would get pretty messy pretty quickly, since collections tend
to grow and shrink. That's why the heap is so much nicer than the stack for
dynamic data.