为什么必须通过引用传递 String 对象?
Why a String object has to be passed by reference?
据我所知,在 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";}
它将打印 "hello",而不是 "world"。打印"world"的唯一方法是在方法签名中添加关键字ref
并调用
为什么会这样?我的回答(我希望你确认或更正)是在 C# 中,字符串对象是不可变的,所以如果我让 s="world" 实际上,编译器正在创建一个新的字符串对象,但是对该对象的引用字符串 s 没有改变(因为段落是按值)。
事实上,如果我在 method()
调用之前和之后打印 s.getHashCode()
,这两个值是不同的。
你觉得我的解释怎么样?
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:
您没有修改 String
对象。您正在修改 参数 以引用不同的 String
。这只是改变了一个局部变量,不是调用者看到的。
正在按值传递字符串引用,就像正常情况一样。您需要区分更改 参数 的值和修改参数值引用的对象。您会看到与您自己的 class 完全相同的行为,即使它是可变的:
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" };
}
}
现在,如果您在 Method
中更改了 对象 ,例如
static void Method(Person parameter)
{
parameter.Name = "Robin";
}
... 然后 你会看到输出发生了变化。但这不是修改参数。字符串的不可变性相关的唯一原因是,当参数是字符串时,这意味着上面 Method
的第二个版本没有等效项(在安全代码中)。
有关详细信息,请参阅 my article on parameter passing。
它与字符串不变性无关。这是引用类型变量的默认行为。当您分配一个新的引用时,您正在更改变量的引用值。引用同一位置的其他变量不受该分配的影响。在您的情况下,当您不使用 ref
时,s
的参考值将被复制到 parameter
中,如下所示:
string s = "hello"
string parameter = s;
之后,如果您为 parameter
分配新的引用,它只会改变 parameter
指向的位置,不会影响 s
。当你使用 ref
时,没有 copying.In 这种情况你 实际上 传递了一个 reference 而不是reference.That 是您可以更改 s
指向的位置的原因。 再次所有引用类型都是如此,而不仅仅是字符串。
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#).
是的,100% 正确。如果您能够修改实际的 string
实例,那么调用者将能够观察到该更改。
当然,因为string
是不可变的所以您无法修改字符串实例。这就是它不可变的意思。
由于您实际上并没有修改 string
实例,因此调用者实际上没有进行任何修改。
您在代码中所做的不是修改字符串实例,而是修改持有字符串引用的变量。该变量与 main 方法中的局部变量完全不同。修改一个不会影响另一个(除非你使用 ref
)。
你所拥有的是完全不同的变量,每个变量都有一个字符串的引用。如果您更改两者都引用的字符串,则可以从任一位置观察到该更改。更改任一变量以引用新内容不是另一个变量可以观察到的内容。
据我所知,在 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";}
它将打印 "hello",而不是 "world"。打印"world"的唯一方法是在方法签名中添加关键字ref
并调用
为什么会这样?我的回答(我希望你确认或更正)是在 C# 中,字符串对象是不可变的,所以如果我让 s="world" 实际上,编译器正在创建一个新的字符串对象,但是对该对象的引用字符串 s 没有改变(因为段落是按值)。
事实上,如果我在 method()
调用之前和之后打印 s.getHashCode()
,这两个值是不同的。
你觉得我的解释怎么样?
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:
您没有修改 String
对象。您正在修改 参数 以引用不同的 String
。这只是改变了一个局部变量,不是调用者看到的。
正在按值传递字符串引用,就像正常情况一样。您需要区分更改 参数 的值和修改参数值引用的对象。您会看到与您自己的 class 完全相同的行为,即使它是可变的:
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" };
}
}
现在,如果您在 Method
中更改了 对象 ,例如
static void Method(Person parameter)
{
parameter.Name = "Robin";
}
... 然后 你会看到输出发生了变化。但这不是修改参数。字符串的不可变性相关的唯一原因是,当参数是字符串时,这意味着上面 Method
的第二个版本没有等效项(在安全代码中)。
有关详细信息,请参阅 my article on parameter passing。
它与字符串不变性无关。这是引用类型变量的默认行为。当您分配一个新的引用时,您正在更改变量的引用值。引用同一位置的其他变量不受该分配的影响。在您的情况下,当您不使用 ref
时,s
的参考值将被复制到 parameter
中,如下所示:
string s = "hello"
string parameter = s;
之后,如果您为 parameter
分配新的引用,它只会改变 parameter
指向的位置,不会影响 s
。当你使用 ref
时,没有 copying.In 这种情况你 实际上 传递了一个 reference 而不是reference.That 是您可以更改 s
指向的位置的原因。 再次所有引用类型都是如此,而不仅仅是字符串。
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#).
是的,100% 正确。如果您能够修改实际的 string
实例,那么调用者将能够观察到该更改。
当然,因为string
是不可变的所以您无法修改字符串实例。这就是它不可变的意思。
由于您实际上并没有修改 string
实例,因此调用者实际上没有进行任何修改。
您在代码中所做的不是修改字符串实例,而是修改持有字符串引用的变量。该变量与 main 方法中的局部变量完全不同。修改一个不会影响另一个(除非你使用 ref
)。
你所拥有的是完全不同的变量,每个变量都有一个字符串的引用。如果您更改两者都引用的字符串,则可以从任一位置观察到该更改。更改任一变量以引用新内容不是另一个变量可以观察到的内容。