Value types vs reference types in C#

Short answer

A value type (int, bool, struct, enum) is copied on assignment. A reference type (class, string, arrays, delegates) copies only the reference, so both names point at the same object.

csharp
// Value type — copied
int a = 5;
int b = a;
b = 10;
Console.WriteLine(a);        // 5

// Reference type — shared
var list1 = new List<int> { 1, 2 };
var list2 = list1;
list2.Add(3);
Console.WriteLine(list1.Count);   // 3

#Passing to methods

csharp
void Modify(List<int> items) => items.Add(99);   // caller sees the change
void Reassign(List<int> items) => items = new(); // caller does NOT

The reference is passed by value. Mutating the object works; replacing it does not. ref changes that if you genuinely need it.

#string is the odd one

string is a reference type but behaves like a value type, because it is immutable. Every "modification" makes a new string:

csharp
string s = "a";
s += "b";      // a new string; the original is untouched

That is why building a string in a loop is slow. Use StringBuilder.

#Nullability

Reference types can be null; value types cannot, unless you mark them:

csharp
int? maybe = null;
int actual = maybe ?? 0;

Enable nullable reference types in your project file (<Nullable>enable</Nullable>) and the compiler starts warning about possible null dereferences. Turn it on for new projects.

#When to write a struct

Rarely. Use a struct only for small, immutable, value-like data — a coordinate, a colour, a money amount. Everything else should be a class. A large struct copied repeatedly is slower than a class, not faster.