На этом шаге мы рассмотрим использование структур в качестве аргумента метода.
Экземпляр структуры можно передавать методу в качестве агумента. В этом случае важно помнить, что по умолчанию аргументы передаются по значению (то есть в действительности передается копия переменной, фактически указанной аргументом), а структура является типом данных с прямым доступом к значению. В остальном передача экземпляров структуры методу в качестве аргументов достаточно тривиальна. В примере ниже представлена программа, поясняющая ситуацию.
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);
Еще один статический метод maker() также не возвращает результат. У метода четыре аргумента. Первые два являются экземплярами структуры MyStruct, причем первый аргумент (обозначен как A) передается по значению, а второй аргумент (обозначен как B и описан с ключевым словом ref) передается по ссылке. Третий аргумент (обозначен как k) является целым числом, а четвертый аргумент (обозначен как s) является символьным значением. Метод выполняется так: сначала отображаются значения полей экземпляров A и B структуры (команды
show(A);
show(B);
show(A);
show(B);
A.name[k] = s;
B.name[k] = s;
A.code++;
B.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 изменилось только значение элемента в символьном массиве (в силу описанных выше причин).
На следующем шаге мы рассмотрим использование экземпляра структуры как результата метода.