struct PointS { public int X, Y; public override string ToString() => $"({X},{Y})"; } class PointC { public int X, Y; public override string ToString() => $"({X},{Y})"; } class Program { static void MoveFirstWrong(PointS[] arr) { // BUG: copies the struct, mutates the copy, never writes it back var p = arr[0]; // value copy p.X += 10; p.Y += 10; // arr[0] not updated -> no effect on array storage } static void MoveFirstRight(PointS[] arr) { // FIX: mutate a local copy and assign it back var p = arr[0]; // value copy p.X += 10; p.Y += 10; arr[0] = p; // write back } static void MoveFirstRef(PointC[] arr) { // Works directly because arr[0] is a reference to the same object arr[0].X += 10; arr[0].Y += 10; } // Optional: foreach pitfall with structs in a List<T> static void IncrementAllWrong(List<PointS> list) { foreach (var item in list) { var tmp = item; // copy tmp.X++; tmp.Y++; // mutate the copy only // not assigned back -> list unchanged } } static void IncrementAllRight(List<PointS> list) { for (int i = 0; i < list.Count; i++) { var tmp = list[i]; tmp.X++; tmp.Y++; list[i] = tmp; // write back } } static void Main() { // --- Struct array demo --- var s = new[] { new PointS { X = 1, Y = 1 } }; Console.WriteLine($"Struct before: {s[0]}"); // (1,1) MoveFirstWrong(s); Console.WriteLine($"After Wrong : {s[0]}"); // still (1,1) <-- bug observed MoveFirstRight(s); Console.WriteLine($"After Right : {s[0]}"); // (11,11) <-- fixed // --- Class array demo --- var c = new[] { new PointC { X = 1, Y = 1 } }; Console.WriteLine($"nClass before : {c[0]}"); // (1,1) MoveFirstRef(c); Console.WriteLine($"After Ref : {c[0]}"); // (11,11) <-- same object mutated // --- Optional List<T> pitfall --- var list = new List<PointS> { new PointS { X = 5, Y = 5 } }; Console.WriteLine($"nList before : {list[0]}"); // (5,5) IncrementAllWrong(list); Console.WriteLine($"After Wrong : {list[0]}"); // (5,5) <-- unchanged IncrementAllRight(list); Console.WriteLine($"After Right : {list[0]}"); // (6,6) <-- changed } } Â