Полное руководство. С# 4.0 - Шилдт Герберт
Шрифт:
Интервал:
Закладка:
При выполнении этой программы получается следующий результат.Герберт Шилдт, Полный справочник по C# 4.0, (с) 2010Член book2.Title пуст.Структура bоок2 теперь содержит:Олдос Хаксли, О дивный новый мир, (с) 1932Красный шторм
Как демонстрирует приведенный выше пример программы, структура может бытьинициализирована с помощью оператора new для вызова конструктора или же путемпростого объявления объекта. Так, если используется оператор new, то поля структурыинициализируются конструктором, вызываемым по умолчанию (в этом случае во всехполях устанавливается задаваемое по умолчанию значение), или же конструктором,определяемым пользователем. А если оператор new не используется, как это имеетместо для структуры bоок3, то объект структуры не инициализируется, а его полядолжны быть установлены вручную перед тем, как пользоваться данным объектом.
Когда одна структура присваивается другой, создается копия ее объекта. В этом заключается одно из главных отличий структуры от класса. Как пояснялось ранее в этойкниге, когда ссылка на один класс присваивается ссылке на другой класс, в итоге ссылкав левой части оператора присваивания указывает на тот же самый объект, что и ссылкав правой его части. А когда переменная одной структуры присваивается переменнойдругой структуры, создается копия объекта структуры из правой части оператора присваивания. Рассмотрим в качестве примера следующую программу.// Скопировать структуру.using System;// Определить структуру.struct MyStruct { public int x;}// Продемонстрировать присваивание структуры.class StructAssignment { static void Main() { MyStruct a; MyStruct b; a.x = 10; b.x = 20; Console.WriteLine("a.x {0}, b.x {1}", a.x, b.x); a = b; b.x = 30; Console.WriteLine("a.x {0}, b.x {1}", a.x, b.x); }}
Вот к какому результату приводит выполнение этой программы.а.х 10, b.x 20a.x 20, b.x 30
Как показывает приведенный выше результат, после присваиванияа = b;
переменные структуры а и b по-прежнему остаются совершенно обособленными,т.е. переменная а не указывает на переменную b и никак не связана с ней, помимо того,что она содержит копию значения переменной b. Ситуация была бы совсем иной, еслибы переменные а и b были ссылочного типа, указывая на объекты определенного класса. В качестве примера ниже приведен вариант предыдущей программы, где демонстрируется присваивание переменных ссылки на объекты определенного класса.// Использовать ссылки на объекты определенного класса.using System;// Создать класс.class MyClass { public int x;}// Показать присваивание разных объектов данного класса.class ClassAssignment { static void Main() { MyClass a = new MyClass(); MyClass b = new MyClass(); a.x = 10; b.x = 20; Console.WriteLine("a.x {0}, b.x {1}", a.x, b.x); a = b; b.x = 30; Console.WriteLine("а.х {0}, b.x {1}", a.x, b.x); }}
Выполнение этой программы приводит к следующему результату.а.х 10, b.x 20а.х 30, b.x 30
Как видите, после того как переменная b будет присвоена переменной а, обе переменные станут указывать на один и тот же объект, т.е. на тот объект, на который первоначально указывала переменная b.О назначении структур
В связи с изложенным выше возникает резонный вопрос: зачем в C# включенаструктура, если она обладает более скромными возможностями, чем класс? Ответ наэтот вопрос заключается в повышении эффективности и производительности программ. Структуры относятся к типам значений, и поэтому ими можно оперироватьнепосредственно, а не по ссылке. Следовательно, для работы со структурой вообще нетребуется переменная ссылочного типа, а это означает в ряде случаев существеннуюэкономию оперативной памяти. Более того, работа со структурой не приводит к ухудшению производительности, столь характерному для обращения к объекту класса.Ведь доступ к структуре осуществляется непосредственно, а к объектам — по ссылке,поскольку классы относятся к данным ссылочного типа. Косвенный характер доступак объектам подразумевает дополнительные издержки вычислительных ресурсов накаждый такой доступ, тогда как обращение к структурам не влечет за собой подобныеиздержки. И вообще, если нужно просто сохранить группу связанных вместе данных,не требующих наследования и обращения по ссылке, то с точки зрения производительности для них лучше выбрать структуру.
Ниже приведен еще один пример, демонстрирующий применение структуры напрактике. В этом примере из области электронной коммерции имитируется записьтранзакции. Каждая такая транзакция включает в себя заголовок пакета, содержащийномер и длину пакета. После заголовка следует номер счета и сумма транзакции. Заголовок пакета представляет собой самостоятельную единицу информации, и поэтомуон организуется в отдельную структуру, которая затем используется для создания записи транзакции или же информационного пакета любого другого типа.// Структуры удобны для группирования небольших объемов данных.using System;// Определить структуру пакета.struct PacketHeader { public uint PackNum; // номер пакета public ushort PackLen; // длина пакета}// Использовать структуру PacketHeader для создания записи транзакции// в сфере электронной коммерции.class Transaction { static uint transacNum = 0; PacketHeader ph; // ввести структуру PacketHeader в класс Transaction string accountNum; double amount; public Transaction(string acc, double val) { // создать заголовок пакета ph.PackNum = transacNum++; ph.PackLen = 512; // произвольная длина accountNum = acc; amount = val; } // Сымитировать транзакцию. public void sendTransaction() { Console.WriteLine("Пакет #: " + ph.PackNum + ", Длина: " + ph.PackLen + ",n Счет #: " + accountNum + ", Сумма: {0:C}n", amount); }}// Продемонстрировать применение структуры в виде пакета транзакции.class PacketDemo { static void Main() { Transaction t = new Transaction("31243", -100.12); Transaction t2 = new Transaction("AB4655", 345.25); Transaction t3 = new Transaction("8475-09", 9800.00); t.sendTransaction(); t2.sendTransaction(); t3.sendTransaction(); }}
Вот к какому результату может привести выполнение этого кода.Пакет #: 0, Длина: 512, Счет #: 31243, Сумма: ($100.12)Пакет #: 1, Длина: 512, Счет #: АВ4655, Сумма: $345.25Пакет #: 2, Длина: 512, Счет #: 8475-09, Сумма: $9,800.00
Структура PacketHeader оказывается вполне пригодной для формирования заголовка пакета транзакции, поскольку в ней хранится очень небольшое количество данных, не используется наследование и даже не содержатся методы. Кроме того, работасо структурой PacketHeader не влечет за собой никаких дополнительных издержек,связанных со ссылками на объекты, что весьма характерно для класса. Следовательно,структуру PacketHeader можно использовать для записи любой транзакции, не снижая эффективность данного процесса.
Любопытно, что в С++ также имеются структуры и используется ключевое словоstruct. Но эти структуры отличаются от тех, что имеются в С#. Так, в C++ структураотносится к типу класса, а значит, структура и класс в этом языке практически равноценны и отличаются друг от друга лишь доступом по умолчанию к их членам, которыеоказываются закрытыми для класса и открытыми для структуры. А в С# структура относится к типу значения, тогда как класс — к ссылочному типу.Перечисления
Перечисление представляет собой множество именованных целочисленных констант.Перечислимый тип данных объявляется с помощью ключевого слова enum. Ниже приведена общая форма объявления перечисления:enum имя {список_перечисления};
где имя — это имя типа перечисления, а список_перечисления — список идентификаторов, разделяемый запятыми.В приведенном ниже примере объявляется перечисление Apple различных сортовяблок.enum Apple { Jonathan, GoldenDel, RedDel, Winesap, Cortland, McIntosh };
Следует особо подчеркнуть, что каждая символически обозначаемая константав перечислении имеет целое значение. Тем не менее неявные преобразования перечислимого типа во встроенные целочисленные типы и обратно в C# не определены,а значит, в подобных случаях требуется явное приведение типов. Кроме того, приведение типов требуется при преобразовании двух перечислимых типов. Но посколькуперечисления обозначают целые значения, то их можно, например, использовать дляуправления оператором выбора switch или же оператором цикла for.