Варіанти та масиви

Як зазначалося раніше, варіанти здатні представлятинеоднорідні(nonhomogene

ous) масиви, тому наступний код синтаксично абсолютно коректний:

Object Pascal надає кілька функцій, що дозволяють створити варіант,

торий є масивом, зокрема функції VarArrayCreate() та VarArrayOf().

Функція VarArrayCreate() визначена в модулі System наступним чином:

function VarArrayCreate(const Bounds: array of Integer; VarType: Integer): Variant;

Функції VarArrayCreate() як параметри передаються межі створюваного масиву і код типу варіанта елементів створюваного масиву. (Перший пара метр є відкритим масивом, мова про який піде далі в цій главі.) Наприклад, у наведеному нижче фрагменті коду створюється варіант масив цілих чисел, після чого його членам присвоюються необхідні значення.

V := VarArrayCreate([1, 4], varInteger); // Створює масив

V[1]: = 1; V[2]: = 2; V[3]: = 3; V[4]: = 4;

Але це ще не все: передавши як параметр тип varVariant, можна створитиваріант масив варіантів(variant array of variants), який являє собою масив, елементи якого можуть містити значення різних типів. Крім того, так само можна створювати і багатовимірні масиви, для чого досить просто вказати додаткові значення кордонів. Наприклад, у наведеному нижче фрагмент коду створюється двомірний варіант масив розмірністю [1..4, 1..5].

V := VarArrayCreate([1, 4, 1, 5], varInteger);

Модуль Variants був доданий до RTL лише Delphi 6, оскільки лише тепер підтримка варіантів була перенесена з модуля System в окремий модуль. Крім усього іншого, подібний фізичний поділ коду дозволив плавно перейти до со-місткості з Kylix, а також забезпечило підтримку варіантів для користувацьких типів даних.Функція VarArrayOf()

Ця функція визначена в модулі System наступним чином:

function VarArrayOf(const Values: array of Variant): Variant;

Вона повертає одновимірний масив, елементи якого були задані у параметрі Values. Нижче наведено приклад створення масиву з трьох елементів: цілого, рядка та речового числа.

V := VarArrayOf([1, 'Delphi', 2.2]);

Функції та процедури для роботи з варіантами масивами

Крім функцій VarArrayCreate() і VarArrayOf(), існують інші функції та процедури, призначені для роботи з варіантами масивами. Вони визначені в модулі System таким чином:

procedure VarArrayRedim(var A: Variant; HighBound: Integer); function VarArrayDimCount(const A: Variant): Integer; function VarArrayLowBound(const A: Variant;

Dim: Integer): Integer;

function VarArrayHighBound(const A: Variant;

Dim: Integer): Integer;

функція VarArrayLock(const A: Variant): Pointer;

procedure VarArrayUnlock(const A: Variant);

function VarArrayRef(const A: Variant): Variant;

функція VarIsArray(const A: Variant): Boolean;

Функція VarArrayRedim() дозволяє змінювати верхню межу розмірності варіанта масиву. Функція VarArrayDimCount() повертає розмірність варіанта масиву, а функції VarArrayLowBound() і VarArrayHighBound() - відповідально повертають нижню і верхню межі варіанта масиву. Докладнішу інформацію про функції VarArrayLock() і VarArrayUnlock() наведено в наступному розділі цього розділу.

Функція VarArrayRef() необхідна передачі варіантів масивів серверу автоматизації OLE. Проблеми виникають у томувипадку, коли методу автоматизації як параметр передається варіант, що містить варіант масив. Наприклад:

Між передачею варіанта масиву і передачі варіанта, що містить варіант масив, існують важливі відмінності. Якщо серверу передати варіант масив, а не посилання на подібний об'єкт, то при використанні вищенаведеного запису сервер видасть повідомлення про помилку. Функція VarArrayRef() призначена для приведення передається значення до виду і типу, очікуваного сервером:

Функція VarIsArray() є простою перевіркою, що повертає значення True, якщо переданий їй параметр є масивом.

Ініціалізація великого масиву за допомогою VarArrayLock()

Варіанти масиви широко використовуються в засобах автоматизації OLE, так як вони є єдиним способом передачі серверу автоматизації довільних двійкових даних. Зазначимо, що покажчики є допустимим типом даних серед автоматизації OLE. Більш детальну інформацію з цієї теми наведено в розділі 15, “Розробка додатків COM”. Але при неправильному використанні варіанти анти масиви можуть виявитися дуже неефективним засобом обміну даними. Розглянемо невеликий приклад:

V := VarArrayCreate([1, 10000], VarByte); Тут створюється варіант масив розміром 10 000 байт. Припустимо, що існує інший, звичайний, масив того ж розміру і необхідно скопіювати його вміст у створений варіант масив. Природний шлях такого копіювання - цикл, подібний до того, що наведено нижче.

V := VarArrayCreate([1, 10000], VarByte);

for i := 1 to 10000 do V[i] := A[i];

Проблема тут полягає у величезній та зовсім зайвій роботі програми з визначення типу та сумісності кожного елемента, його ініціалізації.та ін. Суть у тому, що присвоєння значень елементам масиву здійснюється під час виконання програми. Для виключення всіх цих непотрібних перевірок призначено функцію VarArrayLock() і процедуру VarArrayUnlock().

Функція VarArrayLock() блокує масив у пам'яті так, щоб його не можна було

перемістити чи змінити його розміри. Вона повертає покажчик на дані масиву.

Процедура VarArrayUnlock() деблокує масив, дозволяючи його переміщення в пам'яті та зміну його розмірів. Після блокування масиву для заповнення його даними можна скористатися більш ефективними методами, наприклад, такими як процедура Move(). Наведений нижче приклад дозволяє ініціалізувати той самий масив значно ефективнішим методом.

V := VarArrayCreate([1, 10000], VarByte);

Існує ще кілька функцій та процедур, призначених для роботи з варіантами. Нижче наведено їх визначення у модулі System.

procedure VarClear(var V: Variant);

procedure VarCopy(var Dest: Variant; const Source: Variant);

procedure VarCast(var Dest: Variant; const Source: Variant;

функція VarType(const V: Variant): Integer;

функція VarAsType(const V: Variant; VarType: Integer): Variant;

функція VarIsEmpty(const V: Variant): Boolean;

функція VarIsNull(const V: Variant): Boolean;

функція VarToStr(const V: Variant): string;

function VarFromDateTime(DateTime: TDateTime): Variant;

функція VarToDateTime(const V: Variant): TDateTime;

Процедура VarClear() очищає варіант і поміщає у його полі VType значення varEmpty. Процедура VarCopy() копіює варіант Source у варіант Dest. Процедура VarCast() призначена для перетворення варіанту в деякий тип і збереження результату віншому варіанті. Функція VarType() повертає значення типу varXXXXдля заданого варіанта. Функція VarAsType() має те саме значення, як і процедура VarCast(). Функція VarIsEmpty() повертає значення True, якщо поле VType варіанта дорівнює VarEmpty, а функція VarIsNull() повертає це значення, якщо дане поле дорівнює VarNull. Функція VarToStr() конвертує варіант у рядок (порожній, якщо варіант порожній або нульовий). За допомогою функції VarFromDateTime() створюється варіант, що містить задане значення типу TDateTime. Функція VarToDateTime() повертає значення типу TDateTime, що міститься у вказаному варіанті.

Тип даних OleVariant практично у всьому ідентичний розглянутому вище типу Variant, за одним винятком - він допускає використання тільки тих типів даних, які сумісні із засобами автоматизації OLE. В даний час єдина відмінність проявляється під час роботи з рядками (тип VarString призначений для рядків типу AnsiString). У той час як тип Variant працює з подібними рядками, при присвоєнні рядкового значення типу AnsiString перемінної типу OleVariant відбувається автоматичне конвертування цього рядка в тип OLE BSTR і збереження його у варіанті як тип VarOleStr.

Джерело: Тейксейра, Стів, Пачеко, Ксав'є. Borland Delphi 6. Посібник розробника. : Пров. з англ. - М.: Видавничий дім "Вільямс", 2002. - 1120 с. : іл. - Парал. тит. англ.