English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية

C# Value Types and Reference Types

In C#, data types are categorized based on how they store values in memory. C# includes the following categories of data types:

  1. Value types

  2. Reference types

  3. Pointer types

Value types

If a data type stores its data value in its own memory space, it is a value type. This means that the variables of these data types directly contain values.

All value types derive fromSystem.ValueTypederived, whereasSystem.ValueTypeand derives fromSystem.Objectderived.

For example, an integer variable int i = 100;

The system will100 is stored in the memory space allocated for the variable i. The following figure illustrates how to100 is stored in the memory of 'i' (0x239110A hypothetical position in the parentheses:

Memory allocation for value type variables

The following data types are value types:

  • bool

  • byte

  • char

  • decimal

  • double

  • enum

  • float

  • int

  • long

  • sbyte

  • short

  • struct

  • uint

  • ulong

  • ushort

Passing value type variables

  When you pass a value type variable from one method to another, the system creates a separate copy of the variable in the other method. If you change the value in one method, it will not affect the variable in the other method.

static void ChangeValue(int x)
{
    x =  200;
    Console.WriteLine(x);
}
static void Main(string[] args)
{
    int i = 100;
    Console.WriteLine(i);
    
    ChangeValue(i);
    
    Console.WriteLine(i);
}
Output:

100
200
100

In the above example, even after passing the variable i from the Main() method to the ChangeValue() method and changing its value, it remains unchanged.

Reference types

Unlike value types, reference types do not store their values directly. Instead, they store the address of the location where the value is stored. In other words, reference types contain pointers to another storage location that holds the data.

For example, the following string variable:

string s = "Hello World!!";

The following figure shows how the system allocates memory for the above string variable.

Memory allocation for reference type variables

As shown in the figure above, the system selects a random location in memory (0x803200). The value of variable s is 0x600000, which is the actual memory address of the data value. Therefore, reference types store the address of the location where the actual value is stored, not the value itself.

The following are reference type data types:

  • Strings

  • Arrays (even if their elements are value types)

  • Classes

  • Delegates

Passing reference type variables

When you pass a reference type variable from one method to another, it does not create a new copy; instead, it passes the address of the variable. Therefore, if we change the value of the variable in the method, it will also reflect in the calling method.

static void ChangeReferenceType(Student std2)
{
    std2.StudentName = "Steve";
}
static void Main(string[] args)
{
    Student std1 = new Student();
    std1.StudentName = "Bill";
    
    ChangeReferenceType(std1);
    Console.WriteLine(std1.StudentName);
}
Output:
Steve

In the above example, we will pass the Student object std1 Passed to the ChangeReferenceType() method. Here, it actually passes std1memory address. Therefore, when the ChangeReferenceType() method changes StudentName, it is actually changing std1the StudentName property of the object, because std1and std2All point to the same address in memory.

Null Value

  The default value null for reference type variables is when they are uninitialized. Null represents a reference to no object.

Null Reference Type

Value type variables cannot be null because they store values rather than memory addresses. C#2Version .0 introduced nullable types, which can be used to assign null to value type variables or declare value type variables without assigning them a value.