Передача параметров массива в C #: почему это неявно по ссылке? - PullRequest
7 голосов
/ 31 августа 2010

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

class ProgramInt
{
    public static void Test(int i) // Pass by Value
    {
        i = 2; // Working on copy.
    }

    static void Main(string[] args)
    {
        int i = 1;
        ProgramInt.Test(i);
        Console.WriteLine(i);
        Console.Read();

        // Output: 1
    }
}

Теперь, чтобы эта функция работала должным образом, нужно добавить ключевое слово ref как обычно:

class ProgramIntRef
{
    public static void Test(ref int i) // Pass by Reference
    {
        i = 2; // Working on reference.
    }

    static void Main(string[] args)
    {
        int i = 1;
        ProgramInt.Test(ref i);
        Console.WriteLine(i);
        Console.Read();

        // Output: 2
    }
}

Теперь я озадачен тем, почему члены массива при передаче в функции неявно передаются по ссылке. Разве массивы не являются типами значений?

class ProgramIntArray
{
    public static void Test(int[] ia) // Pass by Value
    {
        ia[0] = 2; // Working as reference?
    }

    static void Main(string[] args)
    {
        int[] test = new int[] { 1 };
        ProgramIntArray.Test(test);
        Console.WriteLine(test[0]);
        Console.Read();

        // Output: 2
    }
}

Ответы [ 6 ]

16 голосов
/ 31 августа 2010

Нет, массивы являются классами, что означает, что они являются ссылочными типами.

2 голосов
/ 31 августа 2010

Хороший способ запомнить это:

  • "ref" создает псевдоним для переменной
  • массив - это набор переменных ; каждый элемент является переменной.

Когда вы передаете массив нормально, вы передаете набор переменных . Переменные в коллекции не меняются.

Когда вы передаете массив с "ref", вы даете новое имя переменной, содержащей массив .

Когда вы обычно передаете элемент массива, вы передаете значение в переменной .

Когда вы передаете элемент массива - переменную - с помощью "ref", вы даете новое имя этой переменной .

Имеет смысл?

2 голосов
/ 31 августа 2010

Массивы не передаются по ссылке. Ссылки на массивы передаются по значению. Если необходимо изменить массив WHAT, на который указывает переданная переменная массива (например, для изменения размера массива), переменная должна быть передана по ссылке.

1 голос
/ 31 августа 2010

Можете ли вы представить передачу 2-миллионного массива элементов по значению? Теперь представьте, что тип элемента decimal. Вам придется скопировать около 240 МБ 30,5175781 МБ данных.

0 голосов
/ 31 августа 2010

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

0 голосов
/ 31 августа 2010

Как указано ссылка MSDN , массивы - это объекты ( System.Array - абстрактный базовый тип всех массивов ), и объекты передаются по ссылке.

...