DEV Community

Cover image for ๐—›๐—ผ๐˜„ ๐—ฉ๐—ฎ๐—น๐˜‚๐—ฒ ๐—ง๐˜†๐—ฝ๐—ฒ๐˜€ ๐—ฎ๐—ป๐—ฑ ๐—ฅ๐—ฒ๐—ณ๐—ฒ๐—ฟ๐—ฒ๐—ป๐—ฐ๐—ฒ ๐—ง๐˜†๐—ฝ๐—ฒ๐˜€ ๐—ช๐—ผ๐—ฟ๐—ธ ๐—ถ๐—ป ๐—–#?
Md. Saddam Hossain
Md. Saddam Hossain

Posted on • Edited on

๐—›๐—ผ๐˜„ ๐—ฉ๐—ฎ๐—น๐˜‚๐—ฒ ๐—ง๐˜†๐—ฝ๐—ฒ๐˜€ ๐—ฎ๐—ป๐—ฑ ๐—ฅ๐—ฒ๐—ณ๐—ฒ๐—ฟ๐—ฒ๐—ป๐—ฐ๐—ฒ ๐—ง๐˜†๐—ฝ๐—ฒ๐˜€ ๐—ช๐—ผ๐—ฟ๐—ธ ๐—ถ๐—ป ๐—–#?

When working with C#, one of the most important concepts to understand is the difference between value types and reference types.

If you understand this difference, concepts such as copying objects, modifying variables, method parameters, and memory behavior become much easier to reason about.

Let's understand it with a simple real-world example.

Imagine a Creative Agency
In a creative agency, two team leads, Sam and Taylor, have completely different ways of sharing design drafts with their teams.

Sam: Everyone Gets Their Own Copy
Sam likes to print a fresh copy of every design draft for each team member.

Each person gets their own independent copy.

If a designer writes notes on their copy or changes something, Sam's original draft remains unchanged.

For example:

Sam's Original Draft
โ”‚
โ”œโ”€โ”€ Copy โ†’ Designer A
โ”œโ”€โ”€ Copy โ†’ Designer B
โ””โ”€โ”€ Copy โ†’ Designer C

Everyone can modify their own copy without affecting anyone else's.

This is similar to how value types behave in C#.

Taylor: Everyone Shares One Document
Taylor prefers using a shared cloud document.

Instead of giving everyone a separate copy, Taylor gives the entire team access to the same document.

         Shared Document
         /      |       \
        /       |        \
 Designer A  Designer B  Designer C
Enter fullscreen mode Exit fullscreen mode

If Designer A changes something, Designer B and Designer C can see the change because everyone is working with the same underlying document.

This is similar to how reference types work in C#.

What Are Value Types?
A value type stores its value directly.

When you assign one value-type variable to another, the value is copied.

Common value types include:

int

double

decimal

bool

char

struct

enum

Consider this example:

int firstNumber = 10;
int secondNumber = firstNumber;

secondNumber = 20;

Console.WriteLine(firstNumber);  // 10
Console.WriteLine(secondNumber); // 20
Enter fullscreen mode Exit fullscreen mode

When we write:

int secondNumber = firstNumber;

the value 10 is copied into secondNumber.

There are now two independent values.

Changing secondNumber does not change firstNumber.

You can think of it like Sam's printed documents:

firstNumber
โ†“
10

secondNumber
โ†“
10

After changing secondNumber:

firstNumber
โ†“
10

secondNumber
โ†“
20

The original value remains unchanged.

What Are Reference Types?
A reference type variable stores a reference to an object.

When you assign one reference-type variable to another, you copy the reference, not a completely independent object.

Common reference types include:

class

object

string

array

delegate

interface references

Consider this example:

public class Developer
{
    public string Name { get; set; } = string.Empty;
}
Enter fullscreen mode Exit fullscreen mode

Now create an object:

var developer1 = new Developer
{
    Name = "Sam"
};

var developer2 = developer1;

developer2.Name = "Taylor";

Console.WriteLine(developer1.Name); // Taylor
Console.WriteLine(developer2.Name); // Taylor
Enter fullscreen mode Exit fullscreen mode

Why did changing developer2.Name also change developer1.Name?

Because both variables refer to the same object.

Conceptually:

developer1 โ”€โ”€โ”€โ”€โ”€โ”
โ”‚
โ–ผ
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚ Developer โ”‚
โ”‚ Name=Taylor โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
โ–ฒ
โ”‚
developer2 โ”€โ”€โ”€โ”€โ”€โ”˜

This is similar to Taylor's shared cloud document.

There aren't two independent documents. Both variables refer to the same underlying object.

The Important Difference
The easiest way to remember the difference is:

Value type assignment copies the value. Reference type assignment copies the reference.

For example:

int a = 10;
int b = a;
Enter fullscreen mode Exit fullscreen mode

Here, b gets its own copy of the value.

But:

var person1 = new Developer();
var person2 = person1;
Enter fullscreen mode Exit fullscreen mode

Here, person2 points to the same object as person1.

A Side-by-Side Example
Let's compare both behaviors.

Value Type

int x = 10;
int y = x;

y = 20;

Console.WriteLine(x); // 10
Console.WriteLine(y); // 20
Enter fullscreen mode Exit fullscreen mode

The variables contain independent values.

x โ†’ 10

y โ†’ 20

Reference Type
var user1 = new Developer
{
    Name = "Sam"
};

var user2 = user1;

user2.Name = "Taylor";

Console.WriteLine(user1.Name); // Taylor
Console.WriteLine(user2.Name); // Taylor
Enter fullscreen mode Exit fullscreen mode

Both variables refer to the same object.

user1 โ”€โ”€โ”
โ”œโ”€โ”€> Developer { Name = "Taylor" }
user2 โ”€โ”€โ”˜

What Happens When Passing Them to Methods?
This distinction becomes even more important when working with methods.

Consider a value type:

static void ChangeNumber(int number)
{
    number = 100;
}

int value = 10;

ChangeNumber(value);

Console.WriteLine(value); // 10
Enter fullscreen mode Exit fullscreen mode

The method receives a copy of the value.

Changing the parameter doesn't change the original variable.

Now consider a class:

static void ChangeName(Developer developer)
{
    developer.Name = "Taylor";
}

var developer = new Developer
{
    Name = "Sam"
};

ChangeName(developer);

Console.WriteLine(developer.Name); // Taylor
Enter fullscreen mode Exit fullscreen mode

The method receives a copy of the reference, but both references point to the same object.

Therefore, changing the object's property is visible through the original variable.

This is an important detail:

Reference types are passed by value by default in C#.

What gets passed by value is the reference.

That means this:

static void ChangeName(Developer developer)
{
    developer.Name = "Taylor";
}
Enter fullscreen mode Exit fullscreen mode

does not mean the object itself is copied.

Instead, the reference is copied.

Reference Type Assignment Does Not Create a New Object
This is a common source of confusion for developers learning C#.

Consider:

var first = new Developer
{
    Name = "Sam"
};

var second = first;
Enter fullscreen mode Exit fullscreen mode

It is tempting to think that second contains a new Developer object.

It doesn't.

There is still only one object.

first โ”€โ”€โ”€โ”€โ”€โ”
โ”‚
โ–ผ
Developer
Name = Sam
โ–ฒ
โ”‚
second โ”€โ”€โ”€โ”€โ”€โ”˜

To create a separate object, you need to explicitly create or clone one.

For example:

var second = new Developer
{
    Name = first.Name
};
Enter fullscreen mode Exit fullscreen mode

Now the two variables refer to different objects.

Are Value Types Always Stored on the Stack?
You may often hear:

"Value types live on the stack, and reference types live on the heap."

This is a useful beginner-friendly simplification, but it is not an accurate rule.

Where a value is stored depends on the context and how the runtime represents it.

For example, a value type can be:

a local variable

a field inside an object

an element inside an array

boxed into an object

Similarly, a reference-type variable may be a local variable while the object it references is stored elsewhere.

The more accurate mental model is:

Value types represent their data directly, while reference types represent a reference to an object.

Focus on the semantics of copying and sharing rather than memorizing "stack vs heap."

What About string?
string is a reference type in C#.

However, strings are immutable.

For example:

string first = "Hello";
string second = first;

second = "World";

Console.WriteLine(first);  // Hello
Console.WriteLine(second); // World
Enter fullscreen mode Exit fullscreen mode

This can look like value-type behavior.

But string is still a reference type.

The important point is that you cannot modify an existing string object. Operations that appear to change a string actually produce another string.

So:

second = "World";

doesn't modify the original "Hello" string.

Instead, second is made to refer to another string.

Structs Are Value Types
You can also create your own value types using struct.

For example:

public struct Point
{
    public int X { get; set; }
    public int Y { get; set; }
}
Enter fullscreen mode Exit fullscreen mode

Now:

var point1 = new Point
{
    X = 10,
    Y = 20
};

var point2 = point1;

point2.X = 100;

Console.WriteLine(point1.X); // 10
Console.WriteLine(point2.X); // 100
Enter fullscreen mode Exit fullscreen mode

Because Point is a value type, assigning point1 to point2 creates an independent copy of its value.

Classes Are Reference Types
When you define a class:

public class Point
{
    public int X { get; set; }
    public int Y { get; set; }
}
Enter fullscreen mode Exit fullscreen mode

the type is a reference type.

Now:


var point1 = new Point
{
    X = 10,
    Y = 20
};

var point2 = point1;

point2.X = 100;

Console.WriteLine(point1.X); // 100
Enter fullscreen mode Exit fullscreen mode

Both variables refer to the same object.

A Simple Mental Model
Whenever you're unsure about the behavior, ask yourself:

Is this a value type?
Think:

"I'm making a copy of the data."

Original โ†’ Copy

Changes to the copy don't affect the original.

Is this a reference type?
Think:

"I'm making another reference to the same object."

Reference A โ”€โ”€โ”
โ”œโ”€โ”€> Same Object
Reference B โ”€โ”€โ”˜

Changes made through one reference can be observed through the other.

Quick Comparison
Feature Value Type  Reference Type
Examples    int, bool, struct, enum class, string, array, object
Assignment  Copies the value    Copies the reference
Multiple variables  Independent values  Can reference the same object
Object sharing  No, by normal assignment    Yes
Example int x = y   Person p2 = p1
Key Takeaway
Understanding value types and reference types is much easier if you remember Sam and Taylor.
Enter fullscreen mode Exit fullscreen mode

Sam's approach is like a value type:

Everyone receives an independent copy.

Changing one person's copy doesn't affect the original.

Taylor's approach is like a reference type:

Everyone works with the same shared object.

A change made through one reference can be observed through another reference to that same object.

The most important rule to remember is:

Value type assignment copies the value. Reference type assignment copies the reference.

Once you understand this distinction, many C# conceptsโ€”including method parameters, object mutation, structs, classes, arrays, and immutabilityโ€”become much easier to understand.

Learn More
If you want to explore the concept in more depth, check out the full article on my website:

How Value Types and Reference Types Work in C#

Top comments (0)