The parameters are by value. At least this is the default. But the data type of it influences your behavior. You have types that are by value and types that are by reference.
Do not confuse parameter passing with type allocation. Passing by value is not the same as having a type by value.
Passing by value means that a copy of the data is made.
Types by value do what you expect since there is a copy of the data you see.
Reference types are also passed by value. But what is the value of reference types? It is a pointer to an object in the heap. It is a memory address. Always. Then the copy is also made, but it is the address that is copied, not the referenced object. It is by value also.
The difference is this guy has an object with a longer lifespan. Internally the value is pointer, but in your code you access this object pointed by it. Any change in it reflects on the object throughout its lifetime, even outside the method where there was the change. This is a characteristic of the type and not of the parameter passage.
Note that if you change the address of the object, then you will see that there was this change in argument passed to the method, whether constructor or not.
I created an example to demonstrate this:
public void OutroTeste(List<string> lista) {
lista = new List<string>() { "aaa", "bbb" };
return;
}
Behold working in the ideone. And in the .NET Fiddle. Also put on the Github for future reference.
This method is receiving lista
by value. Then it creates a new list with completely different data inside it and have it stored in lista
which is the parameter. When I go to the list after running this method, what happens? This new data is gone. The new list only exists inside the method, even though I have assigned it to the parameter, it has not changed, because this time I actually changed the parameter. When you change the elements of the same list as the parameter points, you are changing the pointed object and not the parameter itself.
Learn more about their allocation.
In his example List<T>
is a type by reference, is a class. Then everything you change in it, will be reflected in the variable that was used as argument.
A curious fellow is the string
. It is a reference, so it is always passed the pointer. But it is immutable and has value semantics, so a change in the object will create a new object that will be allocated at another memory position. Therefore the change will be restricted to the method where this occurred. Unless, of course, the parameter is marked as reference.
Parameters ref
out
and ref
are used to pass by reference. There you will always pass a reference, to the real value. For reference types, there shall be a reference for the pointer of the type which is nevertheless a reference for the object itself. In this case even in the example above if a new object is created, this will be reflected outside the method.
Therefore types by value or types by reference can make use of the reference passage.
If you’re curious to understand better how does the stack and the heap.
This answer about passing parameter by value or by reference should be useful to you: http://answall.com/a/59687/14584
– Caffé