Это System.Массив.Clone() гарантированно клонирует типы значений?

#c# #.net #language-specifications #system.array

#c# #.net #язык-спецификации #system.array

Вопрос:

 int[] array1 = new[] { 1, 2, 3 };
int[] array2 = (int[])array1.Clone();

array2[0] = 9;

Debug.Assert(array1[0] != array2[0]);
  

Это работает нормально. Clone() выполняется неглубокая копия, но типы массивов являются типами значений, поэтому они тоже клонируются.

Мой вопрос в том, является ли это явным в спецификации языка или это просто артефакт текущей реализации?

Мои сомнения связаны с System.Array поддержкой типов значений «невидимо» за кулисами с помощью обобщений во время выполнения. Глядя на общедоступные методы, можно ожидать, что типы значений будут помещены в коробку.

Комментарии:

1. Почему вы ожидаете, что типы значений будут помещены в коробку?

2. Значения типа значения ведут себя как значения, а не ссылки. Это не изменится внезапно, если сохранить их в массиве. Или любой другой тип класса. Конечно, очень по дизайну.

Ответ №1:

Это работает, потому что абсолютно невозможно, чтобы два массива могли использовать один и тот же экземпляр типа значения.

В спецификации конкретно не указано, как Array.Clone ведет себя с типами значений по сравнению с тем, как он ведет себя со ссылочными типами. Но в спецификации указано, что экземпляры типов значений копируются побитово при назначении. Поэтому при array1[i] копировании в array2[i] вы получаете клон экземпляра по индексу i . Всегда.

Однако имейте в виду, что если тип значения имеет поле ссылочного типа, будет скопирована только ссылка, а не экземпляр ссылочного типа.

мой вопрос заключался в том, будет ли потенциальный бокс по массиву отрицать это. т.е. копируются ссылки в штучной упаковке, а не базовый тип значения.

Даже если array1[i] он был помещен в коробку во время клонирования, его нужно было бы распаковать, чтобы в итоге вы получили a int[] , а не an object[] . Значение будет клонировано при распаковке.

Комментарии:

1. Я согласен с тем, что назначения типов значений копируются по битам, но мой вопрос заключался в том, будет ли потенциальный бокс по массиву отрицать это. т.е. копируются ссылки в штучной упаковке, а не базовый тип значения.

2. @GazTheDestroyer Я обновил свой ответ. Но опять же, это сводится к тому, что я сказал в первом предложении: «нет абсолютно никакого способа, чтобы два массива могли использовать один и тот же экземпляр типа значения». Экземпляр типа значения находится внутри его контейнера. Итак, если у вас есть два контейнера ( array1 и array2 ), и у каждого контейнера есть свое собственное пространство памяти, an int не может находиться в двух местах одновременно.

3. Да, спасибо за ваши разъяснения. Я поиграл с некоторым кодом и понял, что суть моего замешательства заключалась в том, что я думал, что есть какой-то способ обновить «содержимое» значения в штучной упаковке без изменения самой ссылки. Вы не можете, он просто получает новое «поле».