Опубликован: 15.09.2010 | Доступ: свободный | Студентов: 4808 / 630 | Оценка: 3.97 / 3.80 | Длительность: 14:45:00
Лекция 5:

Классы: основные понятия

< Лекция 4 || Лекция 5: 1234 || Лекция 6 >

Параметры методов

При вызове метода выполняются следующие действия:

  1. Вычисляются выражения, стоящие на месте аргументов.
  2. Выделяется память под параметры метода в соответствии с их типом.
  3. Каждому из параметров сопоставляется соответствующий аргумент (аргументы как бы накладываются на параметры и замещают их).
  4. Выполняется тело метода.
  5. Если метод возвращает значение, оно передается в точку вызова; если метод имеет тип void, управление передается на оператор, следующий после вызова.

При этом проверяется соответствие типов аргументов и параметров и при необходимости выполняется их преобразование. При несоответствии типов выдается диагностическое сообщение. Листинг 5.3 иллюстрирует этот процесс.

using System;
namespace ConsoleApplication1
{   class Class1
    {   
        static int Max(int a, int b)  // метод выбора максимального значения
        {
            if ( a > b ) return a;
            else         return b;
        }
        static void Main()
        {
            int a = 2, b = 4;
            int x = Max( a, b );                 // вызов метода Max
            Console.WriteLine( x );              // результат: 4

            short t1 = 3, t2 = 4;
            int y = Max( t1, t2 );               // вызов метода Max
            Console.WriteLine( y );              // результат: 4

            int z = Max( a + t1, t1 / 2 * b );   // вызов метода Max
            Console.WriteLine( z );              // результат: 5
        }
    }
}
Листинг 5.3. Передача параметров методу

Внимание

Главное требование при передаче параметров состоит в том, что аргументы при вызове метода должны записываться в том же порядке, что и в заголовке метода, и должно существовать неявное преобразование типа каждого аргумента к типу соответствующего параметра. Количество аргументов должно соответствовать количеству параметров. Иллюстрация приведена на рис. 5.4.

Соответствие параметров при вызове метода

Рис. 5.4. Соответствие параметров при вызове метода

Существуют два способа передачи параметров: по значению и по ссылке.

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

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

В C# для обмена данными между вызывающей и вызываемой функциями предусмотрено четыре типа параметров:

  • параметры-значения;
  • параметры-ссылки — описываются с помощью ключевого слова ref ;
  • выходные параметры — описываются с помощью ключевого слова out ;
  • параметры-массивы — описываются с помощью ключевого слова params.

Ключевое слово предшествует описанию типа параметра. Если оно опущено, параметр считается параметром-значением. Параметр-массив может быть только один и должен располагаться последним в списке, например:

public int Calculate( int a, ref int b, out int c, params int[] d ) …

Параметры-значения

Параметр-значение описывается в заголовке метода следующим образом:

тип имя

Пример заголовка метода, имеющего один параметр-значение целого типа:

void P( int x )

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

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

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

Например, пусть в вызывающей функции описаны переменные и им до вызова метода присвоены значения:

int    x = 1; 
sbyte  c = 1;
ushort y = 1;

Тогда следующие вызовы метода Р, заголовок которого был описан ранее, будут синтаксически правильными:

P( x );    P( c );    P( y );    P( 200 );    P( x / 4 + 1 );

Параметры-ссылки

Признаком параметра-ссылки является ключевое слово ref перед описанием параметра:

ref тип имя

Пример заголовка метода, имеющего один параметр-ссылку целого типа:

void P( ref int x )

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

Внимание

При вызове метода на месте параметра-ссылки может находиться только ссылка на инициализированную переменную точно того же типа. Перед именем параметра указывается ключевое слово ref.

Проиллюстрируем передачу параметров-значений и параметров-ссылок на примере (листинг 5.4).

using System;
namespace ConsoleApplication1
{   class Class1
    {   
        static void P( int a, ref int b )
        {
            a = 44; b = 33;
            Console.WriteLine( "внутри метода {0} {1}", a, b );
        }
        static void Main()
        {
            int a = 2, b = 4;
            Console.WriteLine( "до вызова     {0} {1}", a, b );
            P( a, ref b );
            Console.WriteLine( "после вызова  {0} {1}", a, b );
        }
    }
}
Листинг 5.4. Параметры-значения и параметры-ссылки

Результаты работы этой программы:

до вызова     2 4
внутри метода 44 33
после вызова  2 33

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

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

Довольно часто возникает необходимость в методах, которые формируют несколько величин. В этом случае становится неудобным ограничение параметров-ссылок: необходимость присваивания значения аргументу до вызова метода. Это ограничение снимает спецификатор out. Параметру, имеющему этот спецификатор, должно быть обязательно присвоено значение внутри метода.

Изменим описание второго параметра в листинге 5.4 так, чтобы он стал выходным (листинг 5.5).

using System;
namespace ConsoleApplication1
{   class Class1
    {   
        static void P( int a, out int b )
        {
            a = 44; b = 33;
            Console.WriteLine( "внутри метода {0} {1}", a, b );
        }
        static void Main()
        {
            int a = 2, b;
            P( a, out b );
            Console.WriteLine( "после вызова  {0} {1}", a, b );
        }
    }
}
Листинг 5.5. Выходные параметры

При вызове метода перед соответствующим параметром тоже указывается ключевое слово out.

< Лекция 4 || Лекция 5: 1234 || Лекция 6 >
Stefan Berzan
Stefan Berzan
Молдова, Кишинев
Дмитрий Казимиров
Дмитрий Казимиров
Россия, Омск