Библиотека программиста

«Машины должны работать. Люди должны думать»

Девиз компании IBM

Главная страница > Язык Object Pascal > 14. Тип Variant

14. Тип Variant

Иногда бывает необходимо обрабатывать данные, тип которых на этапе компиляции не известен. В этом случае выходом может служить использование типа Variant. Этот тип представляет такие значения, тип которых может изменяться на этапе выполнения программы.

Тип Variant предоставляет большую гибкость, однако поглощает больше памяти по сравнению с соответствующими переменными и операции над данными типа Variant выполняются медленнее.

Более того, недопустимые операции над данными этого типа чаще приводят к ошибкам на этапе выполнения программы, в то время как подобные ошибки над данными другого типа были бы выявлены еще на этапе компиляции программы.

Variant может содержать данные любого типа, за исключением:

· структурных типов;

· указателей;

· Int64 (начиная с Delphi 6 – может).

В Delphi 6.0 вариант может включать такие типы (приведенные константы описаны в модуле System):

const

varEmpty = $0000;

varNull = $0001;

varSmallint = $0002;

varInteger = $0003;

varSingle = $0004;

varDouble = $0005;

varCurrency = $0006;

varDate = $0007;

varOleStr = $0008;

varDispatch = $0009;

varError = $000A;

varBoolean = $000B;

varVariant = $000C;

varUnknown = $000D;

varShortInt = $0010;

varByte = $0011;

varWord = $0012;

varLongWord = $0013;

varInt64 = $0014;

varStrArg = $0048;

varString = $0100;

varAny = $0101;

varTypeMask = $0FFF;

varArray = $2000;

varByRef = $4000;

Этот тип может содержать COM и CORBA объекты, чьи методы и свойства могут быть доступны посредством этого типа.

Также тип Variant может содержать динамические массивы и специфический вид статических массивов, называемых вариантными массивами (variant array).

Variant можно смешивать (в выражениях и операторах) с другими вариантами, числовыми, строковыми и булевскими данными. При этом компилятор автоматически выполняет преобразование типа.

Варианты, содержащие строки, не могут, однако, индексироваться (V[i} не допустимо).

Вариант занимает 16 байт памяти и включает код типа и значение или указатель на данные того типа, на который указывает код типа.

На этапе создания вариант инициализируется специальным значением Unassigned. Другое специальное значение – Null – указывает на неизвестные или отсутствующие данные (unknown or missing data).

Стандартная функция VarType возвращает код типа, представленного в варианте. Каждый код типа представлен своей (16-битовой) константой. Константа varTypeMask=$0FFF предназначена для извлечения кода, возвращаемого VarType. Например, выражение

(VarType(V) and varTypeMask) = varDouble

будет иметь значение true, если V содержит данное типа Double или массив Double. Маска varTypeMask просто скрывает 13-й бит (строго говоря, четыре старших бита), который указывает на массив.

В модуле System определен также тип-запись TVarData, с помощью которого можно получить доступ к внутреннему представлению данных в типе Variant.

В Delphi 6.0 имеется модуль Variants, содержащий ряд подпрограмм для работы с данными типа Variant.

Преобразования типа Variant.

Как было сказано выше, типы integer, real, string, character и Boolean (за исключением Int64) являются совместимыми по присваиванию с типом Variant. Тип выражения может быть явно приведен к типу Variant. Для изменения внутреннего представления варианта может быть использована подпрограмма
VarAsType:

Function VarAsType(const V: Variant; VarType: TVarType): Variant;

Следующий код иллюстрирует использование вариантов и некоторые автоматические преобразования типов при смешивании вариантов с другими типами.

var

V1, V2, V3, V4, V5: Variant;

I: Integer;

D: Double;

S: string;

begin

V1 := 1; { integer value }

V2 := 1234.5678; { real value }

V3 := 'Hello world!'; { string value }

V4 := '1000'; { string value }

V5 := V1 + V2 + V4; { real value 2235.5678}

I := V1; { I = 1 (integer value) }

D := V2; { D = 1234.5678 (real value) }

S := V3; { S = 'Hello world!' (string value) }

I := V4; { I = 1000 (integer value) }

S := V5; { S = '2235.5678' (string value) }

end;

Компилятор выполняет преобразования типов по правилам, приведенным в следующей таблице.

Table 5.7 Variant type conversion rules

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

Специальные правила преобразования применяются к типу TDateTime (вещественный тип double).

Когда тип TDateTime преобразуется к любому другому типу, он трактуется просто как вещественный. Когда какой-либо числовой или булевский тип преобразуется к типу TDateTime, он сначала приводится к типу double, а затем читается так же, как тип TDateTime.

Использование Variant в выражениях.

К типу Variant можно применять все операции, за исключением ^, is и in. Операции над операндами типа Variant возвращают и значение типа Variant. Они возвращают Null, если такое значение имеет один или оба операнда. Если хотя бы один операнд имеет значение Unassigned, возникает ошибка.

Если один из операндов (для бинарных операций) является Variant, второй преобразуется к типу Variant.

В основном при выполнении операций над вариантами действуют те же правила, что и для "обычных" операндов. Например, если V1 и V2 являются вариантами, один из которых содержит вещественное значение, а другой – целочисленное, результат будет вещественным.

Вариантные массивы.

Можно создавать и обрабатывать массивы вариантов, но можно также создать и вариантный массив. Вариантные массивы не описываются, а создаются с помощью стандартных функций VarArrayCreate и VarArrayOf. Например,

var V: Variant;

. . .

V := VarArrayCreate([ - 1, 9], varInteger);

Теперь переменная V может быть индексирована, однако ее нельзя передавать подпрограмме как параметр-переменную. Вариантные массивы всегда индексируются целочисленным индексом.

Функция VarArrayOf создает и заполняет вариантный массив. Значения элементов массива передаются функции в качестве параметров, например

V := VarArrayOf([1, 10, 100, 1000]);

После выполнения этого оператора V[1] = 10. Вариантные массивы могут быть многомерными, чего можно добиться таким образом:

V[i] := VarArrayOf([1, 10, 100, 1000]);

Теперь V – двухмерный массив.

В модуле System определен также ряд других подпрограмм, которые предназначены для выполнения различных действий над вариантными массивами (получение границ индексов, изменение числа элементов массива и т.д.).

Пример из Help Delphi 6.0:

var A: Variant;

begin

A := VarArrayCreate([0, 4], varVariant);

A[0] := 1;

A[1] := 1234.5678;

A[2] := 'Hello world';

A[3] := True;

A[4] := VarArrayOf([1, 10, 100, 1000]);

WriteLn(A[2]); { Hello world }

WriteLn(A[4][2]); { 100 }

end;

Тип OleVariant представляет собой такой вариант, который содержит только COM-совместимые типы. Когда Variant присваивается OleVariant, несовместимые типы преобразуются в совместимые аналоги.





<< Предыдущая статья
«13. Процедурные типы»
Следующая статья >>
15. Объявления типов