Самый краткий ответ: прочитайте мою статью о передаче параметров , в которой достаточно подробно.
Немного более длинный ответ - сравнить эти два метода, каждый из которых использует значение параметры:
public void ChangeMe(string x)
{
x = "changed";
}
public void ChangeMe(Person x)
{
x.Name = "changed";
}
В первом случае вы изменяете значение параметра . Это полностью изолировано от первоначального аргумента. Вы не можете изменить содержимое самой строки, потому что строки неизменны.
Во втором случае вы изменяете содержимое объекта, значение параметра которого относится к . Это не меняет значение самого параметра - это будет та же самая ссылка. Например, если кто-то доставляет в ваш дом что-то, что меняет содержимое вашего дома, но не меняет адрес вашего дома.
Если вы изменили второй метод на этот:
public void ChangeMe(Person x)
{
x = new Person("Fred");
}
тогда звонящий не увидит никаких изменений. Это ближе к тому, что вы делаете со строкой - вы заставляете параметр ссылаться на другой объект, а не изменяете содержимое существующего объекта.
Теперь, когда вы используете параметр ref
, переменная, используемая вызывающей стороной в качестве аргумента, «связывается» с параметром - так что если вы измените значение параметра, это также изменит значение аргумента , Так что, если мы изменим последний метод следующим образом:
public void ChangeMe(ref Person x)
{
x = new Person("Fred");
}
, то:
Person y = new Person("Eric");
ChangeMe(ref y);
Console.WriteLine(y.Name);
это выведет "Fred".
Ключевая концепция, которую нужно понять, состоит в том, что значение переменной никогда не является объектом - это либо значение типа значения, либо ссылка. Если данные объекта изменены, это изменение будет видно через другие ссылки. Как только вы поймете, что копирование ссылки - это не то же самое, что копирование объекта, все остальное становится довольно легко.