1

Обучаюсь языку C#. В процессе его "ковыряния" возник вопрос: почему при передаче массива в метод его изменение отображается во внешнем контексте, а у строки нет, хотя и то и другое - ссылочные типы?

Изменение Массива

Изменение строки

  • 2
    Потому что в первом случае вы меняете сам массив, а во втором только ссылку на строку, сама строка остается без изменений – tym32167 Jan 27 '21 at 18:53
  • @tym32167, как это - меняю ссылку на строку? – HadntSeenASunlight Jan 27 '21 at 18:54
  • С таким же успехом вы в первом случае можете написать a = new int[100]; и поглядеть результат – tym32167 Jan 27 '21 at 18:54
  • 2
    Ссылочная переменная хранить ссылку на объект. Это как дом и адрес дома - дом это значение объекта, а адрес - это бумажка с адресом где дом находится. Вот тут a = "abc"; вы просто на бумажке с адресом стираете старый адрес дома и пишете новый адрес нового дома, при этом сами дома никак не меняются – tym32167 Jan 27 '21 at 18:57
  • 2
    Вот это же a[0]=5; означает пойди по адресу на бумажке а, зайди в первую квартиру и запиши туда 5 - то есть эта операция меняет значение в массиве, потому вы видите это изменение. – tym32167 Jan 27 '21 at 18:59
  • 1
    @tym32167, спасибо большое за объяснение, разложили всё по полочкам. – HadntSeenASunlight Jan 27 '21 at 19:00
  • 1
    к строке вы тоже можете обращаться как к массиву из char, но только на чтение char c = text[3], а вот наоборот присвоить не получится, потому что строка - неизменяема. – aepot Jan 27 '21 at 19:55
  • Дубликат? https://ru.stackoverflow.com/a/267076/10105 – VladD Jan 27 '21 at 21:31
  • @VladD Как по мне - дубликат, в этой части различий между java и C# не вижу, строки и там и там иммутабельные. Спросил в чате, нормально ли что ЯП разные, а так вообще не вижу препятствий. – A K Jan 28 '21 at 07:24
  • @VladD не дубликат. тут вопрос про передачу параметров, а не про неизменяемость строк - автор же не пытается поменять содержимое строки, присваивает новую. и в принципе ответ "вы меняете саму ссылку на объект, а не заменяете что-то внутри объекта, используйте ref чтобы изменение ссылки отобразилось во внешнем контексте" был бы уместен. А там - точно нет. –  Jan 29 '21 at 13:44

1 Answers1

5

Поменять массив внутри метода не получится, посмотрите:

void Main()
{
    var arr = new int[] { 1, 2, 3 };
    Test1(arr);
    arr.Dump();
}

private void Test1(int[] arr) { arr = null; }

Выведет:

введите сюда описание изображения

А вот в вашем примере вы меняете не массив, а его элементы - а внутри массива у вас значимый тип (int), он заменяется.

Аналогично и с другими ссылочными типами:

void Main()
{
    var book = new Book { Id = 1, Title = "asdf"}; 
    Test1(book);
    book.Dump();
}

private void Test1(Book book) { book.Id = 2; book = null; }

public class Book { public int Id { get; set; } public string Title { get; set; } }

введите сюда описание изображения

Со строками такой вариант не проходит, потому что строки в C# - неизменяемый тип.

A K
  • 28,718