На этом шаге мы рассмотрим передачу параметров по ссылке.
Кроме используемого по умолчанию режима передачи аргументов по значению, аргументы еще можно передавать и по ссылке. В таком случае в метод передается именно та переменная, которая указана аргументом (а не ее копия). Если мы хотим, чтобы аргументы в метод передавались по ссылке, то в описании метода перед соответствующим аргументом указывается инструкция ref. Такая же инструкция указывается перед аргументом при вызове метода. Как иллюстрацию рассмотрим программу ниже. Это модификация примера из предыдущего шага, но только аргументы методам alpha(), bravo() и charlie() передаются по ссылке.
using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace pr69_1 { class Program { // Первый метод. Аргумент - целое число: static void alpha(ref int n) { // Проверка значения аргумента: Console.WriteLine("В методе alpha(). На входе: " + n); // Попытка изменить значение аргумента: n++; // Проверка значения аргумента: Console.WriteLine("В методе alpha(). На выходе: " + n); } // Второй метод. Аргумент - ссыпка на массив: static void bravo(ref int[] n) { // Проверка содержимого массива: Console.WriteLine("В методе bravo(). На входе: " + ArrayToText(n)); // Перебор элементов массива: for(int k=0; k < n.Length; k++){ n[k]++; } // Проверка содержимого массива: Console.WriteLine("В методе bravo(). На выходе: " +ArrayToText(n)); } // Третий метод. Аргумент - ссылка на массив: static void charlie(ref int[] n){ // Проверка содержимого массива: Console.WriteLine("В методе charlie(). На входе: " + ArrayToText(n)); // Создается новый массив: int[] m = new int [n.Length]; // Перебор элементов в массиве: for(int k=0; k < n.Length; k++){ // Значение элемента массива: m[k] = n[k] + 1; } n = m; // Проверка содержимого массива: Console.WriteLine("В методе charlie(). На выходе: " + ArrayToText(n)); } // Метод для преобразования массива в текст: static string ArrayToText(int[] n){ // Текстовая переменная: string res = "[" + n[0]; // Перебор элементов массива (кроме начального): for(int k=1; k < n.Length; k++){ // Дописывание текста в текстовую переменную: res += "," + n[k]; } // Дописывание текста з текстовую переменную: res += "]"; // Результат метода - текстовая строка: return res; } // Главный метод программы: static void Main() { // Переменная для передачи аргументом методу: int A = 100; // Проверка значения переменной: Console.WriteLine("До вызова метода alpha(): А=" + A); // Вызов метода: alpha(ref A); // Проверка значения переменной: Console.WriteLine("После вызова метода alpha: А=" + A); // Массив для передачи аргументом методу: int[] B = {1, 3, 5}; // Проверка содержимого массива: Console.WriteLine("До вызова метода bravo(): B=" + ArrayToText(B)); // Вызов метода: bravo(ref B); // Проверка содержимого массиза: Console.WriteLine("После вызова метода bravo(): B=" + ArrayToText(B)); // Массив для передачи аргументом методу: int[] C = {2, 4, 6}; // Проверка содержимого массива: Console.WriteLine("До вызова метода charlie(): C=" + ArrayToText(C)); // Вызов метода: charlie(ref C); // Проверка содержимого массива: Console.WriteLine("После вызова метода charlie(): C=" + ArrayToText(C)); // Задержка: Console.ReadLine(); } } }
В этом случае результат выполнения программы такой:
Рис.1. Результат выполнения программы
Видим, что теперь изменяется не только массив, на который ссылается переменная В, но и массив, на который ссылается переменная С, а также изменяется переменная А. Объяснение простое - аргументы передаются по ссылке, поэтому изменения, которые мы вносим в методе в аргументы, применяются к аргументам, а не к их копиям.
На следующем шаге мы закончим изучение этого вопроса.