Не передается ссылка на массив С#

Массив ссылочный тип данных, и если мы присвоим один массив другому, то передастся ссылка. (по идее)

        static void Main(string[] args)
        {
            int[] nums1 = new int[] { 9 ,10,10,15,0,0,0,0};
            int[] nums2 = new int[] { 10, 11, 12, 12 };
            Merge(nums1,nums2);
            foreach (int i in nums1)
            {
                Console.WriteLine(i);
            }
        }
        static public void Merge(int[] nums1, int[] nums2)
        {
            int[] newNums = new int[nums1.Length];
            ...
            nums1 = newNums;
        }

И после выхода из такого вида метода nums1 не поменялся. Объясните почему массив ведет себя так. И я смотрел по отладчику, что nums1 был равен newNums до выхода из метода. Но после выхода nums1 стал равен первоначальному. Если через чикл присвоить те же значения, или передать через ref,то все будет в порядке.


Ответы (3 шт):

Автор решения: CREAsTIVE

Переменная nums1 является локальной которая хранит ссылку на объект массива в памяти.

Передавая массив nums1 в метод значение переменной копируется, т. е. копируется только то, что хранится в самой переменной, а именно - ссылка, а не сам массив. Изменив скопированную ссылку оригинал не поменяется. Если же вы измените сам массив (а не создадите новый), то изменится как раз таки содержимое оригинального массива.

В C++ аналогичной записью будет:

int fn(int* arr) {arr = new int[] {...};}

arr = new int[] {...};
fn(arr);

Параметр ref в свою очередь передаёт значение по ссылке. Т. к. значение nums1 - ссылка, то с помощью ref передаётся ссылка на ссылку (на адресс в памяти, хранящий список значений).

В C++ аналогичной записью будет:

int fn(int** arr) {*arr = new int[] {...};}

arr = new int[] {...};
fn(&arr);

Или просто

int fn(int*& arr) {arr = new int[] {...};}

arr = new int[] {...};
fn(arr);

P. S.: Вы всё равно создаёте новый массив, так почему бы его не возвращать через return? Это гораздо понятнее и логичнее.

→ Ссылка
Автор решения: Faraday

Используйте ключевое слово ref. Вот так будет выглядеть ваш метод в этом случае:

static public void Merge(ref int[] nums1, int[] nums2)
{
    int[] newNums = new int[nums1.Length];
    ...
    nums1 = newNums;
}

Либо возвращайте какой-то результат работы вашего метода:

static public int[] Merge(int[] nums1, int[] nums2)
{
    int[] newNums = new int[nums1.Length];
    ...
    return newNums;
}

static void Main(string[] args)
{
    int[] nums1 = new int[] { 9 ,10,10,15,0,0,0,0};
    int[] nums2 = new int[] { 10, 11, 12, 12 };
    int[] result = Merge(nums1,nums2);
    foreach (int i in result)
    {
        Console.WriteLine(i);
    }
}

 
→ Ссылка
Автор решения: maeril

Для передачи массива по ссылке используется ключевое слово ref. Попробуй передать массив через него:

        static public int[] Merge(ref int[] nums1, int[] nums2)
        {
            // Пример: создадим новый массив и переназначим переменной nums1
            nums1 = new int[nums1.Length];
            // Заполняем новый массив какими-либо значениями (например, нулями)
            Random rnd = new Random();
            for (int i = 0; i < nums1.Length; i++)
            {
                nums1[i] = rnd.Next(-10, 10);
            }
            return nums1;
        }

        static void Main(string[] args)
        {
            int[] nums1 = new int[] { 9, 10, 10, 15, 0, 0, 0, 0 };
            int[] nums2 = new int[] { 10, 11, 12, 12 };

            // При вызове метода добавляем ключевое слово "ref"
            int[] result = Merge(ref nums1, nums2);

            // Теперь массив nums1 переназначен внутри метода и это изменение видно здесь:
            foreach (int i in result)
            {
                Console.WriteLine(i);
            }
        }
→ Ссылка