Parameters are by value. At least this is the default. But his type of data influences his behavior. You have types that are by value and types that are by reference .
Do not confuse parameter passing with type allocation. Going by value is not the same as having one type by value.
Passing by value means that a copy of the data is made.
Value types do what you expect since there is a copy of the data you see.
The types by reference are also passed by value. But what is the value of the types by reference? It is a pointer to an object in heap . It's a memory address. Ever. Then the copy is also made, but it is the address that is copied, not the object referenced. It's for value too.
The difference is that this type has an object with a longer lifetime. Internally the value is pointer, but in your code you access this object pointed to by it. Any change in it, reflects on the object throughout its lifetime, even outside the method where the change occurred. This is a characteristic of type and not of parameter passing.
Note that if you change the object's address, then you'll see that there was no change in argument last for the method, either constructor or not.
I created an example to demonstrate this:
public void OutroTeste(List<string> lista) {
lista = new List<string>() { "aaa", "bbb" };
return;
}
See running on dotNetFiddle .
This method is receiving lista
by value. Then it creates a new list with completely different data inside it and you have to save it to lista
which is the parameter. When I am accessing the list after I ran this method, what happens? This new data is gone. The new list only exists within the method, even though I have assigned it to the parameter, it has not been changed, because this time I actually flipped the parameter. When you change the elements of the same list that the parameter points to, you are changing the object pointed to and not the parameter itself.
Learn more about their placement .
In your example List<T>
is a type by reference, it's a class. Then everything you change in it will be reflected in the variable that was used as an argument.
A curious type is string
. It is a reference, so the pointer is always passed. But it is immutable and has value semantics, so a change in the object will create a new object that will be allocated in another position from memory. Therefore the change will be restricted to the method where this occurred. Unless, of course, the parameter is marked as a reference.
Parameters ref
out
and ref
are used to pass by reference . There will always be a reference, for the real value. In the case of types by reference, there will be a reference to the type pointer that is still a reference to the object itself. In this case even in the example above if a new object is created, this will reflect outside the method.
So types by value or types by reference can make use of passing by reference.
If you're curious to understand how stack works and heap in> .