Список объектов коллекции как параметр метода - PullRequest
0 голосов
/ 19 декабря 2010

Может ли кто-нибудь объяснить, как выполняется распределение памяти при вызове метода, имеющего в качестве параметра коллекцию списков. Поскольку приведенный ниже фрагмент кода, по-видимому, выглядит так же, но он не является таким же. Поэтому я хотел бы знать разницу в вызове обоих методов с точки зрения выделения памяти.

using System;
using System.Collections.Generic;
namespace ListSample
{
    class ListSampleClass   
    {
        static void Main(string[] args)
        {
            List<int> i = new List<int>();
            i.Add(10);
            i.Add(15);
            SampleMethod1(i);
            Console.WriteLine("Result of SampleMethod1:"+i[0]);
            SampleMethod2(i);
            Console.WriteLine("Result of SampleMethod2:" + i[0]);
            Console.ReadKey();
        }

        public static void SampleMethod1(List<int> i)
        {
            List<int> j = new List<int>();
            j.Insert(0,20);
            i = j; 
        }

        public static void SampleMethod2(List<int> i)
        {
            List<int> j = new List<int>();            
            j = i;
            j.Insert(0, 20);
        }
    }
}

1 Ответ

6 голосов
/ 19 декабря 2010

Если не указано ref или out, параметры передаются по значению. Для ссылочных типов это означает, что ссылка на объект (в данном случае List<int>) передается по значению.

«Передать по значению» означает, что аргумент (выражение в вызывающем операторе) вычисляется, а затем результирующее значение копируется в параметр (переменная, указанная в подпись метода). Любые дальнейшие изменения параметра, с точки зрения присвоения ему нового значения, не видны вызывающей стороной. (Но продолжайте читать ...)

Это означает, что при первом вызове метода:

public static void SampleMethod1(List<int> i)
{
    List<int> j = new List<int>();
    j.Insert(0,20);
    i = j; 
}

вы создаете новый список, вставляете в него значение, а затем копируете ссылку на этот новый список в i - но это никак не влияет . Параметр фактически является просто другой локальной переменной - изменение значения самой переменной не влияет на вызывающую функцию.

Теперь сравните это со вторым методом:

public static void SampleMethod2(List<int> i)
{
    List<int> j = new List<int>();            
    j = i;
    j.Insert(0, 20);
}

Это создает новый список, а затем сразу же игнорирует его, вместо этого присваивая ссылку на переданный список (как i) j. Затем он вставляет значение в список. Конечным результатом этого метода является то, что значение вставляется в список. Это эквивалентно:

public static void SampleMethod2(List<int> i)
{
    i.Insert(0, 20);
}

Обратите внимание, что не меняет значение параметра. Он вносит изменения в объект, к которому относится значение параметра. Это решающее различие, чтобы понять.

У меня есть статья о передаче параметров и еще одна о типах ссылок и значений , которая может помочь вам понять это подробнее.

...