In C#.net, all data types are mainly classified into two categories.
- Value Type
- Reference Type
Value Type in C#:
A variable of a value type in C# contains its value and the variable name is directly associated with the storage location in memory where the value is stored.
Values of value types are short lived, and they are generally needed for being a part of an expression. In that case, variables and temporary values stored on a temporary storage pool, known as stack.
For example, when we declare a value type variable as int X = 500 then the C# compiler allocates some memory space from the stack and stores the value, as shown in the image below.

Copy a value type to another value type in C#?
If we assign a value type variable to another value type variable, then the exact value is copied and in that case both of the variables work independently. If we change value of any variable, then that doesn’t affect to the other variable.

Let’s take an example and here we have two variables declared as int X = 600 and int Y = 500 , If we look at above, the compiler allocates memory space from stack for both variables and stores the exact value in it.

Now, when we assign variable X = Y then the compiler copies exact value of Y to X . In this case, both X and Y have value 500 stored in the stack memory.

When we reset the value of Y to 1000 compiler assigns 1000 to Y in the stack memory. However, value of X remains unchanged.
Both are two different memory location. So, any change to any one variable doesn’t affect the other.
Example 1: Assign value type to another value type in C#
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
static void Main(string[] args) { int X = 600; int Y = 500; Console.WriteLine("Value of X - {0}", X); Console.WriteLine("Value of Y - {0}", Y); X = Y; //Assigning the value of Y to X Y = 1000;//Reset Y to 1000 Console.WriteLine("Value of X after assignment- {0}", X); Console.WriteLine("Value of Y after assignment - {0}", Y); Console.ReadLine(); } |
Output:

Examples of value types in C#:
In C#, we have following value types available.
- bool
- byte
- char
- decimal
- double
- enum
- float
- int
- long
- sbyte
- short
- struct
- uint
- ulong
- ushort
Reference Type in C#:
Reference type holds the reference of the value, so in other words when we declare a reference type, then the compiler allocates some memory space from the managed heap and stores the value, the address of the memory is stored in the stack.

In the above example, the variable emp is declared as a reference type, hence the compiler allocates memory from heap and stores the values. The memory address 0x00000046 of the reference type emp is stored in the thread stack.
What happens when we assign one reference type to another reference type in C#?
If we assign a reference type variable to another reference type then the reference is copied, that means the memory address will be copied and both variables will point to same memory location.

In above example, we have declared two reference types emp and emp2. Both these reference types have been allocated memory in managed heap. The memory addresses of the reference types emp and emp2 have been stored in the stack as shown in the image above.

If we assign reference type emp to emp2 as emp2 = emp; In this case the compiler just updates the memory address of emp2 to emp. (ea. 0x00000046, which is memory address of emp as shown in the image).
That means, both the reference types emp and emp2 point to same memory location. Any change to any of the variable affects the other, because they are both pointing to the same location. The output value of emp2.Name will be “Robin”. as below

Example 2: Assign reference type to another reference type in C#
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 |
public class Employee { public string Name { get; set; } public int Age { get; set; } } public class program { static void Main(string[] args) { Employee emp = new Employee(); emp.Name = "Robin"; emp.Age = 25; Employee emp2 = new Employee(); emp2.Name = "Russel"; emp2.Age = 30; Console.WriteLine("Before assignment, both emp & emp2 has separate location."); Console.WriteLine("emp.Name : " + emp.Name.ToString()); Console.WriteLine("emp2.Name : " + emp2.Name.ToString()); Console.WriteLine("**********************************************************"); //Assign emp to emp2 emp2 = emp; Console.WriteLine("After assignment, both emp & emp2 points to same location."); Console.WriteLine("emp.Name : " + emp.Name.ToString()); Console.WriteLine("emp2.Name : " + emp2.Name.ToString()); Console.WriteLine("**********************************************************"); emp2.Name = "Steve"; Console.WriteLine("Changed emp2.Name value, that changed emp.Name value aswell."); Console.WriteLine("emp.Name : " + emp.Name.ToString()); Console.WriteLine("emp2.Name : " + emp2.Name.ToString()); Console.ReadLine(); } } |
Output:

Reference Types in C#:
In .NET, we have following reference types available.
- class
- interface
- delegate
- dynamic
- object
- string
Conclusion
Value types and Reference types in C# are essential for efficiently working with simple and complex data structures and types. Understanding how they work, their memory allocation, and their role in boxing and unboxing can help write more optimized and efficient C# programs.

Thanks for the clear examples- great!