Размер структуры FixedBankRecord оказывается в точности равным сумме ее чле нов, но так бывает далеко не всегда со структурами, содержащими буферы фиксиро ванного размера. Ради повышения эффективности кода общая длина структуры мо жет быть увеличена для выравнивания по четной границе, например по границе слова. Поэтому общая длина структуры может оказаться на несколько байтов больше, чем сумма ее членов, даже если в ней содержатся буферы фиксированного размера. Как правило, аналогичное выравнивание длины структуры происходит и в C++. Следует, однако, иметь в виду возможные отличия в этом отношении.
И наконец, обратите внимание на то, как в данной программе создается буфер фик сированного размера вместо массива Name. public fixed byte Name[80]; // создать буфер фиксированного размера
Как видите, размер массива указывается после его имени. Такое обозначение обычно принято в C++ и отличается в объявлениях массивов в С#. В данном операторе распре деляется по 80 байтов памяти в пределах каждого объекта типа FixedBankRecord. Обнуляемые типы
Начиная с версии 2.0, в C# внедрено средство, обеспечивающее изящное решение типичной и не очень приятной задачи распознавания и обработки полей, не содержа щих значения, т.е. неинициализированных полей. Это средство называется обнуляемым типом. Для того чтобы стала более понятной суть данной задачи, рассмотрим пример простой базы данных заказчиков, в которой хранится запись с именем, адресом, иден тификационным номером заказчика, номером счета-фактуры и текущим остатком на счету. В подобной ситуации может быть вполне создан элемент данных заказчика, в ко тором одно или несколько полей не инициализированы. Например, заказчик может просто запросить каталог продукции, и в этом случае номер счета-фактуры не потре буется, а значит, его поле окажется неиспользованным.
Раньше для обработки неиспользуемых полей приходилось применять заполняю щие значения или дополнительные поля, которые просто указывали, используется поле или нет. Безусловно, заполняющие значения пригодны лишь в том случае, если они подставляются вместо значения, которое в противном случае окажется недействи тельным, но так бывает далеко не всегда. А дополнительные поля, указывающие, ис пользуется поле или нет, пригодны во всех случаях, но их ввод и обработка вручную до ставляют немало хлопот. Оба эти затруднения позволяет преодолеть обнуляемый тип. Основы применения обнуляемых типов
Обнуляемый тип — это особый вариант типа значения, представленный структу рой. Помимо значений, определяемых базовым типом, обнуляемый тип позволяет хранить пустые значения (null). Следовательно, обнуляемый тип имеет такой же диа пазон представления чисел и характеристики, как и его базовый тип. Он предоставляет дополнительную возможность обозначить значение, указывающее на то, что перемен ная данного типа не инициализирована. Обнуляемые типы являются объектами типа System.Nullаble<Т>, где Т — тип значения, которое не должно быть обнуляемым.
ПРИМЕЧАНИЕ Обнуляемые эквиваленты могут быть только у типов значений.
Обнуляемый тип может быть указан двумя способами. Во-первых, объекты типа
Nullable
И во-вторых, обнуляемый тип объявляется более кратким и поэтому чаще исполь зуемым способом с указанием знака ? после имени базового типа. В приведенном ниже примере демонстрируется более распространенный способ объявления обну ляемых переменных типа int и bool. int? count; bool? done;
Когда в коде применяются обнуляемые типы, создаваемый обнуляемый объект обычно выглядит следующим образом. int? count = null;
В данной строке кода переменная count явно инициализируется пустым значени ем (null). Это вполне соответствует принятому правилу: прежде чем использовать переменную, ей нужно присвоить значение. В данном случае присваиваемое значение означает, что переменная не определена.
Значение может быть присвоено обнуляемой переменной обычным образом, по скольку преобразование базового типа в обнуляемый определено заранее. Например, в следующей строке кода переменной count присваивается значение 100. count = 100;
Определить, имеет переменная обнуляемого типа пустое или конкретное значение, можно двумя способами. Во-первых, можно проверить переменную на пустое значе ние. Так, если переменная count объявлена так, как показано выше, то в следующей строке определяется, имеет ли эта переменная конкретное значение. if (count != null) // переменная имеет значение