Strings that do not behave as a reference type

Today I learned about value types and reference types.

I have one doubt in the code example below:

class Program { static void Main(string[] args) { StringBuilder sb = new StringBuilder(); FunctionSB(sb); Console.WriteLine(sb); //sb updated customer c = new customer(); FunctionClass(c); Console.WriteLine(cs);//updated class value String str = ""; FuntionString(str); Console.WriteLine(str);// } private static void FunctionSB(StringBuilder sb) { sb.Append("sb updated"); } private static void FunctionClass(customer c) { cs = "updated class value "; } static void FuntionString(String str) { str = "updated value"; } } class customer { public string s; } 

Here the value of the builder string and the value of the variable of the class member is updated, but why is FuntionString(str); doesn't update str value? (Why is this not passed as a link?)

+7
pass-by-reference c #
source share
4 answers

It is important for me to distinguish between a variable and an object.

Consider the code:

 String str = ""; FuntionString(str); 

str is a variable. First, the value of this variable is a string reference. Let's say that this link is number 246. Line 246 can be resolved to a value; this value is an empty character array.

Then we pass the value of this variable to FuntionString . We do not pass a reference to the str variable, we just pass the number 246. This is a copy of this link or number.

Inside this function, it has a completely different variable, which is also called str . The fact that the identifier is the same does not change the fact that it is another variable that simply has the same value.

When you change the str variable inside a FuntionString , you do not change the str variable from Main . After the body of the FuntionString ends, the str from Main is still held on reference 246, as before, and the variable str inside the FuntionString is set to some new link, let’s say 3, a newline with the value "updated value" . This variable change is not reflected in Main .

In the case of FunctionSB the method implementation does not actually change the sb variable . Instead of modifying a variable, it mutates the object referenced by the variable. In this case, sb points to an object in some place, say 39. sb in the main method and in this other method are two different variables with a copy of the same link. The method does not change the sb variable; instead, it changes the sb object at location 39. The two sb objects still have the same value; they do not change, but both of them point to the same object that has changed. Thus, a mutation performed using the method can be observed from Main .

If, from the definition of FuntionString you changed the string object that both variables pointed to, instead of changing the variable itself, then the change will be "observable" from the caller. Of course, this is not possible because strings are immutable. A method cannot mutate an object so that the caller can observe.

+6
source share

To understand that when you write str = "updated value"; , you are actually creating a new object. That is, you have completed the equivalent:

 str = new string("updated value"); 

This means that when you write str = "updated value" you assign a new object to the "str" ​​link without modifying the existing object. **

So, the correct comparison point with respect to the client class is not this:

 cs = "updated class value"; 

But rather:

 c = new customer { s = "updated class value" }. 

The source object referenced earlier that contains "c" or "str" ​​is therefore not changed.


What you need to do in the case of OP is to pass the link to the string using the ref keyword:

 static void FuntionString(ref String str) { str = "updated value"; } 

The difference here is that the link itself is updated inside the FunctionString and now points to a new string object.


** Please note that since . String strings are immutable , this will always be true. You cannot change a string object only to create a new one and reassign it. To reinstall it a little differently: yes, the string is passed by reference, but since the type of the string is immutable, you still cannot use this link to modify the object in any way.

+4
source share

When you use StringBuilder, you mutate the instance of the StringBuilder instance. This is the same object because the value is a reference to the same StringBuilder object.

Consider this:

 StringBuilder sb = new StringBuilder(); //sb is a variable to a string builder //cat is a difference reference than sb, but both values are references that point to the same string builder. private static void FunctionSB(StringBuilder cat) { cat.Append("sb updated"); } 

However, with your string example, you are not modifying the same string instance, you are modifying the value as a reference to the difference.

 static void FuntionString(String str) { str = "updated value"; } 

This example above replaces the value that str refers to. This is not a unique string behavior; StringBuilder behaves the same. This shows the same problem as String:

 private static void FunctionSB(StringBuilder sb) { sb = new StringBuilder(); } 

The above will not modify the string constructor that is passed to FunctionSB . As others have noted, you can use ref to solve this problem, since you want to change the link itself.

+1
source share

A string in C # is a built-in data type. If you want to pass a value so that you can rename (you cannot change, replace, strings are immutable), you need an out modifier:

  static void FuntionString(out String str) { str = "updated value"; } 

This is essentially the same as passing it by reference. The only difference is that when using out, your string must be initialized. If you cannot be sure of this, use the link instead.

0
source share

All Articles