Урок 44. Параметры метода C#


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

Параметр

Передача переменных типа значения по значению

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

В следующем примере кода демонстрируется использование параметров с переменными, которые являются типами значений. В этом примере объявляется переменная типа значения и присваивается ее значение. Затем эта переменная передается параметру по значению, и значение параметра изменяется в рамках метода. Исходная переменная остается неизменной.

static void Main(string[] args)
{
    int original = 100;     
    showDouble(original);
    Console.WriteLine("Original: {0}", original);
}
 
static void showDouble(int valueToShow)
{
    valueToShow *=2;
    Console.WriteLine("Double: {0}", valueToShow);
}
 
/* Вывод
 
Double: 200
Original: 100
 
*/
Передача ссылочных типов по значению

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

Для демонстрации рассмотрим следующий код. Есть класс Ball, который содержит одно свойство для диаметра шара. При вызове метода InflateBall, мяч передается по ссылке. Увеличение свойства диаметра внутри метода также видно за пределами метода. Однако при вызове метода GetNewBall переназначенный объект не отображается внешне по отношению к методу.

Этот код можно протестировать, создав новое консольное приложение и скопировав его в программу и создав класс Ball.

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

class Program
{
    static void Main(string[] args)
    {
        Ball football = new Ball();
        football.Diameter = 15;
 
        InflateBall(football);
        Console.WriteLine("Диаметр: {0}", football.Diameter);
 
        GetNewBall(football);
        Console.WriteLine("Диаметр: {0}", football.Diameter);
 
        /* Вывод
 
        Диаметр: 16
        Диаметр: 16
 
        */
    }
 
    static void InflateBall(Ball ball)
    {
        ball.Diameter++;
    }
 
    static void GetNewBall(Ball ball)
    {
        ball = new Ball();
        ball.Diameter = 1;
    }
}
 
 
class Ball
{
    private int _diameter;
     
    public int Diameter
    {
        get
        {
            return _diameter;
        }
        set
        {
            _diameter = value;
        }
    }
}
Примечание: если параметр value использует ссылочный тип, изменения свойств объекта в большинстве случаев отражаются вне метода. Примером того, где это неверно, может служить неизменяемый класс string, который предназначен для действия как тип значения в некотором его поведении.

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

Передача типов значений по ссылке

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

Ссылочный параметр объявляется с помощью ключевого слова ref перед типом параметра. Этот префикс также должен использоваться при вызове метода.

Следующий пример кода основан на первом примере в этой статье, но при использовании ссылочного параметра, а не параметра value, наблюдаемые результаты отличаются.

static void Main(string[] args)
{
    int original = 100;     
    showDouble(ref original);
    Console.WriteLine("Original: {0}", original);
}
 
static void showDouble(ref int valueToShow)
{
    valueToShow *=2;
    Console.WriteLine("Double: {0}", valueToShow);
}
 
/* Вывод
 
Double: 200
Original: 200
Передача ссылочных типов по ссылке

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

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

class Program
{
    static void Main(string[] args)
    {
        Ball football = new Ball();
        football.Diameter = 15;
 
        InflateBall(ref football);
        Console.WriteLine("Diameter: {0}", football.Diameter);
 
        GetNewBall(ref football);
        Console.WriteLine("Diameter: {0}", football.Diameter);
 
        /* Вывод
 
        Diameter: 16
        Diameter: 1
 
        */
    }
 
    static void InflateBall(ref Ball ball)
    {
        ball.Diameter++;
    }
 
    static void GetNewBall(ref Ball ball)
    {
        ball = new Ball();
        ball.Diameter = 1;
    }
}
 
 
class Ball
{
    private int _diameter;
 
    public int Diameter
    {
        get
        {
            return _diameter;
        }
        set
        {
            _diameter = value;
        }
    }
}
Выходной параметр

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

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

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

static void Main(string[] args)
{
    int area;
    int perimeter;
 
    area = CalculateRectangle(5, 10, out perimeter);
 
    Console.WriteLine("Area: {0}", area);
    Console.WriteLine("Perimeter: {0}", perimeter);
}
 
 
static int CalculateRectangle(int width, int height, out int perimeter)
{
    perimeter = (width * 2) + (height * 2);
    return width * height;
}
 
/* 
 
Area: 50
Perimeter: 30
 
*/
Примечание: этот код предназначен для отображения примера выходных параметров. Было бы необычно создавать такой метод в реальной программе, поскольку было бы более читабельно создавать отдельные методы для вычислений площади и периметра.

Массив параметров

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

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

static void Main(string[] args)
{
    showScores("Боб", 15);
    showScores("Джилл", 10, 12, 15, 25);
    showScores("Кен");
}
 
 
static void showScores(string player, params int[] scores)
{
    Console.WriteLine("Игрок: {0}", player);
 
    foreach (int score in scores)
    {
        Console.Write("{0}\t", score);
    }
 
    Console.WriteLine("\n");
}
/* Вывод
 
Игрок: Боб
15
 
Игрок: Джилл
10 12 15 25
 
Игрок: Кен
 
*/
Автор этого материала - я - Пахолков Юрий. Я оказываю услуги по написанию программ на языках Java, C++, C# (а также консультирую по ним) и созданию сайтов. Работаю с сайтами на CMS OpenCart, WordPress, ModX и самописными. Кроме этого, работаю напрямую с JavaScript, PHP, CSS, HTML - то есть могу доработать ваш сайт или помочь с веб-программированием. Пишите сюда.

тегистатьи IT, си шарп, уроки по си шарп, методы




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




Новости блога
Демонстрация Q-learning в программе на Java
Урок 6. Введение в обработку событий Vue.js