传递字符串作为参数:是复制还是引用?我很困惑

时间:2019-12-24 01:11:04

标签: c#

我一直在阅读值和引用类型以及ref关键字,特别注意这篇文章:C# string reference type?。乔恩·斯基特(Jon Skeet)的回答“对字符串的引用是按值传递的。按值传递引用和按引用传递对象之间有很大的区别。不幸的是,在两种情况下都使用了“引用”一词。即使以他为榜样也使我感到困惑。

考虑一下:

string x = "foo";

void Bar(string s)
{
    Console.Write(s);
}

Bar(x);

我的问题:将x传递到Bar时,s代表内存中x的完整副本还是s指向{{ 1}}?如果x确实很大,这将变得很重要。当我要做的只是将x转换为其他内容(而不更改x本身)时,将ref传递给s会有性能上的好处吗?

3 个答案:

答案 0 :(得分:1)

c#中的所有字符串都是不可变的,因此可以安全地传递指针。在您的示例中,“ foo”是静态常量,它将存在于程序集中的某个位置,并被加载到内存中的固定位置。您正在声明x并分配该位置。然后将该指针传递给Bar,在Bar中还为该变量分配了一个新的局部变量

如果Bar更改s的值,则不会更改x的当前值,因为两个变量都是指针位置的副本。

如果将Bar更改为以s作为参考参数,则s不再是单独的局部变量。取而代之的是x本身的位置将传递到Bar中,并且对s和x的任何更改都将更改同一指针。变量s成为对指向字符串的变量的引用。

答案 1 :(得分:1)

  

将x传递给Bar时,s是否表示x的完整副本   在内存中还是s指向x?

xs都是变量,它们引用内存中的同一String对象-“ Foo”。

  

在以下情况下通过ref传递x会带来性能上的好处   我要做的就是将s转换为不同的东西(没有   改变自己?)

使用s关键字传递ref参数可让您通过分配新的String(或null)来将x变量分配给内存中的另一个String对象(或null)。 s参数。但是没有性能差异,因为在两种情况下,仅复制一个地址(分别为字符串“ Foo”的地址或变量x的地址)-字符串“ Foo”的内容没有被复制。

答案 2 :(得分:1)

  

“当将x传递给Bar时,s代表内存中x的完整副本还是s指向x的指针。”

x是对“ foo”的引用,而不是“ foo”的完整副本。

完成时

  

Bar(x)

x是通过值传递的(即x的副本不是通过x本身传递的),因此您在Bar中所做的任何操作都不会更改x所指的含义。如果您想让Bar更改x的含义,则必须使用ref关键字通过引用传递它。这需要更改Bar的签名,如下所示:

  

void Bar(引用字符串s){}

然后您可以将其称为:

  

Bar(ref x)

在这种情况下通过引用传递与

无关
  

性能优势

而是实现期望的目标(即更改x所指的内容)。