Нашли ошибку или опечатку? Выделите текст и нажмите

Поменять цветовую

гамму сайта?

Поменять
Обновления сайта
и новые разделы

Рекомендовать в Google +1

Модификаторы параметров

93

Mетоды могут как принимать, так и не принимать параметров, а также возвращать или не возвращать значения вызывающей стороне. Хотя определение метода в C# выглядит довольно понятно, существует несколько ключевых слов, с помощью которых можно управлять способом передачи аргументов интересующему методу:

Модификаторы параметров
Модификатор параметра Описание
(отсутствует) Если параметр не сопровождается модификатором, предполагается, что он должен передаваться по значению, т.е. вызываемый метод должен получать копию исходных данных
out Выходные параметры должны присваиваться вызываемым методом (и, следовательно, передаваться по ссылке). Если параметрам out в вызываемом методе значения не присвоены, компилятор сообщит об ошибке
ref Это значение первоначально присваивается вызывающим кодом и при желании может повторно присваиваться в вызываемом методе (поскольку данные также передаются по ссылке). Если параметрам ref в вызываемом методе значения не присвоены, компилятор никакой ошибки генерировать не будет
params Этот модификатор позволяет передавать в виде одного логического параметра переменное количество аргументов. В каждом методе может присутствовать только один модификатор params и он должен обязательно указываться последним в списке параметров. В реальности необходимость в использовании модификатора params возникает не особо часто, однако он применяется во многих методах внутри библиотек базовых классов

Нередко требуется, чтобы метод оперировал теми аргументами, которые ему передаются. Характерным тому примером служит метод Swap(), осуществляющий перестановку значений своих аргументов. Но поскольку аргументы простых типов передаются по значению, то, используя выбираемый в C# по умолчанию механизм вызова по значению для передачи аргумента параметру, невозможно написать метод, меняющий местами значения двух его аргументов, например типа int. Это затруднение разрешает модификатор ref.

Как вам должно быть уже известно, значение возвращается из метода вызывающей части программы с помощью оператора return. Но метод может одновременно возвратить лишь одно значение. А что, если из метода требуется возвратить два или более фрагментов информации, например, целую и дробную части числового значения с плавающей точкой? Такой метод можно написать, используя модификатор out.

Давайте отдельно рассмотрим роль каждого из вышеуказанных ключевых слов.

Модификатор ref

Модификатор параметра ref принудительно организует вызов по ссылке, а не по значению. Этот модификатор указывается как при объявлении, так и при вызове метода.

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

Выходные параметры

Это параметры, которые не нужно инициализировать перед передачей методу. Причина в том, что метод сам должен присваивать значения выходным параметрам перед выходом.

Ссылочные параметры

Эти параметры нужно обязательно инициализировать перед передачей методу. Причина в том, что они подразумевают передачу ссылки на уже существующую переменную. Если первоначальное значение ей не присвоено, это будет равнозначно выполнению операции над неинициализированной локальной переменной.

Давайте рассмотрим пример использования модификатора ref:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace ConsoleApplication1
{

    class Program
    {
        // Метод, изменяющий свой аргумент
        static void myCh(ref char c)
        {
            c = 'A';
        }

        // Метод меняющий местами аргументы
        static void Swap(ref char a, ref char b)
        {
            char c;
            c = a;
            a = b;
            b = c;
        }

        static void Main()
        {
            char ch = 'B', s1 = 'D', s2 = 'F';
            Console.WriteLine("Переменная ch до вызова метода myCh: {0}",ch);
            myCh(ref ch);
            Console.WriteLine("Переменная ch после вызова метода myCh: {0}", ch);

            Console.WriteLine("\nПеременная s1 = {0}, переменная s2 = {1}", s1, s2);
            Swap(ref s1, ref s2);
            Console.WriteLine("Теперь s1 = {0}, s2 = {1}",s1,s2);

            Console.ReadLine();
        }
    }
}
Модификатор ref

В отношении модификатора ref необходимо иметь в виду следующее. Аргументу, передаваемому по ссылке с помощью этого модификатора, должно быть присвоено значение до вызова метода. Дело в том, что в методе, получающем такой аргумент в качестве параметра, предполагается, что параметр ссылается на действительное значение. Следовательно, при использовании модификатора ref в методе нельзя задать первоначальное значение аргумента.

Модификатор out

Модификатор параметра out подобен модификатору ref, за одним исключением: он служит только для передачи значения за пределы метода. Поэтому переменной, используемой в качестве параметра out, не нужно (да и бесполезно) присваивать какое-то значение. Более того, в методе параметр out считается неинициализированным, т.е. предполагается, что у него отсутствует первоначальное значение. Это означает, что значение должно быть присвоено данному параметру в методе до его завершения. Следовательно, после вызова метода параметр out будет содержать некоторое значение.

Пример:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace ConsoleApplication1
{

    class Program
    {
        // Метод возвращающий целую и дробную части
        // числа, квадрат и корень числа
        static int TrNumber(double d, out double dr, out double sqr, out double sqrt)
        {
            int i = (int)d;
            dr = d - i;
            sqr = d * d;
            sqrt = Math.Sqrt(d);

            return i;
        }

        static void Main()
        {
            int i;
            double myDr, mySqr, mySqrt, myD = 12.987;
            i = TrNumber(myD, out myDr, out mySqr, out mySqrt);

            Console.WriteLine("Исходное число: {0}\nЦелая часть числа: {1}\nДробная часть числа: {2}\nКвадрат числа: {3}\nКвадратный корень числа: {4}",myD,i,myDr,mySqr,mySqrt);

            Console.ReadLine();
        }
    }
}
Использование модификатора out

Обратите внимание, что использование модификатора out в данном примере позволяет возвращать из метода сразу четыре значения.

Модификатор params

В C# поддерживается использование массивов параметров за счет применения ключевого слова params. Ключевое слово params позволяет передавать методу переменное количество аргументов одного типа в виде единственного логического параметра. Аргументы, помеченные ключевым словом params, могут обрабатываться, если вызывающий код на их месте передает строго типизированный массив или разделенный запятыми список элементов.

Число элементов массива параметров будет равно числу аргументов, передаваемых методу. А для получения аргументов в программе организуется доступ к данному массиву:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace ConsoleApplication1
{

    class Program
    {
        static void MaxArr(ref int i, params int[] arr)
        {
            // Изначально нужно обязательно выполнить проверку 
            // на непустоту массива
            if (arr.Length == 0)
            {
                Console.WriteLine("Пустой массив!");
                i=0;
                return;
            }
            else
            {
                if (arr.Length == 1)
                {
                    i = arr[0];
                    return;
                }
            }

            i = arr[0];
            // Ищем максимум
            for (int j = 1; j < arr.Length; j++)
                if (arr[j] > i)
                    i = arr[j];
        }

        static void Main()
        {
            int result = 0;

            int[] arr1 = new int[8];
            int[] arr2 = new int[5];
            Random ran = new Random();
            // Инициализируем оба массива случайными числами
            for (int i = 0; i < 8; i++)
                arr1[i] = ran.Next(1, 20);
            for (int i = 0; i < 5; i++)
                arr2[i] = ran.Next(100, 200);

            Console.WriteLine("Массив arr1: \n");
            foreach (int i in arr1)
                Console.Write("{0}\t",i);
            MaxArr(ref result, arr1);
            Console.WriteLine("Максимум: {0}",result);

            Console.WriteLine("\nМассив arr2: \n");
            foreach (int i in arr2)
                Console.Write("{0}\t", i);
            MaxArr(ref result, arr2);
            Console.WriteLine("Максимум: {0}", result);

            Console.ReadLine();
        }
    }
}
Использование модификатора params

В тех случаях, когда у метода имеются обычные параметры, а также параметр переменной длины типа params, он должен быть указан последним в списке параметров данного метода. Но в любом случае параметр типа params должен быть единственным.

Пройди тесты