为什么字符串变量在函数内部修改时不会改变,但是List会改变

时间:2015-07-23 22:46:01

标签: java c# string list arraylist

想象一下这种情况:

你有一个字符串,并调用一个函数来接收这个字符串作为参数并更改函数内的值。函数外部的字符串值不会更改,只会在函数内部更改。

但是,如果您使用List<string> List<string>内容对其进行修改,则会在函数外部进行修改。

为什么会这样?

查找此代码以获取回购:

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");
    }
}

结果是:text仍然是“文字”,但list有一个新元素。

enter image description here

我使用字符串vs List在C#中测试它,在Java中使用字符串vs具有相同行为的ArrayList测试它。

2 个答案:

答案 0 :(得分:3)

  

你有一个字符串并且调用一个函数来接收这个字符串作为参数并更改函数内的值。

从技术上讲,您无法更改字符串的,因为字符串是不可变的。他们无法改变它们。您只能创建一个新字符串并更改变量,使其指向新字符串。

这是text = "new value";的作用。它会创建一个全新的String对象,并更改变量text,使其指向新的String。原始字符串仍在内存中,而指向它的任何其他变量仍然指向它。

这就是原因:

  

函数外部的字符串值不会更改,只会在函数内部更改。

因为当您调用该函数时,您传递了名为text的引用的副本。在函数内部,您将函数的引用副本更改为指向其他字符串,但外部引用不受影响。

  

但是,如果您使用List<string> List<string>内容对其进行修改,则会在函数外部进行修改。

不,如果你为一个List<string>的引用分配一个新值,那么这个改变只发生在函数内部。

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

你不会在功能之外看到这种变化。

您实际在做的是改变现有列表:

myList.Add("new item");

这是string无法做到的事情。 string类上没有允许您修改字符串的函数。如果有,那么将在函数外部显示

答案 1 :(得分:-1)

这是因为如何为该类实现“赋值”运算符...

请考虑以下代码:

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);
        }

    }
}

在这种情况下,在操作原始“列表”时,不会更改原始String对象“text”。原因很简单,String类每次创建一个新对象,所以当我们编写

String anotherString = text;

我们实际上是在那个时间点创建一个值等于“text”的新String对象,这是由于赋值运算符在String类中重载。但是,当我们写作

List<string> anotherList = list;

我们只是创建了原始“list”对象的另一个引用。请注意,在此赋值中不会创建新对象,并且两个引用都引用同一对象。

(方法参数也使用赋值操作初始化参数)