CodeOath
← All posts
C#65 min total · 17 parts

C# Fundamentals: Value Types, Reference Types, Boxing, and the Type System

Contents — Part 17 of 17: Common Mistakes Worth Remembering
Part 17 of 17 · ~1 min

Common Mistakes Worth Remembering

  • Expecting a struct passed to a method to reflect changes made inside it (it won't, unless passed with ref).
  • Forgetting that string methods return new strings instead of mutating in place — s.Trim(); alone does nothing observable.
  • Overusing object/non-generic collections (ArrayList, Hashtable) and paying a hidden boxing cost on every value type stored in them.
  • Overriding Equals without also overriding GetHashCode (or vice versa), silently breaking Dictionary/HashSet lookups for that type.
  • Treating a static field like harmless shared convenience without considering what happens when multiple threads (or concurrent web requests) touch it at once.
  • Writing a mutable struct and then being surprised that mutating a copy — from a list indexer, a property getter, or a plain variable assignment — doesn't affect the original.
  • Assuming an array or collection assignment copies the data — it copies the reference; the underlying array or list is shared until you explicitly clone it.
  • Conflating "value type" with "lives on the stack" — a value type is heap-allocated whenever it's a field of a class, captured by a closure, or used in an async method.

Practice the type-system reasoning behind these examples — writing real C# solutions and comparing against reference answers — in the code lab, and see how these same lifetime and mutation questions play out at the API layer in Building REST APIs with ASP.NET Core.