我一直在阅读值和引用类型以及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
会有性能上的好处吗?
答案 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?
x
和s
都是变量,它们引用内存中的同一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所指的内容)。