Почему передача строки в метод ведет себя иначе, чем List‹object›, если они оба являются ссылочными?

Я читал код, который заставил меня остановиться на какой-то строке:

List<object> props = new List<object>();
DoWork(param1, param2, props);
//props.Count grew up

Я думал, что изменение переменной за пределами ее области действия требует передачи ее как out или ref, но потом я понял, что если только метод DoWork не изменит ссылку props, например:

props = new List<object>();

ссылка будет указывать на то же место. Так что здесь нет необходимости использовать ref.

а затем я создал метод для типа string:

static void ChangeMe(string str)
{
    str = "W77";
}
public static void Main(string[] args)
{
    string str = "p1";
    ChangeMe(str);
    //str is still "p1"
}

Если поведение, побуждающее List быть измененным за пределами его области, заключается в том, что это ссылочный тип, почему string не изменяется, если он не перераспределяется в вызываемом методе и является ссылочным типом, таким как List<object>?


person mshwf    schedule 29.07.2017    source источник


Ответы (2)


Причина в том, что string является неизменяемым типом в C#, и поэтому всякий раз, когда вы «меняете» его, на самом деле вы создаете новый string с новым значением и ссылаетесь на него.

При вызове ChangeMe создается новая ссылка на ту же строку. Затем в методе вы ссылаетесь на новую ссылку на совершенно новую строку, которая не влияет на предыдущую строку, определенную в Main.

person Gilad Green    schedule 29.07.2017

В функции ChangeMe у вас есть локальная копия ссылки на объект, который вы передали. Когда вы сохраняете что-то в str, вы фактически заменяете эту ссылку новой. Неизменяемость здесь не играет роли, потому что на самом деле вы не пытались изменить объект, на который ссылается str. Итак, теперь у вас есть новая ссылка, хранящаяся в str, которая указывает на новый объект, созданный строковым конструктором, когда вы используете строковый литерал "W77". И, как вы указали, вы можете получить это за пределами функции с помощью ref или out.

person Luboš Hemala    schedule 29.07.2017