With this code:
void SomeMethod(string str)
{
string tmpStr = ... Read some value from file ...
if( !tmpStr.Empty() )
str = tmpStr;
}
When I call this method with a simple string just created inside the main subroutine:
string localString = "";
SomeMethod( localString );
The value that I get back in localString is an empty event when I see in debug that in the method SomeMethod the variable tmpStr is not empty and the variable str in the method is full with chars.
If I change the SomeMethod signature to be:
SomeMethod(ref string str)
I see the right result.
But string is a reference type, so why do I need in this case to send it with ref?
and why I get the result that I expected only when I call:
SomeMethod(string str)
It’s not just that the string is immutable, but also that while
stringis a reference type, a reference itself is not. That is, you are passing thestringby reference, but the reference itself is passed by value.Thus, for reference types, you can modify the object that is referred to by the parameter (as long as it’s modifiable), but you cannot modify what the argument refers to unless you pass it by reference.
So, when you try to change what the
stringvariable refers to:It changes what
strrefers to locally, but does not affect what the original argumentlocalStringrefers to.Think of it this way, let’s say that the argument
localStringrefers to an object at location 1000:Then when we pass
localStringto the method, it creates a copy of the reference (asstr) and updates the reference count…Then, when you assign str to a new string, it modifies the reference
strbut notlocalString:So your modification of
stronly changed whatstrrefers to, not the original referncelocalString, if you want to change that, then you pass by reference, which means thatstris a reference back to the original argument (much like a ptr to a ptr):Now, when you change
strit changes the referncelocalStringas well:And then, of course, the original string (assuming nothing else refers to it as in this example) can be garbage collected…
So, if you really want to modify the
stringparameter, pass it byreforout, or you can return the new mutated version, or store in an instance member (though pass-by-instance-member is a higher order of coupling and can cause other issues…).