You're not alone; it confuses a lot of people.
Here's how I like to think about it.
A variable is a storage location.
A variable can store something of a certain type.
There are two types of types: value types and reference types.
The value of a variable of a reference type is a reference to an object of this type.
A value of a value type variable is an object of this type.
A formal parameter is a kind of variable.
There are three types of formal parameters: parameter values, ref parameters, and out parameters.
When you use a variable as an argument that matches a value parameter, the value of the variable is copied to the repository associated with the formal parameter. If the variable is of type value, then a copy of the value is created. If the variable has a reference type, then a copy of the link is made, and now two variables refer to the same object. In either case, a copy of the value of the variable is created.
When you use a variable as an argument that matches the out or ref parameter, that parameter becomes an alias for the variable . When you speak:
void M(ref int x) { ...} ... int y = 123; M(ref y);
what you are saying is "x and y are now the same variable." They both belong to the same storage location.
I find it much easier to understand than to think about how the alias is implemented - passing the managed address of a variable to a formal parameter.
It is clear?
Eric Lippert
source share