Типы ссылок передаются «ссылка по значению» в .NET.Это означает, что присвоение другого значения фактическому параметру фактически не меняет исходного значения (если вы не используете ByRef / ref).Однако все, что вы делаете для изменения фактического объекта, который передается, изменит объект, на который ссылается вызывающий метод.Например, рассмотрим следующую программу:
void Main()
{
var a = new A{I=1};
Console.WriteLine(a.I);
DoSomething(a);
Console.WriteLine(a.I);
DoSomethingElse(a);
Console.WriteLine(a.I);
}
public void DoSomething(A a)
{
a = new A{I=2};
}
public void DoSomethingElse(A a)
{
a.I = 2;
}
public class A
{
public int I;
}
Вывод:
1
1
2
Метод DoSomething
назначил своему параметру a
другое значение, но этот параметр простолокальный указатель на местоположение оригинала a
из вызывающего метода.Изменение значения указателя ничего не изменило для изменения значения a
вызывающего метода.Однако DoSomethingElse
фактически внес изменение в одно из значений в объекте, на который ссылаются.
Независимо от того, что говорят другие ответчики, string
не является исключительным в этом смысле.Все объекты ведут себя таким образом.
Где string
отличается от многих объектов тем, что он неизменен: там нет никаких методов или свойств или полей в строке, которые вы можете вызвать на самом делеизменить строку.Как только строка создается в .NET, она доступна только для чтения.
Когда вы делаете что-то вроде этого:
var s = "hello";
s += " world";
... компилятор превращает это в нечто вроде этого:
// this is compiled into the assembly, and doesn't need to be set at runtime.
const string S1 = "hello";
const string S2 = " world"; // likewise
string s = S1;
s = new StringBuilder().Append(s).Append(S2).ToString();
Эта последняя строка генерирует новую строку, но S1 и S2 все еще находятся вокруг.Если они являются постоянными строками, встроенными в сборку, они останутся там.Если они были созданы динамически и на них больше нет ссылок, сборщик мусора может отменить их, чтобы освободить память.Но ключ должен понять, что S1 фактически никогда не изменялся.Переменная, указывающая на нее, просто изменилась, чтобы указывать на другую строку.