Передача параметров ссылочного типа (Руководство по программированию в C#)
Переменная ссылочного типа не содержит непосредственные данные; она содержит ссылку на эти данные. Если параметр ссылочного типа передается по значению, можно изменить данные, на которые указывает ссылка, например, значение члена класса. Однако нельзя изменить значение самой ссылки; то есть нельзя использовать одну ссылку для выделения памяти для нового класса и его создания вне заданного блока. Для этого передайте параметр с помощью ключевого слова ref или out. Для простоты в следующем примере использовано ключевое слово ref.
Передача ссылочных типов по значению
В следующем примере демонстрируется передача параметра ссылочного типа arr по значению в метод Change. Поскольку этот параметр является ссылкой на arr, можно изменить значения элементов массива. Однако попытка назначить параметр другому адресу в памяти может быть выполнена только внутри метода и не влияет на исходную переменную 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. В этом случае в метод передается копия ссылки, указывающей на arr. В результате выполнения видно, что метод может изменить содержимое элемента массива, в данном случае с 1 на 888. Однако выделение новой области памяти с помощью оператора new внутри метода Change приводит к тому, что переменная pArray ссылается на новый массив. Поэтому любые изменения, внесенные после этого, не затрагивают исходный массив arr, созданный внутри Main. В действительности в данном примере создаются два массива, один внутри Main и один внутри метода Change.
Передача ссылочных типов по ссылке
Следующий пример такой же, как и предыдущий, за исключением того, что ref ключевое слово добавляется к заголовку и вызову метода. Все изменения, выполняемые в исходную переменную, влияют на метода в вызывающей программе.
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. В действительности исходный массив перераспределяется с помощью оператора new. Поэтому после вызова метода Change любая ссылка на arr указывает на массив из пяти элементов, созданный в методе Change.
Перестановка двух строк
Перестановка строк представляет собой хороший пример передачи параметров ссылочного типа по ссылке. В данном примере две строки str1 и str2 инициализируются в Main и передаются в метод SwapStrings в качестве параметров, изменяемых по ключевому слову ref. Эти две строки переставляются внутри метода и также внутри Main.
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
*/
В данном примере необходимо передать параметры по ссылке для оказания влияния на переменные в вызывающей программе. Если удалить ключевое слово ref как из заголовка метода, так и из вызова метода, то вызывающая программа изменена не будет.
Дополнительные сведения о строках см. в разделе Строка.
См. также
Ссылки
Передача параметров (Руководство по программированию в C#)
Передача массивов при помощи параметров ref и out (Руководство по программированию на C#)
Ссылочные типы (Справочник по C#)