Шаг 197.
Язык программирования C#. Начала.
Перечисления и структуры. Экземпляр структуры как аргумент метода

    На этом шаге мы рассмотрим использование структур в качестве аргумента метода.

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

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

namespace pr197_1
{
    // Структура: 
    struct MyStruct {
        // Ссылка на символьный массив: 
        public char[] name;
        // Целочисленное поле:
        public int code;
        // Конструктор:
        public MyStruct(string t, int n) {
            // Создание на основе текста символьного массива.
            // Ссылка на массив присваивается значением полю: 
            name = t.ToCharArray();
            // Значение целочисленного поля: 
            code = n;
        }
    }

    // Класс с главным методом: 
    class Program
    {
        // Метод для отображения значений полей экземпляра 
        // структуры, переданного аргументом: 
        static void show(MyStruct A) {
            // Преобразование символьного массива в текст: 
            string txt = new string(A.name);
            // Отображение текста:
            Console.WriteLine("Символьный массив [{0}]", txt);
            // Отображение значения целочисленного поля: 
            Console.WriteLine("Числовое поле {0}", A.code);
        }
        // Метод для присваивания новых значений полям 
        // экземпляров структуры:
        static void maker(MyStruct A, ref MyStruct B, int k, char s){ 
            Console.WriteLine("Bыпoлняeтcя метод maker()"); 
            Console.WriteLine("Пepвый аргумент:");
            // Отображение значений полей экземпляра структуры: 
            show(A);
            Console.WriteLine("Второй аргумент:");
            // Отображение значений полей экземпляра структуры: 
            show(B);
            // Изменение значения элемента в массиве:
            A.name[k] = s;
            B.name[k] = s;
            // Изменение значения текстового поля:
            A.code++;
            B.code++;
            Console.WriteLine();
            Console.WriteLine("Пepвый аргумент:");
            // Отображение значений полей экземпляра структуры: 
            show(A);
            Console.WriteLine("Второй аргумент:");
            // Отображение значений полей экземпляра структуры: 
            show(B);
            Console.WriteLine("Meтод maker() завершен\n");
        }

        // Главный метод: 

        static void Main()
        {
            // Создание экземпляров структуры:
            MyStruct A = new MyStruct("Alpha", 100);
            MyStruct B = new MyStruct("Bravo", 200);
            // Вызов статического метода: 
            maker(A, ref B, 4, 'R');
            Console.WriteLine("После вызова метода maker()");
            Console.WriteLine("Экземпляр A:");
            // Отображение значений полей экземпляра структуры: 
            show(A);
            Console.WriteLine("Экземпляр B:");
            // Отображение значений полей экземпляра структуры: 
            show(B);
            // Задержка:
            Console.ReadLine();
        }
    }
}
Архив проекта можно взять здесь.

    Результат выполнения программы такой:


Рис.1. Результат выполнения программы

    У структуры MyStruct есть открытое целочисленное поле code и открытое поле name, представляющее собой ссылку на символьный массив. Конструктор имеет два аргумента: текстовый и целочисленный. Целочисленный аргумент присваивается в качестве значения полю code. Текстовый аргумент (обозначен как t) командой t.ToCharArray() преобразуется в символьный массив (точнее, на основе текста формируется массив), а ссылка на массив записывается в поле name.

    В классе с методом Main() описано два статических метода. Метод show() не возвращает результат, а аргументом методу передается экземпляр структуры MyStruct. Метод предназначен для отображения значений полей экземпляра структуры, переданного методу в качестве аргумента. В теле метода командой

  string txt = new string(A.name); 
на основе символьного массива name экземпляра A (аргумент метода) создается текстовое значение, и ссылка на текстовый объект записывается в переменную txt. Значение этой текстовой переменной отображается в консольном окне. Также в консольном окне отображается значение целочисленного поля code экземпляра A.

    Еще один статический метод maker() также не возвращает результат. У метода четыре аргумента. Первые два являются экземплярами структуры MyStruct, причем первый аргумент (обозначен как A) передается по значению, а второй аргумент (обозначен как B и описан с ключевым словом ref) передается по ссылке. Третий аргумент (обозначен как k) является целым числом, а четвертый аргумент (обозначен как s) является символьным значением. Метод выполняется так: сначала отображаются значения полей экземпляров A и B структуры (команды

  show(A); 
и
  show(B); 
), переданных методу в качестве аргументов, после этого изменяются значения полей этих экземпляров, и новые значения полей отображаются в консольном окне (еще раз используются команды
  show(A); 
и
  show(B); 
). Изменение полей выполняется следующим образом. Символьное значение s, переданное четвертым аргументом, присваивается элементу с индексом k (третий аргумент метода) массива name экземпляров структуры (команды
  A.name[k] = s; 
и
  B.name[k] = s;
). Еще командами
  A.code++;
и
  B.code++;
на единицу увеличивается значение поля code экземпляров структуры.

    В главном методе программы командами

  MyStruct A = new MyStruct("Alpha", 100);
и
  MyStruct B = new MyStruct("Bravo", 200);
создаются два экземпляра структуры. После этого выполняется команда
  maker(A, ref B, 4, 'R');   . 

    Экземпляр A передается методу по значению, то есть передается копия экземпляра A. Экземпляр B передается по ссылке, то есть "в оригинале". Что происходит? Сначала отображаются значения полей для копии экземпляра A и экземпляра B. С оригиналом все просто. С копией ситуация такая. Поле code у копии экземпляра имеет такое же значение, что и поле code оригинала. Поле name копии имеет такое же значение, как и поле name оригинала. Значение этого поля - ссылка на массив. Получается, что и экземпляр A, и его копия, переданная в метод maker() через поле name, ссылаются на один и тот же массив. Поэтому при выполнении метода maker() меняется значение поля code копии экземпляра A, а также меняется значение элемента в массиве, на который ссылаются поля name и экземпляра A, и его копии (переданной в качестве аргумента). Что касается экземпляра B, то, поскольку он передается по ссылке, все изменения происходят именно с этим экземпляром.

    После завершения работы метода maker() мы проверяем значения полей экземпляров A и B. Видим, что у экземпляра B изменилось и значение поля code, и значение символа в символьном массиве. У экземпляра A изменилось только значение элемента в символьном массиве (в силу описанных выше причин).

    На следующем шаге мы рассмотрим использование экземпляра структуры как результата метода.




Предыдущий шаг Содержание Следующий шаг