Class VBUserDefinedTypeLayout
Where each field of a VBUserDefinedType sits in memory, and how much memory the whole type occupies — MS-VBAL §2.1's "linear concatenation of the aggregated data values possibly with implementation defined padding between data values".
public sealed class VBUserDefinedTypeLayout
- Inheritance
-
VBUserDefinedTypeLayout
- Inherited Members
Remarks
A UDT has two sizes, and MS-VBAL §6.1.2.11 says so where it defines Len
and LenB: "with user-defined types, Len returns the size as it will be written to the file",
while "LenB returns the in-memory size, including any implementation-specific padding between
elements". This is the second one. The first belongs to whatever writes the record — a Put
statement concatenates the fields with no padding at all, so a file is never laid out like memory is.
🎯 The padding is "implementation-specific" by the specification's own word, so RDCore is free to choose
it — and chooses MS-VBA's, because a UDT is exactly the kind of thing whose in-memory size a program
measures with LenB and then relies on. Each field is aligned to its own natural boundary, and the
type as a whole is padded up to the strictest boundary any of its fields asked for.
👉 Widths here are memory widths, which are not always the widths the same value takes in a file:
a variable-length String field is a pointer in memory and its characters in a record, and a
fixed-length String field is Unicode in memory and ANSI in a record. That is the whole reason
Len and LenB disagree about a UDT.
Fields
DefaultPointerWidth
The pointer width a layout assumes when the caller does not say — 32-bit, which is the width every
MS-VBA UDT is laid out for, and therefore the one a file or a LenB from MS-VBA agrees with.
public const int DefaultPointerWidth = 4
Field Value
Remarks
🚧 A 64-bit host lays the same declaration out differently (a pointer field, and
LongPtr, both widen). TODO thread the environment's own pointer width through to here, the
way CLngPtr's declared type already is, once a UDT can be declared in a 64-bit host session.
MaxAlignment
The strictest boundary any field is aligned to, whatever its natural alignment would be.
public const int MaxAlignment = 8
Field Value
Remarks
An 8-byte boundary, which is what a Double, a Currency and a Date each ask for.
Nothing in a UDT asks for more: a Variant is sixteen bytes of data but is itself aligned to
eight, and a fixed-length String or a Byte to one.
Properties
Alignment
The boundary the type as a whole is aligned to: the strictest any of its fields asked for.
public int Alignment { get; }
Property Value
Fields
Each field, in declaration order, with the offset it sits at.
public IReadOnlyList<VBUserDefinedTypeField> Fields { get; }
Property Value
Size
The in-memory size of the whole type, padding included — what LenB reports.
public int Size { get; }
Property Value
Methods
Of(VBUserDefinedType, int)
Lays type out.
public static VBUserDefinedTypeLayout Of(VBUserDefinedType type, int pointerWidth = 4)
Parameters
typeVBUserDefinedTypeThe type to lay out.
pointerWidthintThe host's pointer width in bytes; DefaultPointerWidth unless the caller knows better.
Returns
OffsetOf(string)
The offset of the field named name, or null when the type has no such field.
public int? OffsetOf(string name)
Parameters
namestringThe field name, compared the way VBA compares identifiers.
Returns
- int?