For all other reference types, passing it using byval semantics (without ref or out ), means you cannot change which object on the heap the callers copy points to, it does not mean you can't change the contents of the object on the heap that the variable points to. Because strings are immutable, they are truly an exception, they behave like a value type in this respect, even though they are a reference type, but this is done by exceptional additional coding in the CLR.