Главная страница
Навигация по странице:

  • Знакомство со структурами

  • Результат выполнения программы (из листинга 3.2)

  • Васильев А.Н. Основы программирования на C#. Васильев А. Н. Программирование


    Скачать 5.54 Mb.
    НазваниеВасильев А. Н. Программирование
    АнкорВасильев А.Н. Основы программирования на C
    Дата20.09.2022
    Размер5.54 Mb.
    Формат файлаpdf
    Имя файлаVasilev_Programmirovanie-na-C-dlya-nachinayushchih-Osobennosti-y.pdf
    ТипДокументы
    #686596
    страница11 из 40
    1   ...   7   8   9   10   11   12   13   14   ...   40
    134
    //
    ɇɨɜɨɟ ɡɧɚɱɟɧɢɟ ɩɟɪɟɦɟɧɧɨɣ:
    animal=Animals.Dog;
    Console.WriteLine(
    Ǝanimal: {0,-5} ɢɥɢ {1}Ǝ,animal,(int)animal);
    //
    ɉɪɟɨɛɪɚɡɨɜɚɧɢɟ ɰɟɥɨɝɨ ɱɢɫɥɚ ɜ ɡɧɚɱɟɧɢɟ
    //
    ɬɢɩɚ ɩɟɪɟɱɢɫɥɟɧɢɹ:
    animal=(Animals)2;
    Console.WriteLine(
    Ǝanimal: {0,-5} ɢɥɢ {1}Ǝ,animal,(int)animal);
    //
    ɋɭɦɦɚ ɩɟɪɟɦɟɧɧɨɣ ɢ ɰɟɥɨɝɨ ɱɢɫɥɚ:
    animal=animal+1;
    Console.WriteLine(
    Ǝanimal: {0,-5} ɢɥɢ {1}Ǝ,animal,(int)animal);
    //
    ɉɪɢɦɟɧɟɧɢɟ ɨɩɟɪɚɰɢɢ ɢɧɤɪɟɦɟɧɬɚ:
    animal++;
    Console.WriteLine(
    Ǝanimal: {0,-5} ɢɥɢ {1}Ǝ,animal,(int)animal);
    Console.WriteLine(
    Ǝȼ ɦɢɪɟ ɮɢɧɚɧɫɨɜƎ);
    //
    ɉɟɪɟɦɟɧɧɚɹ ɬɢɩɚ ɩɟɪɟɱɢɫɥɟɧɢɹ:
    Coins coin;
    //
    Ɉɛɴɟɤɬ ɫ ɤɨɧɫɬɚɧɬɚɦɢ ɢɡ ɩɟɪɟɱɢɫɥɟɧɢɹ:
    Array names=Enum.GetValues(typeof(Coins));
    //
    ɉɟɪɟɛɨɪ ɤɨɧɫɬɚɧɬ:
    for(int k=0;k //
    Ɂɧɚɱɟɧɢɟ ɩɟɪɟɦɟɧɧɨɣ:
    coin=(Coins)names.GetValue(k);
    Console.WriteLine(
    Ǝcoin: {0,-5} ɢɥɢ {1}Ǝ,coin,(int)coin);
    }
    Результат выполнения программы представлен ниже Результат выполнения программы (из листинга 3.1)
    ȼ ɦɢɪɟ ɠɢɜɨɬɧɵɯ
    animal: Cat
    ɢɥɢ 0
    Перечисления и структуры Dog
    ɢɥɢ 1
    animal: Fox
    ɢɥɢ 2
    animal: Wolf
    ɢɥɢ 3
    animal: Bear
    ɢɥɢ 4
    ȼ ɦɢɪɟ ɮɢɧɚɧɫɨɜ
    coin: One
    ɢɥɢ 1
    coin: Two
    ɢɥɢ 2
    coin: Five
    ɢɥɢ 5
    coin: Ten
    ɢɥɢ 10
    coin: Fifty
    ɢɥɢ В этой программе мы объявляем два перечисления перечисление Animals объявляется командой enum Animals {Cat,Dog,Fox,Wolf,Bear}, а перечисление Coins объявляется командой enum Coins В главном методе программы командой Animals animal=Animals.Cat объявляется и инициализируется переменная animal типа Animals. При отображении значения переменной animal в консольном окне отображается символьное название константы, которая присвоена в качестве значения переменной. Чтобы узнать целочисленное значение константы, используем инструкцию (int)animal, в которой выполняется явное приведение к целочисленному типу НАЗ А МЕТКУ Инструкция
    {0,-5}
    в текстовой строке в аргументе метода
    WriteLine()
    означает, что для отображения соответствующего значения выделяется
    5
    позиций и выравнивание выполняется полевому (из-за знака минус) краю.
    Новое значение переменной animal присваивается командами animal=Animals.Dog
    (значением присваивается константа из перечисления (выполняется явное приведение целочисленного значения к типу Animals), animal=animal+1 (увеличение текущего значения переменной на единицу, а также animal++ применение операции инкремента. При выполнении последних операций мы приняли в расчет, что числовые значения констант отличаются
    Глава друг от друга на единицу. Нов общем случае это не всегда так например, перечисление Coins. Для работы с этим перечислением мы командой объявляем переменную coin. Но проблема здесь в том, что константы из перечисления Coins имеют уникальные целочисленные значения. Лишь для констант One и Two значения отличаются на единицу, значения всех прочих констант заданы индивидуально. Поэтому перебор ряда натуральных чисел с помощью оператора цикла не очень подходит. Мы поступаем немного хитрее. Сначала с помощью команды Array names=Enum.GetValues(typeof(Coins)) создаем объект names класса Array, содержащий набор значений констант из перечисления Coins. Для этого из класса Enum вызывается статический метод GetValues(). Результатом метод возвращает ссылку на объект класса Array. Этот объект по свойствам напоминает массив и содержит, как отмечалось, значения, формирующие тип Coins. Аргументом методу GetValues() передается объект класса Type, который содержит информацию о перечислении Coins. Этот объект можно получить с помощью инструкции typeof(Coins). Для перебора значений, формирующих тип перечисления Coins, мы запускаем оператор цикла, в котором используем индексную переменную k. Количество элементов в объекте names вычисляется выражением names.Length, как для массива. Для считывания очередного значения, содержащегося в объекте names, используем метод GetValue(). Аргументом методу передается индекс считываемого элемента. Но поскольку значением выражения names.GetValue(k) является объектная ссылка класса object, то мы используем процедуру явного приведения типа. В итоге получается команда coin=(Coins)names.GetValue(k), которой значение присваивается переменной coins. В консольном окне отображается значение этой переменной и его целочисленный эквивалент ПОДРОБНОСТИ bЕсть несколько обстоятельств, которые нужно иметь ввиду при работе с перечислениями. Во-первых, как мы знаем, константы, формирующие тип перечисления, являются целочисленными. Предполагается, что значением переменной типа перечисления может быть одна из таких констант. Но дело в том, что технических ограничений назначения для переменной типа перечисления нет. Это означает, что переменная может получить целочисленное значение, которое не совпадает со значением ни одной из констант из перечисления. Например, если в рассмотренном выше примере выполнить команду
    Перечисления и структуры, то ошибки не будет, хотя в списке констант перечисления константы со значением
    5
    нет. Это же замечание относится к операциям вида animal++
    или animal=animal+1
    : если окажется, что новое вычисленное значение не представлено константой в списке перечисления, то оно все рано будет записано в переменную.
    Нулевое значение особое например, поле, тип которого является перечислением, инициализируется с начальным нулевым значением. Причем происходит это, даже если среди констант, формирующих перечисление, нет константы с нулевым значением. Поэтому общая рекомендация состоит в том, чтобы перечисление все же содержало константу с нулевым значением.
    Знакомство со структурами
    Нет, давай будем считать, что мы на Земле в какой-то пустыне.
    из к/ф «Кин-дза-дза»
    В языке C# структуры напоминают классы. По сравнению с классами возможности структур скромнее. Зато, в отличие от объектов класса, экземпляры структуры реализуются через механизм прямого доступа, что повышает эффективность обработки данных. Но обо всем по порядку.
    Как и класс, структура представляет собой некоторый шаблонна основе которого создаются объекты. В случае структуры эти объекты мы будем называть экземплярами структуры. Здесь концептуально все должно быть более-менее понятно. Описывается структура, в общем-то, также, как и класс. Разница лишь в том, что вместо ключевого слова class используется ключевое слово struct. Общий шаблон описания структуры следующий
    ɢɦɹ{
    //
    Ɍɟɥɨ После ключевого слова struct указывается имя структуры, а в блоке из фигурных скобок описывается тело структуры поля, методы (в том числе и операторные, индексаторы, свойства и события
    Глава 3
    138
    {
    i
    НАЗ А МЕТКУ В языке C++ также есть структуры. В языке C# структуры кардинально отличаются от структур языка C++. В языке C++ структура может содержать только поля, ноне методы. В языке C# структура является аналогом класса.
    Вместе стем, если сравнивать с классами, на структуры накладываются существенные ограничения. Ниже перечислены наиболее важные особенности структур У структур могут быть конструкторы, однако нельзя описать конструктор без аргументов. У каждой структуры есть конструктор без аргументов, используемый по умолчанию. Он существует, даже если в структуре описаны прочие версии конструкторов. Другими словами, у структуры всегда есть конструктор без аргументов и переопределить его нельзя. При этом мы можем описать другие версии конструктора (с аргументами У структур нет деструкторов.
    • К структурам неприменимо наследование структура не может создаваться на основе класса или структуры и не может быть базовой для класса. При этом все структуры встроены в иерархию наследования с классом
    Object на верхнем уровне (то есть переменная класса
    Object может ссылаться на экземпляр структуры При описании членов структуры используют спецификаторы уровня доступа. Если спецификатор доступа не указан, соответствующий член является закрытыми доступен только в пределах кода структуры. Спецификатор уровня доступа protected не используется (в нем простонет смысла, поскольку наследование не поддерживается При объявлении полей в классе полям можно присваивать значения такое значение будет у поля при создании объекта. Для поля структуры (при объявлении поля) значение можно указать, только если поле статическое (использовано ключевое слово static
    ) или является константой (использовано ключевое слово const
    ).
    • Как и классы, структуры могут реализовать интерфейсы При присваивании экземпляров структуры (одной переменной структуры присваивается другая переменная структуры) выполняется побитовое копирование значение каждого поля присваиваемого
    Перечисления и структуры
    139
    экземпляра копируется в соответствующее поле экземпляра, которому присваивается значение. Этот механизм копирования обусловлен тем, что структуры относятся к типам с прямым доступом к значе- нию.
    Учитывая, что ограничения существенные, возникает естественный вопроса зачем вообще нужны структуры В чем их преимущество Ответ состоит в том, что структуры — это не ссылочный тип (как классы, а тип с прямым доступом к значению. Это дает преимущество в плане повышения быстродействия программы.
    Здесь уместно напомнить, как мы реализуем объекты классов. Для этого нам нужен собственно объект и еще нам нужна объектная переменная, которая на объект ссылается. Доступ к объекту мы получаем через объектную переменную, которая играет роль посредника. Это ссылочный тип. А вот целочисленная переменная хранит не ссылку на целое число, а само это целое число. Это тип с прямым доступом к значению. Таким же типом является структура. Если мы создаем экземпляр (объект) структуры, то этот экземпляр реализуется как значение некоторой переменной, без каких бы тони было посредников. Преимущество данного подхода в том, что операции с экземпляром выполняются быстрее, чем в случае, если бы это был аналогичный объект класса, доступ к которому необходимо получать через объектную переменную. Плата за сэкономленное время — ограничение в функциональных возможностях экземпляров структуры по сравнению с объектами классов НАЗ А МЕТКУ Механизм, использованный в языке C# для реализации экземпляров структуры, в языке C++ используется для реализации объектов класса.
    Также стоит отметить, что целочисленные значения в языке C# на самом деле реализуются как экземпляры структуры.
    Экземпляр структуры создается также, как объявляется переменная базового типа — указывается название структуры и имя переменной При создании экземпляра в этом случае поля структуры остаются не- инициализированными, и поэтому перед использованием экземпляра структуры полям придется сначала присвоить значения. Если при
    Глава создании экземпляра структуры мы хотим использовать конструктор с аргументами, то синтаксис создания экземпляра структуры будет такой же, как и синтаксис команды создания объекта класса, только вместо имени класса указывается имя структуры ɩɟɪɟɦɟɧɧɚɹ=new Как ив случае с созданием объектов класса, используется инструкция. В результате создается экземпляр структуры, который является значением переменной, указанной слева от оператора присваивания. Подобного типа команду (с инструкцией new) можно использовать и для создания экземпляра структуры с использованием конструктора без аргументов (конструктор по умолчанию ɩɟɪɟɦɟɧɧɚɹ=new В этом случае аргументы конструктору не передаются. Эффект от выполнения такого рода команды практически такой же, как и при создании экземпляра структуры командой вида
    ɋɬɪɭɤɬɭɪɚ ɩɟɪɟɦɟɧɧɚɹ. Разница в том, что при вызове конструктора по умолчанию выполняется инициализация полей. Поля инициализируются значениями по умолчанию для числовых полей это нулевое значение, а для ссылочных типов это пустая ссылка null).
    q
    ПОДРОБНОСТИ bЕсли в структуре описывается конструктор, тов теле конструктора полям структуры должны быть присвоены значения.
    После того как экземпляр структуры создан, мы можем обращаться кот- крытым полями методам этого экземпляра точно также, как мы это делали с полями и методами объектов. Для этого достаточно указать имя экземпляра структуры и через точку имя поля или имя метода с аргументами в круглых скобках (или пустыми круглыми скобками, если методу не передаются аргументы НАЗ А МЕТКУ Кроме полей и методов, в структуре могут быть описаны свойства, индексаторы и события. Правила их описания и использования такие же, как при работе с объектами и классами. Методы (и индек- саторы) для структур могут перегружаться также, как это делается
    Перечисления и структуры
    141
    для классов. Кроме этого, структура может содержать статические члены. Для обращения к статическим членам вместо имени объекта используют имя структуры.
    Программа с описанием структуры, в которой создаются и используются экземпляры структуры, представлена в листинге Листинг 3.2. Знакомство со структурами System;
    //
    ɋɬɪɭɤɬɭɪɚ:
    struct MyStruct{
    //
    ɐɟɥɨɱɢɫɥɟɧɧɨɟ ɩɨɥɟ:
    public int code;
    //
    Ɍɟɤɫɬɨɜɨɟ ɩɨɥɟ:
    public string name;
    //
    Ʉɨɧɫɬɪɭɤɬɨɪ:
    public MyStruct(int n,string t){
    code=n; //
    Ɂɧɚɱɟɧɢɟ ɰɟɥɨɱɢɫɥɟɧɧɨɝɨ ɩɨɥɹ
    name=t; //
    Ɂɧɚɱɟɧɢɟ ɬɟɤɫɬɨɜɨɝɨ ɩɨɥɹ
    }
    //
    Ɇɟɬɨɞ:
    public void show(){
    //
    Ɉɬɨɛɪɚɠɟɧɢɟ ɡɧɚɱɟɧɢɣ ɩɨɥɟɣ:
    Console.WriteLine(
    Ǝɉɨɥɹ \Ǝ{0}\Ǝ ɢ {1}Ǝ,name,code);
    }
    }
    //
    Ʉɥɚɫɫ ɫ ɝɥɚɜɧɵɦ ɦɟɬɨɞɨɦ:
    class StructDemo{
    //
    Ƚɥɚɜɧɵɣ ɦɟɬɨɞ:
    static void Main(){
    //
    ɋɨɡɞɚɧɢɟ ɷɤɡɟɦɩɥɹɪɚ ɫɬɪɭɤɬɭɪɵ:
    MyStruct A;
    //
    ɉɪɢɫɜɚɢɜɚɧɢɟ ɡɧɚɱɟɧɢɣ ɩɨɥɹɦ:
    Глава 3
    142
    A.code=100;
    A.name=
    Ǝɗɤɡɟɦɩɥɹɪ AƎ;
    //
    ȼɵɡɨɜ ɦɟɬɨɞɚ:
    A.show();
    //
    ɋɨɡɞɚɧɢɟ ɷɤɡɟɦɩɥɹɪɚ ɫɬɪɭɤɬɭɪɵ:
    MyStruct B=new MyStruct(200,
    Ǝɗɤɡɟɦɩɥɹɪ BƎ);
    //
    ȼɵɡɨɜ ɦɟɬɨɞɚ:
    B.show();
    //
    ɉɪɢɫɜɚɢɜɚɧɢɟ ɷɤɡɟɦɩɥɹɪɨɜ:
    A=B;
    //
    ɉɪɢɫɜɚɢɜɚɧɢɟ ɡɧɚɱɟɧɢɹ ɩɨɥɸ:
    B.code=300;
    //
    ȼɵɡɨɜ ɦɟɬɨɞɨɜ:
    A.show();
    B.show();
    Результат выполнения программы представлен ниже:
    
    Результат выполнения программы (из листинга 3.2)
    ɉɨɥɹ Ǝɗɤɡɟɦɩɥɹɪ AƎ ɢ 100
    ɉɨɥɹ Ǝɗɤɡɟɦɩɥɹɪ BƎ ɢ 200
    ɉɨɥɹ Ǝɗɤɡɟɦɩɥɹɪ BƎ ɢ 200
    ɉɨɥɹ Ǝɗɤɡɟɦɩɥɹɪ BƎ ɢ Мы описываем структуру MyStruct следующим образом (комментарии для удобства удалены MyStruct{
    public int code;
    public string name;
    public MyStruct(int n,string t){
    code=n;
    Перечисления и структуры name=t;
    }
    public void show(){
    Console.WriteLine(
    Ǝɉɨɥɹ \Ǝ{0}\Ǝ ɢ {1}Ǝ,name,code);
    У этой структуры есть два открытых поля целочисленное (тип int) поле code и текстовое (тип string) поле name. Мы также описали конструктор структуры с двумя аргументами (целое число и текст, которые определяют значения полей создаваемого экземпляра. Таким образом, при создании экземпляров структуры мы можем использовать либо конструктор по умолчанию (без аргументов, либо конструктор с двумя аргументами. Еще в структуре описан метод show(). Он не имеет аргументов и не возвращает результат. При вызове метод отображает в консольном окне значения полей экземпляра, из которого он был вызван.
    В главном методе программы командой MyStruct A создается экземпляр структуры MyStruct. В данном случае при создании экземпляра его поляне инициализируются. Поэтому нам нужно присвоить значения полям экземпляра ПОДРОБНОСТИ bПри создании экземпляра структуры вместо команды
    MyStruct
    A
    мы могли использовать команду
    MyStruct
    A=new
    MyStruct()
    . В этом случае поле code получило бы значение по умолчанию
    0
    , а поле name содержало бы пустую ссылку Присваивание значений полям осуществляется командами A.code=100 и A.name=
    Ǝɗɤɡɟɦɩɥɹɪ AƎ. После этого командой A.show() из экземпляра структуры вызывается метод show(), в результате чего в консольном окне отображаются значения полей экземпляра.
    Еще один экземпляр структуры создается командой
    MyStruct
    B=new MyStruct(200,
    Ǝɗɤɡɟɦɩɥɹɪ BƎ). В данном случае экземпляр B создается вызовом конструктора с двумя аргументами, и поля экземпляра получают значения, переданные конструктору в качестве аргументов. Проверяем значения полей с помощью команды
    B.show()
    Глава В программе есть пример операции присваивания командой A=B экземпляр присваивается в качестве значения экземпляру A. Если бы мы имели дело с объектами класса, то копирование выполнялось бы на уровне ссылок на объекты, ив результате обе переменные ссылались бы на один и тот же объект. В данном случае значениями переменных и B являются не ссылки, асами экземпляры. Команда присваивания выполняется как побитовое копирование значений полей из экземпляра B в экземпляр A. В результате поле name экземпляра A получает значение
    Ǝɗɤɡɟɦɩɥɹɪ BƎ, а поле code экземпляра A получает значение 200. При этом оба экземпляра остаются физически разными. Поэтому при выполнении команды B.code=300 поле code экземпляра
    B
    получает значение 300, а поле code экземпляра A остается со значением. В том, что это действительно так, мы убеждаемся с помощью команд A.show() и Далее мы рассмотрим некоторые особенности использования структур на практике.
    Массив как поле структуры Вы можете сказать, что им придет в голову Все что угодно И я того же мнения.
    из к/ф Собачье сердце»
    Хотя структура сама по себе относится к типу данных с прямым доступом к значению, среди полей структуры могут быть значения ссылочных типов. Одна из таких ситуаций — когда поле структуры является массивом (ссылкой на массив. Соответствующая программа представлена в листинге Листинг 3.3. Массив как поле структуры System;
    //
    ɋɬɪɭɤɬɭɪɚ:
    struct MyStruct{
    //
    ɋɫɵɥɤɚ ɧɚ ɫɢɦɜɨɥɶɧɵɣ ɦɚɫɫɢɜ:
    public char[] symbs;
    Перечисления и структуры //
    Ɇɟɬɨɞ ɞɥɹ ɨɬɨɛɪɚɠɟɧɢɹ ɫɨɞɟɪɠɢɦɨɝɨ ɦɚɫɫɢɜɚ:
    public void show(){
    for(int k=0;k Console.Write(
    Ǝ|Ǝ+symbs[k]);
    }
    Console.WriteLine(
    Ǝ|Ǝ);
    }
    }
    //
    Ʉɥɚɫɫ ɫ ɝɥɚɜɧɵɦ ɦɟɬɨɞɨɦ:
    class ArrayInStructDemo{
    //
    Ƚɥɚɜɧɵɣ ɦɟɬɨɞ:
    static void Main(){
    //
    ɋɨɡɞɚɧɢɟ ɷɤɡɟɦɩɥɹɪɨɜ ɫɬɪɭɤɬɭɪɵ:
    MyStruct A,B;
    //
    ɉɨɥɸ ɩɪɢɫɜɚɢɜɚɟɬɫɹ ɫɫɵɥɤɚ ɧɚ ɦɚɫɫɢɜ
    A.symbs=new char[7];
    //
    Ɂɚɩɨɥɧɟɧɢɟ ɦɚɫɫɢɜɚ:
    for(int k=0;k A.symbs[k]=(char)(
    ƍAƍ+k);
    }
    Console.WriteLine(
    Ǝɗɤɡɟɦɩɥɹɪ A:Ǝ);
    //
    ɋɨɞɟɪɠɢɦɨɟ ɦɚɫɫɢɜɚ:
    A.show();
    //
    ɉɪɢɫɜɚɢɜɚɧɢɟ ɷɤɡɟɦɩɥɹɪɨɜ ɫɬɪɭɤɬɭɪɵ:
    B=A;
    Console.WriteLine(
    Ǝɗɤɡɟɦɩɥɹɪ B:Ǝ);
    //
    ɋɨɞɟɪɠɢɦɨɟ ɦɚɫɫɢɜɚ:
    B.show();
    //
    ɉɪɢɫɜɚɢɜɚɧɢɟ ɡɧɚɱɟɧɢɣ ɷɥɟɦɟɧɬɚɦ ɦɚɫɫɢɜɚ:
    A.symbs[0]='X';
    B.symbs[B.symbs.Length-1]='Y';
    Console.WriteLine(
    Ǝɗɤɡɟɦɩɥɹɪ A:Ǝ);
    Глава 3
    1   ...   7   8   9   10   11   12   13   14   ...   40


    написать администратору сайта