int, bool, double, DateTime, and any struct are value types — assigning one copies the actual data. class instances are reference types — assigning one copies a reference to the same object, not the object itself.
int a = 5;
int b = a;
b = 10;
Console.WriteLine(a); // 5 — b holds its own independent copy
class Point { public int X; }
Point p1 = new Point { X = 5 };
Point p2 = p1;
p2.X = 10;
Console.WriteLine(p1.X); // 10 — p1 and p2 point to the same object
This is the single most common source of "why did changing this also change that" bugs — and, in the other direction, "why didn't changing this affect that" bugs when someone expects reference semantics from a value type (or vice versa).
Method parameters follow the same rule by default: passing a value type copies it into the method, so changes inside the method don't affect the caller's variable — unless you explicitly opt in with ref or out (covered in depth later):
void Increment(ref int x) { x++; }
int n = 5;
Increment(ref n);
Console.WriteLine(n); // 6 — ref makes the parameter an alias for the caller's variable
Passing a reference type parameter, by contrast, copies the reference — so mutating the object it points to is visible to the caller, but reassigning the parameter itself to a new object is not:
void Rename(Point p) { p.X = 99; } // mutates the shared object — caller sees it
void Replace(Point p) { p = new Point(); } // reassigns the local copy of the reference — caller does not see it
var point = new Point { X = 1 };
Rename(point);
Console.WriteLine(point.X); // 99
Replace(point);
Console.WriteLine(point.X); // still 99 — Replace only changed its own local reference