为什么必须通过引用传递String对象?

jus*_*rld 3 c# pass-by-reference pass-by-value

在C#中,据我所知,方法调用期间参数的传递是按值进行的.但是当您使用对象作为参数时,您传递的是对象本身的引用.这意味着如果您访问(并修改)对象内部字段的值,则一旦方法调用完成,也将看到更新.

因此,如果我在方法中修改String的值,则应在方法调用终止时修改它(因为String是C#中的对象).但事实并非如此,事实上如果我写:

public static void main (String []args){
  String s= "hello";
  method(s);
  System.Console.Writeline(s);
}

public void method (String s)
{s = "world";}
Run Code Online (Sandbox Code Playgroud)

它将打印"你好",而不是"世界".打印"世界"的唯一方法是ref在方法签名和调用中添加关键字.

为什么会这样?我的答案(我希望你确认或纠正)是在C#中String对象是不可变的,所以如果我使s ="world"实际上编译器正在创建一个新的字符串对象,但是对象的引用是不会改变(因为通过是值).

事实上,如果我s.getHashCode()method()通话前后打印,这两个值是不同的.

你怎么看待我的解释?

Jon*_*eet 6

因此,如果我在方法中修改String的值,则应在方法调用终止时修改它(因为String是C#中的对象).但事实并非如此,事实上如果我写:

你没有修改String对象.您正在修改参数以引用其他参数String.这只是改变一个局部变量,而不是由调用者看到.

正如值一样,String引用按值传递.您需要区分更改参数的值和修改参数值引用的对象.您将看到与您自己的类完全相同的行为,即使它是可变的:

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" };
    }
}
Run Code Online (Sandbox Code Playgroud)

现在,如果Method您在对象中进行了更改,例如

static void Method(Person parameter)
{
    parameter.Name = "Robin";
}
Run Code Online (Sandbox Code Playgroud)

... 然后你会看到输出的变化.但那不是修改参数.字符串不变性相关的唯一原因是它意味着Method当参数是字符串时,上面的第二个版本没有等效(在安全代码中).

有关详细信息,请参阅有关参数传递的文章.

  • @justHelloWorld:我说'main`中`s`的值被复制到`method`中的`s`,因为这是值传递的意思.然后在方法中为`s`分配一个新值,这不会改变`main`中`s`的值,因为这是值传递的意思.你需要明白`s`的值是*不是*一个字符串,它是一个引用......其余的都是直截了当的.(想象一下,你有`int`值 - 你不会指望``方法`中的`s = 10`来改变`main`中`s`的值,对吗?) (3认同)
  • 这涉及字符串的不变性。不是参数传递。 (2认同)