C# - Difference between Value and Ref Types parameters

In C#, the difference between value type and reference type parameters is fundamentally about how they store their data and what happens when they are passed to methods.

Value Types are stored on the stack and contain their data directly. When you pass a value type to a method, you are passing a copy of the data. Modifying the data inside the method does not change the original data.

Reference Types, on the other hand, are stored on the heap, and a reference (or pointer) to this data is held on the stack. When you pass a reference type to a method, you are passing the reference to the data, not the actual data itself. Therefore, any changes you make inside the method will reflect on the original data because both the original reference and the parameter in the method point to the same data on the heap.

Let's illustrate this with an example:


using System;

public struct ValueTypeExample
{
    public int Value;
}

public class ReferenceTypeExample
{
    public int Value;
}

public class Program
{
    public static void ModifyValueType(ValueTypeExample val)
    {
        val.Value = 10; // This will modify the copy, not the original structure.
    }

    public static void ModifyReferenceType(ReferenceTypeExample refObj)
    {
        refObj.Value = 10; // This will modify the original object's property.
    }

    static void Main()
    {
        ValueTypeExample valType = new ValueTypeExample();
        valType.Value = 5;
        
        ReferenceTypeExample refType = new ReferenceTypeExample();
        refType.Value = 5;

        Console.WriteLine("Before:");
        Console.WriteLine("Value Type: " + valType.Value); // Outputs 5
        Console.WriteLine("Reference Type: " + refType.Value); // Outputs 5

        ModifyValueType(valType);
        ModifyReferenceType(refType);

        Console.WriteLine("After:");
        Console.WriteLine("Value Type: " + valType.Value); // Still outputs 5, because it's a copy
        Console.WriteLine("Reference Type: " + refType.Value); // Outputs 10, the object was modified
    }
}

If you run this code, you'll get the following output:


Before:
Value Type: 5
Reference Type: 5
After:
Value Type: 5
Reference Type: 10

This shows that the ValueTypeExample instance valType retains its original value after the method call because a copy was passed to the method. In contrast, the ReferenceTypeExample instance refType shows the changed value after the method call because the method modified the same object that refType refers to.

This example clearly shows the fundamental difference in how value and reference types are treated when passed to methods. The value type keeps its value unchanged because we're working with a copy, while the reference type's value changes because we're working directly with the original object via its reference.