Reputation: 6828
In C#, for what I know, the passage of the parameters during a method call is by value. BUT when you use an object as an argument, what you pass is the reference of the object itself. This means that if you access (and modify) the value of a field inside an object, the updates will be seen once the method call is finished too.
So, if I modify the value of a String inside a method, it should be modified when the method call is terminated (since String is an object in C#). But this isn't true, in fact if I write:
public static void main (String []args){
String s= "hello";
method(s);
System.Console.Writeline(s);
}
public void method (String s)
{s = "world";}
It will print "hello", and not "world". The only way to print "world" is to add the keyword ref
in the method signature and call.
Why this happens? My answer (which I'd like that you confirm or correct) is that in C# String objects are immutable, so if I make s="world" actually the compiler is creating a new string object, but the reference to the object String s doesn't change (since the passage is by value).
In fact, if I print s.getHashCode()
just before and after method()
call, the two values are different.
What do you think about my explanation?
Upvotes: 4
Views: 4351
Reputation: 1500675
So, if I modify the value of a String inside a method, it should be modified when the method call is terminated (since String is an object in C#). But this isn't true, in fact if I write:
You're not modifying the String
object. You're modifying the parameter to refer to a different String
. That's just changing a local variable, and is not seen by the caller.
The String reference is being passed by value, just like normal. You need to distinguish between changing the value of the parameter, and modifying the object that a parameter value refers to. You'll see exactly the same behaviour with your own class, even if it's mutable:
class Person
{
public string Name { get; set; }
}
class Test
{
static void Main()
{
var p = new Person { Name = "Tom" };
Method(p);
Console.WriteLine(p.Name);
}
static void Method(Person parameter)
{
parameter = new Person { Name = "Robin" };
}
}
Now if in Method
you made a change to the object instead, e.g.
static void Method(Person parameter)
{
parameter.Name = "Robin";
}
... then you'd see a change to the output. But that's not modifying the parameter. The only reason that string's immutability is relevant is that it means the second version of Method
above has no equivalent (in safe code) when the parameter is a string.
See my article on parameter passing for more details.
Upvotes: 7
Reputation: 203824
So, if I modify the value of a String inside a method, it should be modified when the method call is terminated (since String is an object in C#).
Yes, that is 100% correct. If you were able to modify the actual string
instance, than the caller would be able to observe that change.
Of course, because string
is immutable there is no way for you to modify the string instance. That's what it means for it to be immutable.
Since you're not actually modifying the string
instance, there is no modification for the caller to actually observe.
What you are doing in your code is not modifying the string instance, but rather modifying the variable that is holding the reference to the string. That variable is a completely different variable from the local variable in your main method. Modifying one does not affect the other (unless you use ref
).
What you have are to completely different variables, each with a reference to a string. If you change the string that both reference, then that change can be observed from either location. Changing either variable to reference something new is not something the other variable can observe.
Upvotes: 2
Reputation: 101681
It has nothing to do with strings immutability. It's the default behaviour of reference type variables. When you assign a new reference, you are changing the reference value of the variable. The other variables that references to the same location is not affected from that assignment. In your case, when you don't use ref
the reference value of s
will be copied into the parameter
, like this:
string s = "hello"
string parameter = s;
After that if you assign a new reference to parameter
, it will only change where parameter
points to and won't affect s
. when you use ref
there is no copying.In that case you are actually passing a reference rather than a copy of the reference.That's why you can change the where s
points to. And again it's true for all reference types not just string.
Upvotes: 1