Передача параметров ссылочного типа (Руководство по программированию в C#)Passing Reference-Type Parameters (C# Programming Guide)

Переменная ссылочного типа содержит не сами данные, а ссылку на них.A variable of a reference type does not contain its data directly; it contains a reference to its data. При передаче параметра ссылочного типа по значению можно изменять данные, относящиеся к объекту, на который указывает ссылка, например, значение члена класса.When you pass a reference-type parameter by value, it is possible to change the data belonging to the referenced object, such as the value of a class member. Тем не менее вы не можете изменить значение самой ссылки. Например, вы не можете использовать одну и ту же ссылку, чтобы выделить память для нового объекта и сохранить его вне этого метода.However, you cannot change the value of the reference itself; for example, you cannot use the same reference to allocate memory for a new object and have it persist outside the method. Для этого необходимо передать параметр с использованием ключевого слова ref или out.To do that, pass the parameter using the ref or out keyword. В следующих примерах мы для простоты используем ref.For simplicity, the following examples use ref.

Передача ссылочных типов по значениюPassing Reference Types by Value

В следующем примере демонстрируется передача параметра ссылочного типа arr по значению в метод Change.The following example demonstrates passing a reference-type parameter, arr, by value, to a method, Change. Поскольку этот параметр является ссылкой на arr, можно изменять элементы массива.Because the parameter is a reference to arr, it is possible to change the values of the array elements. Тем не менее переназначение параметра другому блоку памяти возможно только внутри самого метода и не влияет на исходную переменную arr.However, the attempt to reassign the parameter to a different memory location only works inside the method and does not affect the original variable, arr.

class PassingRefByVal
{
    static void Change(int[] pArray)
    {
        pArray[0] = 888;  // This change affects the original element.
        pArray = new int[5] {-3, -1, -2, -3, -4};   // This change is local.
        System.Console.WriteLine("Inside the method, the first element is: {0}", pArray[0]);
    }

    static void Main()
    {
        int[] arr = {1, 4, 5};
        System.Console.WriteLine("Inside Main, before calling the method, the first element is: {0}", arr [0]);

        Change(arr);
        System.Console.WriteLine("Inside Main, after calling the method, the first element is: {0}", arr [0]);
    }
}
/* Output:
    Inside Main, before calling the method, the first element is: 1
    Inside the method, the first element is: -3
    Inside Main, after calling the method, the first element is: 888
*/

В предыдущем примере массив arr имеет ссылочный тип и передается в метод без параметра ref.In the preceding example, the array, arr, which is a reference type, is passed to the method without the ref parameter. В таком случае в метод будет передана копия ссылки, которая указывает на arr.In such a case, a copy of the reference, which points to arr, is passed to the method. Как видно из выходных данных, метод может изменять содержимое элемента массива (в данном случае с 1 на 888).The output shows that it is possible for the method to change the contents of an array element, in this case from 1 to 888. Тем не менее при выделении нового блока памяти с помощью оператора new внутри метода Change переменная pArray будет ссылаться на новый массив.However, allocating a new portion of memory by using the new operator inside the Change method makes the variable pArray reference a new array. Таким образом, любые выполненные после этого изменения не будут отражаться в исходном массиве arr, который был создан внутри Main.Thus, any changes after that will not affect the original array, arr, which is created inside Main. Фактически, в этом примере создается два массива: один внутри Main, а другой — в методе Change.In fact, two arrays are created in this example, one inside Main and one inside the Change method.

Передача ссылочных типов по ссылкеPassing Reference Types by Reference

Следующий пример аналогичен предыдущему, однако в нем в заголовок и вызов метода добавляется ключевое слово ref.The following example is the same as the previous example, except that the ref keyword is added to the method header and call. Любые изменения, выполняемые в методе, влияют на исходную переменную в вызывающей программе.Any changes that take place in the method affect the original variable in the calling program.

class PassingRefByRef
{
    static void Change(ref int[] pArray)
    {
        // Both of the following changes will affect the original variables:
        pArray[0] = 888;
        pArray = new int[5] {-3, -1, -2, -3, -4};
        System.Console.WriteLine("Inside the method, the first element is: {0}", pArray[0]);
    }

    static void Main()
    {
        int[] arr = {1, 4, 5};
        System.Console.WriteLine("Inside Main, before calling the method, the first element is: {0}", arr[0]);

        Change(ref arr);
        System.Console.WriteLine("Inside Main, after calling the method, the first element is: {0}", arr[0]);
    }
}
/* Output:
    Inside Main, before calling the method, the first element is: 1
    Inside the method, the first element is: -3
    Inside Main, after calling the method, the first element is: -3
*/

Все изменения, выполняемые внутри метода, влияют на исходный массив в Main.All of the changes that take place inside the method affect the original array in Main. Фактически, происходит перемещение исходного массива с помощью оператора new.In fact, the original array is reallocated using the new operator. Таким образом, после вызова метода Change любые ссылки на arr будут указывать на массив из пяти элементов, который создается в методе Change.Thus, after calling the Change method, any reference to arr points to the five-element array, which is created in the Change method.

Перестановка двух строкSwapping Two Strings

Перестановка строк представляет собой наглядный пример передачи параметров ссылочного типа по ссылке.Swapping strings is a good example of passing reference-type parameters by reference. В этом примере две строки (str1 и str2) инициализируются в Main, а затем передаются в метод SwapStrings в качестве параметров, измененных по ключевому слову ref.In the example, two strings, str1 and str2, are initialized in Main and passed to the SwapStrings method as parameters modified by the ref keyword. Перестановка двух строк выполняется как в этом методе, так и в Main.The two strings are swapped inside the method and inside Main as well.

 class SwappingStrings
 {
     static void SwapStrings(ref string s1, ref string s2)
     // The string parameter is passed by reference.
     // Any changes on parameters will affect the original variables.
     {
         string temp = s1;
         s1 = s2;
         s2 = temp;
         System.Console.WriteLine("Inside the method: {0} {1}", s1, s2);
     }

     static void Main()
     {
         string str1 = "John";
         string str2 = "Smith";
         System.Console.WriteLine("Inside Main, before swapping: {0} {1}", str1, str2);

         SwapStrings(ref str1, ref str2);   // Passing strings by reference
         System.Console.WriteLine("Inside Main, after swapping: {0} {1}", str1, str2);
     }
 }
 /* Output:
     Inside Main, before swapping: John Smith
     Inside the method: Smith John
     Inside Main, after swapping: Smith John
*/

В этом примере параметры должны передаваться по ссылке, чтобы обеспечить изменение переменных в вызывающей программе.In this example, the parameters need to be passed by reference to affect the variables in the calling program. Если удалить ключевое слово ref из заголовка и вызова метода, в вызывающей программе не будут выполнены никакие изменения.If you remove the ref keyword from both the method header and the method call, no changes will take place in the calling program.

Дополнительные сведения о строках см. в этом разделе.For more information about strings, see string.

См. такжеSee also