Статья: Visual Basic. User Defined Types

Программирование на Visual Basic, главный форум. Обсуждение тем программирования на VB 1—6.
Даже если вы плохо разбираетесь в VB и программировании вообще — тут вам помогут. В разумных пределах, конечно.
Правила форума
Темы, в которых будет сначала написано «что нужно сделать», а затем просьба «помогите», будут закрыты.
Читайте требования к создаваемым темам.
Diamock
Постоялец
Постоялец
Аватара пользователя
 
Сообщения: 388
Зарегистрирован: 26.10.2009 (Пн) 4:19
Откуда: Кемерово

Статья: Visual Basic. User Defined Types

Сообщение Diamock » 01.05.2011 (Вс) 11:26

Visual Basic. User Defined Types

Типы данных определяемые пользователем
Создание и использование


Содержание

    UDT – создание
    UDT – объявление переменных
    UDT – присвоение и получение значений
    UDT – содержащий массив
    UDT – аргумент процедуры
    UDT – содержащий объект
    UDT – составной
    UDT – копирование

UDT – создание

Кроме базовых типов данных: Integer, Long, String и т.д., Visual Basic поддерживает типы данных, определяемые пользователем – User Defined Types (далее UDT). Комбинируя переменные различных типов, можно создать UDT (известный, в языке программирования Cи, как структура). UDT используется, для создания переменной, содержащей несколько взаимосвязанных частей информации.

Для создания UDT используется ключевое слово Type:

Код: Выделить всё
    'Синтаксис VB
                  [Private | Public] Type TypeName
                                 Element1 [([Size])] As DataType
                                 [Element2 [([Size])] As DataType]
                  End Type

Определение общего (Public) UDT, возможно только в секции (General) (Declarations) модуля. В этом случае, тип будет доступен во всех процедурах всех форм, модулей и модулей классов. Для определения UDT в форме или модуле класса, следует использовать ключевое слово Private, поскольку объявление общего типа в данной ситуации не допускается. При этом, область видимости такого типа, будет ограничена контейнером, где он объявлен.

Код: Выделить всё
                  Private Type MyDataType

или

Код: Выделить всё
                  Public Type MyDataType

Например, можно создать UDT, содержащий информацию о компьютере:

Код: Выделить всё
    ' Декларация в стандартном модуле
                  Private Type SystemInfo
                                CPU As Variant
                                Memory As Long
                                VideoColors As Integer
                                Cost As Currency
                                PurchaseDate As Variant
                  End Type

UDT – объявление переменных

Определив UDT, вы можете использовать его для объявления переменных этого типа. Эти переменные могут быть локальными, глобальными или переменными контейнера:

Код: Выделить всё
                  Dim MySystem As SystemInfo
                  Private YourSystem As SystemInfo

Таблица 1. Контейнеры, где можно объявить UDT и его переменную.

Table_01.png
Table_01.png (2.39 Кб) Просмотров: 1624

Примечание! UDT, объявленный без ключевого слова, по умолчанию считается объявленным, как Public. Если требуется UDT уровня модуля или модуля класса, его следует объявлять, используя ключевое слово Private.

UDT – присвоение и получение значений

Доступ к элементам переменной UDT осуществляется, по аналогии с доступом к свойствам, путем указания точки после имени переменной.

Код: Выделить всё
                  MySystem.CPU = "486"
                  If MySystem.PurchaseDate > #1/1/92# Then

При этом переменные одинакового типа можно присваивать не поэлементно, а напрямую:

Код: Выделить всё
                  YourSystem = MySystem

UDT – содержащий массив

UDT, может содержать обычный (фиксированного размера) массив:

Код: Выделить всё
                  Type SystemInfo
                                CPU As Variant
                                Memory As Long
                                DiskDrives(25) As String              ' Фиксированный массив
                                VideoColors As Integer
                                Cost As Currency
                                PurchaseDate As Variant
                  End Type

А также, может содержать динамический массив.

Код: Выделить всё
                  Type SystemInfo
                                CPU As Variant
                                Memory As Long
                                DiskDrives() As String              ' Динамический массив
                                VideoColors As Integer
                                Cost As Currency
                                PurchaseDate As Variant
                  End Type

Доступ к значениям элементов массива, UDT осуществляется, по аналогии с доступом к свойству объекта.

Код: Выделить всё
                  Dim MySystem As SystemInfo
                  ReDim MySystem.DiskDrives(3)
                  MySystem.DiskDrives(0) = "1.44 MB"

Также, можно объявить массив UDT:

Код: Выделить всё
                  Dim AllSystems(100) As SystemInfo

Для доступа к элементам этого типа, следуем тем же правилам.

Код: Выделить всё
                  AllSystems(5).CPU = "386SX"
                  AllSystems(5).DiskDrives(2) = "100M SCSI"

UDT – аргумент процедуры

UDT можно использовать, как один из аргументов процедуры.

Код: Выделить всё
                  Sub FillSystem (SomeSystem As SystemInfo)
                                SomeSystem.CPU = lstCPU.Text
                                SomeSystem.Memory = txtMemory.Text
                                SomeSystem.Cost = txtCost.Text
                  SomeSystem.PurchaseDate = Now
                  End Sub

Примечание! При использовании UDT, в качестве аргумента процедуры в модуле формы, процедура должна быть объявлена, как Private.

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

Примечание! Поскольку UDT всегда передается по ссылке, все данные, будут переданы и получены без проблем. Для UDT, содержащих большие массивы данных, это может привести к снижению производительности, особенно в архитектуре клиент-серверных приложений, где процедура может быть запущена на удаленной машине. В такой ситуации, лучше, принимать и передавать только необходимые данные полей UDT.

UDT – содержащий объект

UDT, может содержать объект.

Код: Выделить всё
                  Private Type AccountPack
                                frmInput as Form
                                dbPayRollAccount as Database
                  End Type

Примечание! Поскольку тип Variant может хранить различные типы данных, массив Variant может быть использован во многих ситуациях, где можно использовать UDT. Массив Variant, на самом деле более гибкий, чем UDT, потому что можно изменить тип данных, хранящихся в каждом его элементе в любое время, и можно сделать массив динамическим, и изменять размер по мере необходимости. Однако, массив Variant, всегда использует больше памяти, чем эквивалентные UDT.

UDT – составной

UDT, может быть составным. В этом случае важна последовательность определения UDT. Сначала нужно определить основной UDT, который будет использоваться далее в составных UDT. Если не соблюдать это правило, то после запуска программы появится сообщение об ошибке. Ниже приводится пример использования составных UDT:

Код: Выделить всё
                  Type DriveInfo
                                Type As String
                                Size As Long
                  End Type
     
                  Type SystemInfo
                                CPU As Variant
                                Memory As Long
                                DiskDrives(26) As DriveInfo
                                Cost As Currency
                                PurchaseDate As Variant
                  End Type
     
                  Dim AllSystems(100) As SystemInfo
                  AllSystems(1).DiskDrives(0).Type = "Floppy"

UDT, рекомендуется использовать при обработке данных неизменной структуры.

UDT – копирование

Рассмотрим оператор Visual Basic – LSet

Код: Выделить всё
    'Синтаксис VB
    LSet StringVariable = StringExpression

LSet – выравнивает строку по левой стороне, при присваивании ей значения, меньшего по размеру, чем исходная строка. Вместо строк могут использоваться UDT.

Вспомним базовые типы данных Visual Basic

Таблица 2. Базовые типы данных Visual Basic

Table_02.png

Определимся со значениями некоторых типов данных.

Boolean: может принимать – True или False (в Visual Basic – False, всегда принимает нулевое значение; True – любое значение отличное от нуля)
Decimal: не используется.
Object: ссылка на объект (указатель)
Variant: универсальный тип, значением которого могут быть данные любого из перечисленных выше типов, объекты, значения NULL, Empty и значения ошибок ERROR.

Рассмотрим следующий пример:

Код: Выделить всё
    'Объявление UDT
                  Private Type TypeExempleOne
                                Element_1 As Integer
                                Element_2 As Long
                  End Type
     
                  Private Type TypeExempleTwo
                                Element_1 As Integer
                                Element_2 As Long
                  End Type
     
    Private Sub CopyUDT()
    'Объявление переменных UDT
                  Dim teo As TypeExempleOne
                  Dim tet As TypeExempleTwo
     
    'Присваивание значений
                  teo.Element_1 = 11
                  teo.Element_2 = 1111111
     
                  tet.Element_1 = 22
                  tet.Element_2 = 222222
     
    'Выводим на печать присвоенные значения
                  Debug.Print "Значения до копирования"
                  Debug.Print "teo.Element_1 = " & teo.Element_1, "teo.Element_2 = " & teo.Element_2
                  Debug.Print "tet.Element_1 = " & tet.Element_1, "tet.Element_2 = " & tet.Element_2
     
    'Копируем один UDT в другой
                  LSet tet = teo
     
    'Выводим на печать значения после копирования
                  Debug.Print "Значения после копирования"
                  Debug.Print "teo.Element_1 = " & teo.Element_1, "teo.Element_2 = " & teo.Element_2
                  Debug.Print "tet.Element_1 = " & tet.Element_1, "tet.Element_2 = " & tet.Element_2
     
    End Sub

В окне Immediate мы увидим следующие значения:

Значения до копирования
teo.Element_1 = 11 teo.Element_2 = 1111111
tet.Element_1 = 22 tet.Element_2 = 222222
Значения после копирования
teo.Element_1 = 11 teo.Element_2 = 1111111
tet.Element_1 = 11 tet.Element_2 = 1111111

При копировании UDT надо придерживаться простого правила: логические (а не фактические) поля должны иметь тот же размер и должны быть расположены в том же порядке, что и соответствующие поля в копируемой структуре.

Немного изменим пример:

Код: Выделить всё
    'Объявление пользовательских типов
                  Private Type TypeExempleOne
                                Element_1 As Integer
                                Element_2 As Long
                  End Type
     
                  Private Type TypeExempleTwo
                                Element_1 As Boolean
                                Element_2 As Long
                  End Type
     
    Private Sub CopyUDT()
    'Объявление переменных пользовательского типа
                  Dim teo As TypeExempleOne
                  Dim tet As TypeExempleTwo
     
    'Присваивание значений
                  teo.Element_1 = 11
                  teo.Element_2 = 1111111
     
                  tet.Element_1 = False
                  tet.Element_2 = 222222
     
    'Выводим на печать присвоенные значения
    Debug.Print "Значения до копирования"
    Debug.Print "teo.Element_1 = " & teo.Element_1, "teo.Element_2 = " & teo.Element_2
    Debug.Print "tet.Element_1 = " & tet.Element_1, "tet.Element_2 = " & tet.Element_2
     
    'Копируем один тип данных в другой
    LSet tet = teo
     
    'Выводим на печать значения после копирования
    Debug.Print "Значения после копирования"
    Debug.Print "teo.Element_1 = " & teo.Element_1, "teo.Element_2 = " & teo.Element_2
    Debug.Print "tet.Element_1 = " & tet.Element_1, "tet.Element_2 = " & tet.Element_2
     
    End Sub

В окне Immediate мы увидим следующие значения:

Значения до копирования
teo.Element_1 = 11 teo.Element_2 = 1111111
tet.Element_1 = False tet.Element_2 = 222222
Значения после копирования
teo.Element_1 = 11 teo.Element_2 = 1111111
tet.Element_1 = True tet.Element_2 = 1111111

В первом примере, мы копировали полностью идентичные UDT, в изменённом – скопировали в Boolean переменную, значение типа Integer.
Как видно из таблицы 2, тип Boolean занимает в памяти 2 байта. Тип данных Integer – 2 байта. Тип данных Long занимает в памяти 4 байта. Значит, общий размер каждого UDT, составляет 6 байт, мы не нарушили правило при копировании.

Соответственно, зная размеры занимаемой памяти, базовых типов Visual Basic, можно легко определиться с копированием UDT.

Например: Long(4 байта) = двухэлементный массив Integer(4 байт)

С уважением Diamock.

P.S. К сожалению, не знаю тега таблица, поэтому вставил рисунки.

Жду конструктивные комментарии и критику.
In der Beschrankung zeigt sich erst der Meister
Графоманю...

Хакер
Телепат
Телепат
Аватара пользователя
 
Сообщения: 16478
Зарегистрирован: 13.11.2005 (Вс) 2:43
Откуда: Казахстан, Петропавловск

Re: Статья: Visual Basic. User Defined Types

Сообщение Хакер » 01.05.2011 (Вс) 19:37

Ошибок много. Если это статья не для себя (руки размять), а образовательная для других, то лучше такие статьи пока не писать или поменчать их в начале соответствующим образом, чтобы на них не полагались другие люди.
—We separate their smiling faces from the rest of their body, Captain.
—That's right! We decapitate them.

Diamock
Постоялец
Постоялец
Аватара пользователя
 
Сообщения: 388
Зарегистрирован: 26.10.2009 (Пн) 4:19
Откуда: Кемерово

Re: Статья: Visual Basic. User Defined Types

Сообщение Diamock » 02.05.2011 (Пн) 4:16

В первую, очередь для себя. Чтобы структурировать собственные знания.
Ну и об ошибках подробнее можно?
In der Beschrankung zeigt sich erst der Meister
Графоманю...

Хакер
Телепат
Телепат
Аватара пользователя
 
Сообщения: 16478
Зарегистрирован: 13.11.2005 (Вс) 2:43
Откуда: Казахстан, Петропавловск

Re: Статья: Visual Basic. User Defined Types

Сообщение Хакер » 02.05.2011 (Пн) 4:24

Напишу, но позже. Если не напишу, напомни (в личку).
—We separate their smiling faces from the rest of their body, Captain.
—That's right! We decapitate them.

Хакер
Телепат
Телепат
Аватара пользователя
 
Сообщения: 16478
Зарегистрирован: 13.11.2005 (Вс) 2:43
Откуда: Казахстан, Петропавловск

Re: Статья: Visual Basic. User Defined Types

Сообщение Хакер » 02.05.2011 (Пн) 10:22

Diamock писал(а):Кроме базовых типов данных: Integer, Long, String и т.д. т.п., Visual Basic (вообще говоря — COM) поддерживает типы данных, определяемые пользователем – User Defined Types (далее UDT).

Diamock писал(а):Комбинируя переменные поля (члены) различных типов, можно создать UDT (известный,← запятая не нужна в языке программирования Cи,← запятая не нужна как структура).

Вообще говоря, с первого раза кажется, что слово «поля» не употребляется вообще, но на самом деле, оказывается, целых два раза, а ведь это основа темы. Не UDT, известные в Си как структуры, а скорее наоборот. Не лишним было бы и сказать, как это называется в Паскале.

Diamock писал(а):UDT используется, для создания переменной, содержащей несколько взаимосвязанных частей информации.

Ну, с натяжкой переменной. Скажем, не переменной, а значения, являющегося составным. Ведь можно использовать UDT для аргументов и для типов возврата функций и для типов свойств классов/модулей.

Diamock писал(а):Для создания объявления UDT используется ключевое слово Type:

Код: Выделить всё
        'Синтаксис VB   ### Хакер: Я бы сказал, что он неверный ###
                      [Private | Public] Type TypeName
                                     Element1 [([Size])] As DataType
                                     [Element2 [([Size])] As DataType]
                      End Type

Зачем такие большие пробельные оступы, кстати?

Diamock писал(а):Определение общего публичного (общий это shared) (Public) UDT, возможно только в секции (General) (Declarations) объявлений модуля.

Значения-болванки дропдаун-лист-боксов ещё не образуют название секции.

Diamock писал(а):В этом случае, тип будет доступен во всех процедурах всех форм, модулей и модулей классов.

Забыл юзер-контроллы, дизайнеры, юзер-документы. Не проще было бы сказать: во всём проекте? По факту: во всём проекте, а так же в проектах, в которых исходный проект подключен через Project→References.

Diamock писал(а):Для определения UDT в форме или модуле класса, следует использовать ключевое слово Private, поскольку объявление общего публичного типа в данной ситуации не допускается.

Подчеркнутое — грубая ложь. Не допускается объявление Public-типа в Private-модулях классов. Если модуль класса сделан публичным, то в нём легко объявляется Public-UDT. Так что отнюдь не «не допускается».

Diamock писал(а):При этом, область видимости такого типа,←запятая не нужна будет ограничена контейнером, где он объявлен

Ну, впрочем, логично, стоило ли писать о таком? По крайней мере, можно было написать что область видимости UDT совпадает с областью видимости перменной, объявленной с аналогичным модификатором публичности. Информацию надо давать обобщённо, а не переписывать 1000 частных случаев.

Diamock писал(а):Определив UDT, вы можете использовать его для объявления переменных этого типа. Эти переменные могут быть локальными, глобальными или переменными контейнера:

  1. «Переменные контейнера» — впервые слышу и не знаю, что это такое.
  2. Но ещё вы можете использовать его для объявления:
    • аргумента процедуры
    • типа возврата процедуры
    • свойства класса/модуля
    • члена другого UDT
  3. Проще было сказать, что UDT можно использовать во всех тех же случаях, что и базовый тип. Информацию надо давать обобщённо, а не переписывать 1000 частных случаев.

Diamock писал(а):Таблица 1. Контейнеры, где можно объявить UDT и его переменную.

Изображение

  1. Ну с учётом заблуждения о невозможности объявлять не-Private типов в не-статических модулях, последние две строки таблицы ошибочны и не имеют смысла (первые три строки оказываются идентичными).
  2. Другое врождённое уродство таблицы: по горизонтали забыты юзер-контроллы, дизайнеры, юзер-документы. Хотя правила для них идентичны правилам для форм и наследуются от правил для классов.
  3. Ещё врожденное уродство таблицы: по вертикали забыты аргументы, типы возвратов процедур и типы свойств. Хотя правила для них идентичны правилам для нелокальных переменных.
  4. Для переменных кроме Local забыт ещё и Static, если он конечно по-твоему не включен в Local.
  5. В общем, таблица бессмысленна и больше путает, чем вносит порядок.

Diamock писал(а):Примечание! UDT, объявленный без ключевого слова, по умолчанию считается объявленным,←запятая не нужна как Public. Если требуется UDT уровня модуля или модуля класса, его следует объявлять, используя ключевое слово Private.

Не уровня модуля, у UDT нет уровней. Вообще, о таком очевидной вещи стоило бы не писать.

Diamock писал(а):Доступ к элементам полям переменной UDT осуществляется,←запятая не нужна по аналогии с доступом к свойствам,←нужно двоеточие путем указания точки после имени переменной.

Забыт With ... End With. Вообще говоря, по историческим причинам, наоборот, доступ к членам классов аналогичен доступу к членам структур, потому что первое появилось хронологически позже.

Diamock писал(а):UDT,←запятая не нужна может содержать обычный (фиксированного размера) массив:

Всё-таки массив фиксированного размера, а не фиксированный массив. Потому что, хоть мало кто об этом помнит, COM-массивы (aka SafeArray) могут ещё и блокироваться (быть locked). Чтобы не провоцировать нежелательных ассоциаций, нужно применять прилагательное к тому слову, к оторому оно относится напрямую (размер), а не косвенно (массив).

Diamock писал(а):А также,←запятая не нужна может содержать динамический массив.←в предыдущем заявлении было двоеточие


Diamock писал(а):Доступ к значениям элементов массива,←запятая не нужна UDT осуществляется,←запятая не нужна по аналогии с доступом к свойству объекта.

Нет уж, логическая путаница.
Поскольку массив внутри UDT является частным случаем поля, речь идёт не о доступе к полю, ибо о доступе к полям (через точку) уже было сказано. Если речь идёт не о доступе к полю, а о доступе к элементу массива (являющегося полем), то доступ к элементу массива (внутри UDT) осуществляется не по аналогии с доступом к свойству объекта, а по аналогии с доступом к элементу массива не в составе UDT.

Diamock писал(а):Также,←запятая вряд ли нужна можно объявить массив UDT:

Diamock писал(а):Для доступа к элементам этого типа,←запятая не нужна следуем тем же правилам.

Diamock писал(а):UDT можно использовать,←запятая не нужна как один из аргументов процедуры.

Как тип аргумента процедуры. Но не только (ещё тип возврата и тип свойств).

Diamock писал(а):Примечание! При использовании UDT,←запятая не нужна в качестве аргумента процедуры в модуле формы,←запятая не нужна процедура должна быть объявлена,←запятая не нужна как Private.

Это заблуждение. Верное правило: если член (любого рода) не-статического модуля объявлен как Public и в его прототипе используется UDT, то и UDT должен быть объявлен как Public. Остальное — следствия и частные случаи.

Diamock писал(а):UDT,←запятая не нужна можно использовать в качестве типа возвращаемого значения функции, а пользовательскую переменную в качестве одного из аргументов процедуры. UDT всегда передаются по ссылке (ByRef), так что процедура может изменить аргумент и вернуть его в вызываемуюющую функцию процедуру.

Подчёркнутое — это, собственно, что. Что такое пользовательский тип я знаю, а что имеется в виду под пользовательской переменной?

Diamock писал(а):Поскольку UDT всегда передается по ссылке, все данные,←запятая не нужна будут переданы и получены без проблем.

Если речь идёт о передаче UDT, то данные вообще не будут переданы и получены. Будет передан указатель на структуру. Если речь идёт о передаче UDT через границу COM-апартамента (который никуда не девается, но о них многие и не слышали), то здесь имеют место разные случаи маршалинга, причём об одном только этом можно написать в несколько раз большую отдельную статью.

Diamock писал(а):Для UDT, содержащих большие массивы данных, это может привести к снижению производительности, особенно в архитектуре клиент-серверных приложений, где процедура может быть запущена на удаленной машине.

Не «особенно», а только в случаях межапартаментного вызова, когда маршалинг есть.

Diamock писал(а):В такой ситуации,←запятая не нужна лучше,←запятая не нужна принимать и передавать только необходимые данные полей UDT.


Diamock писал(а):UDT,←запятая не нужна может содержать объект.

Грубая ложь. UDT совсем не может содержать объект (хотя на самом деле может, но на том же основании, что и просто массив байтов).
UDT может содержать ссылку на интерфейс COM-объекта. При этом UDT может содержать ссылку, а сам объект будет на удалённой машине, расположенной в другом полушарии. Так-то...

Diamock писал(а):Поскольку тип Variant может хранить различные типы данных, массив Variant может быть использован во многих ситуациях, где можно использовать UDT. Массив Variant, на самом деле, более гибкий, чем UDT, потому что можно изменить тип данных, хранящихся в каждом его элементе в любое время, и можно сделать массив динамическим,←запятая не нужна и изменять размер по мере необходимости. Однако,←запятая не нужна массив Variant,←запятая не нужна всегда использует больше памяти, чем эквивалентные UDT.

Туманный и непонятный текст. Но если это предложение использовать массив Variantов в качестве замены одной UDT-переменной, то это глупейший изврат, что я видел.

Diamock писал(а):UDT,←запятая не нужна может быть составным.


Diamock писал(а):В этом случае важна последовательность определения объявления UDT. Сначала нужно определить объявить основной UDT, который будет использоваться далее в составных UDT.

Сперва нужно было объяснить само понятие «составной». Но вообще, составной — не удачный термин. И было бы достаточным давно сказать, что типом поля одного UDT может быть другой UDT. Термин «основной» в отношении UDT, от которого зависят другие UDT, совершенно неудачен. В программировании практика, когда какая-то сущность используется, а только потом объявляется, называется форвард-декларацией (forward-declaration). Во многих языках, не только в VB. Следовало просто сказать, что форвард-декларации в отношении UDT не допускаются (о чём честно повествует сообщения об ошибке).

Diamock писал(а):Если не соблюдать это правило, то после запуска программы появится сообщение об ошибке.

Не правда, ошибка не появится после запуска, потому что сам запуск не состоится. Ошибка появится при попытке компиляции. Компиляция не состоится и нечего будет запускать.

Diamock писал(а):UDT,←запятая не нужна рекомендуется использовать при обработке данных неизменной структуры.

Фраза ни о чём.

Diamock писал(а):Рассмотрим оператор Visual Basic – LSet

LSet — не оператор, а ключевое слово, стоящее как альтернатива ключевому слову Let или Set (или RSet), которое определяет род оператор присвоения «равно» (=). В принципе, можно рассматривать это как четыре двухтокенных оператора (Let <lvalue> = <rvalue>, Set <lvalue> = <value>, LSet <lvalue> = <value> и RSet <lvalue> = <rvalue>), но это не является истиной, потому что это совершенно точно не операторы, потому что нельзя написать a = (lset b = c), как это можно сделать с любым оператором (кроме квази-оператора AddressOf).

Diamock писал(а):LSet – выравнивает строку по левой стороне,←запятая не нужна при присваивании ей значения, меньшего по размеру, чем исходная строка. Вместо строк могут использоваться UDT.

Арабы и евреи негодуют. У них строки выравниваются по правой стороне, потому что письмо RTL-направленное. LSet выравниает по начальной границе. При этом не обязательно меньшего размера: размер может быть равным и даже большим.



Diamock писал(а):Вспомним базовые типы данных Visual Basic
Таблица 2. Базовые типы данных Visual Basic
Изображение
Определимся со значениями некоторых типов данных.

  1. Скорее базовые типы COM. И пожалуй единственный из них, Decimal, не является базовым типом VB, хотя при этом может быть подтипом Variant-значений.
  2. Понятие «Занимаемая память» вообще некорректно. Некоторые переменные являются скалярными и занимают столько, сколько указано, в стеке, секции данных или куче. Другие являются указателями, и занимают 4 байта (в тех же местах). Но часто они на что-то указывают, и это что-то тоже занимает сколько-то места, причём часто по разному. Иногда то, на что указывает указатель, само по себе является указателем или в своём составе имеет указатель.
  3. Decimal занимает не 12, а 16 байт: из них 12 под беззнаковую мантиссу и 4 под показатель степени десятки.
  4. Бред про строку, сказанное прошло мимо ушей (и мозга между ними).
  5. Object занимает 4 байта с тем же успехом, с которым их занимает String и поле внутри Variant-а, указывающее на Decimal.
Diamock писал(а):Boolean: может принимать – True или False (в Visual Basic – False,←здесь должно быть двоеточие всегда принимает нулевое значение,←здесь должна быть запятая True – любое значение отличное от нуля)

Всё насколько иначе. Любое ненулевое значение приводится к True, при этом True всегда равно 16-битному числу со всеми установленными битами (0xFFFF => 65535ui => -1si).

Diamock писал(а):Decimal: не используется.

Используется, как подтип Variant-а.

Diamock писал(а):Object: ссылка на объект (указатель)

Не совсем: ссылка на интерфейс (причём именно IDispatch, а не абы какой) объекта.

Diamock писал(а):Variant: универсальный тип, значением которого могут быть данные любого из перечисленных выше типов, объекты, значения NULL, Empty и значения ошибок ERROR.

  1. Объекты не могут быть значениями Variant, только ссылки на интерфейсы объектов могут быть. Причём не на абы-какие интерфейсы, а либо на IUnknown, либо на IDispatch.
  2. Забыт случай, когда значением Variant-а может быть целый массив.
  3. То, что ты называешь «ERROR» это вообще отдельный случай с hresult-ами, и о нём надо либо подробно рассказывать, либо, по меркам статьи, не рассказывать вообще.


Diamock писал(а):В окне Immediate мы увидим следующие значения:

Ну надо было LSet показать на примере с разными структурами. Например структуру с четырьмя Byte-полями присвоить структуре с одним Long-полем. Это увлекательно. А присваивать LSet-ом структуры с одинаковыми сигнатурами — скучно.

Diamock писал(а):При копировании UDT надо придерживаться простого правила: логические (а не фактические) поля должны иметь тот же размер и должны быть расположены в том же порядке, что и соответствующие поля в копируемой структуре.

Такого правила нет. А это искусственно выдуманное для себя ограничение, никому не нужное.

Diamock писал(а):Как видно из таблицы 2, тип Boolean занимает в памяти 2 байта. Тип данных Integer – 2 байта. Тип данных Long занимает в памяти 4 байта. Значит, общий размер каждого UDT, составляет 6 байт, мы не нарушили правило при копировании.

Мы не нарушили правило, потому что его нет :)
Diamock писал(а):Соответственно, зная размеры занимаемой памяти,←запятая не нужна базовых типов Visual Basic, можно легко определиться с копированием UDT.


Diamock писал(а):Жду конструктивные комментарии и критику.

Пожалуйста.
С запятыми какой-то кошмар.
Совершенно никак не освящён сложный момент: как разные UDT сохраняются и загружаются в/из файл(а) при разных режимах работы с файлом.

Ну и да, ошибок, как видишь, очень много.
—We separate their smiling faces from the rest of their body, Captain.
—That's right! We decapitate them.

Diamock
Постоялец
Постоялец
Аватара пользователя
 
Сообщения: 388
Зарегистрирован: 26.10.2009 (Пн) 4:19
Откуда: Кемерово

Re: Статья: Visual Basic. User Defined Types

Сообщение Diamock » 02.05.2011 (Пн) 14:18

Хакер! Огромное (ну прям слов нет) спасибо за подробные комментарии и разбор ошибок. С запятыми, действительно перестарался :? . Есть много чего осмыслить. Ещё раз спасибо! :D
In der Beschrankung zeigt sich erst der Meister
Графоманю...


Вернуться в Visual Basic 1–6

Кто сейчас на конференции

Сейчас этот форум просматривают: AhrefsBot и гости: 93

    TopList  
cron