Главная » Delphi » Варианты и массивы

0

Как отмечалось ранее, варианты способны представлять неоднородные (nonhomogene

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

var

V: Variant;

I, J: Integer;

begin

I := V[J];

end;

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

торый является массивом, в частности функции VarArrayCreate() и VarArrayOf().

Функция VarArrayCreate()

Функция VarArrayCreate() определена в модуле System следующим образом:

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

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

var

V: Variant;

begin

V := VarArrayCreate([1, 4], varInteger); // Создает массив

// из 4 элементов

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

end;

Но это еще не все: передав в качестве параметра тип 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;

function VarArrayLock(const A: Variant): Pointer;

procedure VarArrayUnlock(const A: Variant);

function VarArrayRef(const A: Variant): Variant;

function VarIsArray(const A: Variant): Boolean;

Функция  VarArrayRedim() позволяет изменять верхнюю границу  размерности самого   варианта массива.   Функция   VarArrayDimCount() возвращает размерность варианта массива,  а функции  VarArrayLowBound() и VarArrayHighBound() —  со ответственно  возвращают  нижнюю  и  верхнюю  границы  варианта массива.   Более подробная информация о функциях VarArrayLock() и VarArrayUnlock() приве дена в следующем разделе этой главы.

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

Server.PassVariantArray(VA);

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

Server.PassVariantArray(VarArrayRef(VA));

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

Инициализация большого массива с помощью VarArrayLock()

и VarArrayUnlock()

Варианты массивы  широко используются в средствах автоматизации OLE,  так  как они представляют собой  единственный способ  передачи серверу  автоматизации произ вольных двоичных данных.  Отметим, что  указатели  не  являются  допустимым типом данных  в среде автоматизации OLE. Более подробная информация по этой теме приве дена в главе 15, “Разработка приложений COM”. Но при неверном использовании вари анты массивы  могут оказаться весьма неэффективным средством обмена  данными. Рас смотрим небольшой пример:

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

begin

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

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

end;

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

Функция  VarArrayLock() блокирует массив  в памяти так,  чтобы  его нельзя  было

переместить или изменить его размеры. Она  возвращает указатель  на данные  массива.

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

begin

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

P := VarArrayLock(V);

try

Move(A, P^, 10000);

finally

VarArrayUnlock(V);

end;

end;

Вспомогательные функции

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

procedure VarClear(var V: Variant);

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

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

VarType: Integer);

function VarType(const V: Variant): Integer;

function VarAsType(const V: Variant; VarType: Integer): Variant;

function VarIsEmpty(const V: Variant): Boolean;

function VarIsNull(const V: Variant): Boolean;

function VarToStr(const V: Variant): string;

function VarFromDateTime(DateTime: TDateTime): Variant;

function 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

Тип данных  OleVariant практически во всем идентичен рассмотренному выше типу Variant, за одним  исключением — он допускает  использование только  тех ти пов данных, которые совместимы со средствами автоматизации OLE. В настоящее время  единственное отличие проявляется при  работе со строками (тип  VarString предназначен для строк  типа  AnsiString). В то время  как тип Variant работает с подобными строками, при  присвоении строкового значения типа  AnsiString пе ременной  типа   OleVariant происходит  автоматическое  конвертирование  этой строки в тип OLE BSTR и сохранение ее в варианте как тип VarOleStr.

Тип Currency

Этот  тип  впервые был введен  в Delphi  2 и представляет собой  десятичное число  с фиксированной точкой, имеющее 15 значащих цифр до десятичной точки  и 4 после. Данный формат идеально подходит для финансовых вычислений, поскольку  позволяет избежать ошибок  округления, свойственных операциям над числами с плавающей точ кой. Настоятельно рекомендуем заменить все участвующие  в финансовых расчетах пе ременные типа Single, Real, Double и Extended на тип Currency.

Источник: Тейксейра, Стив, Пачеко, Ксавье.   Borland Delphi 6. Руководство разработчика. : Пер.  с англ. — М. : Издательский дом “Вильямс”, 2002. —  1120 с. : ил. — Парал. тит. англ.

По теме:

  • Комментарии