-1

Imagine this situation:

You have a string, and called a funtion that recieves this string as parameter and change the value inside the funtion. The string value outside the function does not change, only change inside the function.

But if you do the same with a List<string> the List<string> content its modified outside the function.

Why this happen?

Look up this code for a repo:

using System;
using System.Collections.Generic;

class Program
{
    static void Main()
    {
        List<string> list = new List<string>();
        list.Add("1");
        string text = "text";
        ChangeSomethingInText(text);
        Console.WriteLine(text);
        ChangeSomethingInList(list);
        foreach (var i in list)
        {
            Console.WriteLine(i);
        }
    }


    public static void ChangeSomethingInText(string text)
    {
        text = "Text changed";
    }

    public static void ChangeSomethingInList(List<string> myList)
    {
         myList.Add("From change");
    }
}

This is the result: text is still "text", but list has a new element.

enter image description here

I tested it in C# with a string vs List and in Java with a String vs an ArrayList with the same behavior.

Ricardo Polo Jaramillo
  • 11,413
  • 12
  • 50
  • 79
  • Look at the docs for [passing by value](https://msdn.microsoft.com/en-us/library/9t0za5es.aspx) – Buddy Jul 23 '15 at 22:48
  • If you did `myList = new List` and then examined it, you would see the same effect, as the others have said, this is pass by value vs pass by reference issue. – Ron Beyer Jul 23 '15 at 22:50
  • @Sotirios et al: the posted duplicate question isn't a good one: the interesting point here has to do with _strings_ and not generally _pass by reference_. this is a better question to look at: http://stackoverflow.com/questions/10792603/how-are-strings-passed-in-net – pb2q Jul 23 '15 at 22:50
  • @pb2q I don't see any difference. Whether it's a `String` or any other type, the behavior would be the same. It's assignment vs derenferencing and method invocation. The immutability of a type has nothing to do with it. – Sotirios Delimanolis Jul 23 '15 at 22:54
  • So... If I understand well, depending of the Type of the variable is passed in a different way? – Ricardo Polo Jaramillo Jul 23 '15 at 22:55
  • `=` is completely different to `.Add`. Strings are immutable. If they weren't, and you could do `text.Append("a")`, then you'd see the same behaviour as the list. – Blorgbeard Jul 23 '15 at 22:56
  • @RicardoPolo no. String and List are *both* reference types. The operations `text = "text changed"` and `myList.Add("change")` are different things. You are not comparing apples and apples. – Blorgbeard Jul 23 '15 at 22:58
  • @Ricardo, maybe this will help you: http://stackoverflow.com/questions/10792603/how-are-strings-passed-in-net – pb2q Jul 23 '15 at 23:03
  • 1
    @SotiriosDelimanolis sorry: I read the question too hastily. It is simply a matter of trying to change a passed-by-value reference. I retract my comment: your original dup was fine – pb2q Jul 23 '15 at 23:17

2 Answers2

3

You have a string and called a function that receives this string as parameter and change the value inside the function.

Technically, you can't change the value of a string, because strings are immutable. They have no way for you to change them. You can only create a new string and change your variable so it points to the new string.

This is what text = "new value"; does. It creates an entirely new String object and changes the variable text so that it points to the new String. The original string is still in memory somewhere, and any other variables that point to it still point to it.

Which is why:

The string value outside the function does not change, only change inside the function.

Because when you called the function, you passed a copy of the reference called text. Inside the function, you changed the function's copy of the reference to point to some other string, but the outside reference is unaffected.

But if you do the same with a List<string> the List<string> content its modified outside the function.

Nope, if you assign a new value to a reference to a List<string>, then that change only happens inside the function.

myList = new List<string>() { "new list" };

You won't see this change outside the function.

What you are actually doing is mutating the existing list:

myList.Add("new item");

This is something that you can't do to a string. There are no functions on the string class that let you modify a string in place. If there were, then those changes would be visible outside the function.

Sotirios Delimanolis
  • 252,278
  • 54
  • 635
  • 683
Blorgbeard
  • 93,378
  • 43
  • 217
  • 263
  • It bothers me that you posted this while repeating the same things posted in the answers [here](http://stackoverflow.com/questions/40480/is-java-pass-by-reference-or-pass-by-value). Everything in your answer is there. A duplicate is not about the question, it is about the content providing an answer to the question. That's why the duplicate label states _This question already has an answer here_. – Sotirios Delimanolis Jul 23 '15 at 23:10
  • Well, that question is tagged `java`, whereas this code is C#. And this question is not really about pass-by-reference vs. pass-by-value, but the difference between assigning references vs. modifying values. – Blorgbeard Jul 23 '15 at 23:13
  • Again, it's not about the question, it's about the answers. The answers there explain the difference between a reference value, an object, and a variable as well as the difference between mutating an object and reassigning a variable. I believe C# behaves the same as Java for reference types when `out` and `ref` aren't involved. – Sotirios Delimanolis Jul 23 '15 at 23:14
  • 1
    Sorry for the DV. Your answer is fine. I just think it's unnecessary. – Sotirios Delimanolis Jul 23 '15 at 23:18
  • 1
    Although the same information may be contained in the linked q+a, it's also contained in MSDN and presumably the javadocs. The purpose of my answer is to marshal information into an answer to the specific question asked. It's not *just* about the answers, it *is* also about the question, and I don't think the linked question is close enough to this one. – Blorgbeard Jul 23 '15 at 23:20
-1

This is because how "assignment" operator is implemented for that class...

Consider the code below:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;


class Program
{
    static void Main(string[] args)
    {
        List<string> list = new List<string>();
        list.Add("1");
        String text = "text";

        //Change Something In anotherText
        String anotherString = text;
        anotherString = "another String Changed";
        Console.WriteLine(text);

        //Change Something In anotherList
        List<string> anotherList = list;
        anotherList.Add("added in another List");

        foreach (var i in list)
        {
            Console.WriteLine(i);
        }

    }
}

In this case also, original String object "text" will not be changed while the original "list" is manipulated. Reason is simple, String class creates a new object every-time an assignment is made, so when we write

String anotherString = text;

we are essentially creating a new String object with value equal to "text" at that point of time, this is due to the assignment operator overloading in String class. But, when we write

List<string> anotherList = list;

we are merely creating another reference of original "list" object. Note that no new object is created in this assignment and both the references are referring to same object.

(method parameters also use assignment operation to initialize the parameters)

Charchit
  • 11
  • 1