Buscar

O tipo de dado variant - part i

nome

Héracles Alencar

Colunista ainda sem descrição. Caro colunista, por favor envie-nos sua descrição.

O Tipo de Dados Variant

Por: Héracles Alencar
        heracles_alencar@hotmail.com

Um pouco de história

No princípio era o Delphi 1 e o Windows 3.1 de 16 bits. Depois veio o Delphi 2 e o Windows de 32 bits. E o Delphi se fez forte e perdurou até os presentes dias. (Gênesis Delphi - Cap. 1, Vers. 1).

O parágrafo acima apenas foi criado pelo autor para descontrair os leitores e a ele mesmo, em uma forma de ajudar a se ter uma leitura prazerosa e um desenvolvimento alegre. Porém, há uma ligação sobre o assunto abordado neste artigo.

Os Tipos de Dados Variant foram introduzidos no Delphi a partir de sua versão 2.0, lançada em 1996 para a plataforma Windows 95 e NT. Foi a primeira versão Delphi para plataforma 32 bits e espero, sinceramente, que ele passe para o 64, 128 e etc...

Os Tipos Variant foram criados, inicial e basicamente, para dar suporte a OLE Automation que utiliza com abrangência o tipo Variant, todavia, veio se mostrando bastante útil em outras áreas do Delphi. Até o que o autor conhece, o Object Pascal é a única linguagem compilada que integra completamente variantes como um tipo de dado dinâmico em Runtime e como um tipo estático em tempo de compilação no qual o compilador sempre sabe que se trata de uma Variant, conforme relatam os autores Steve Pacheco e Xavier Teixeira em seu Guia do Desenvolvedor Delphi.

Indo mais a frente, o Delphi 3 introduziu outro Tipo de Dados chamado OleVariant, que encapsula todos as características do Variant, exceto por só poder armazenar tipos compatíveis com Automation.

Neste artigo nos concentraremos apenas ao Tipo Variant do Delphi, apresentando suas principais funções e formas de se trabalhar.

Tipos Variant são Permanentemente Gerenciados

A primeira coisa que se deve saber é que os Tipos Variant são permanentemente gerenciados pelo Delphi. Isso quer dizer que, são usados alocando áreas de memória e recursos adicionais e após desalocados automaticamente, o que diminui em muito possíveis erros do desenvolvedor no esquecimento de alocações de buffers na memória. Os Tipos Permanentemente Gerenciados pelo Delphi, as vezes chamados de Tipos Apanhados do Lixo, submetem-se a regras do compilador quando o desenvolvedor os implementa. Como as variáveis globais do Delphi são inicializadas com valores zero, as regras usadas são simples de se entender. O Delphi apenas limpa os recursos para essas variáveis, com um código de finalização para a aplicação, se elas, realmente, tiverem sido usadas. Para as variáveis locais o processo se dá de forma ligeiramente diferente. O compilador usa um Tratamento Estruturado de Exceções para assegurar que as variáveis são inicializadas com seus respectivos valores zero e após seu uso limpa-as. Considere o seguinte exemplo:

Exemplo 1 – Exceção para um Tipo Permanentemente Gerenciado

Procedure TForm1.Button1Click(Sender: TObject);

Var

 Str: String;

Begin

 Str := Table1[‘Nome’];

 ShowMessage(Str);

End;

Isso é muito normal para o desenvolvedor, atribuir um valor a uma variável string e logo depois mostrá-la ao usuário da aplicação. Nos bastidores do Show Delphi o código é um pouco diferente:

Procedure TForm1.Button1Click(Sender: TObject);

Var

 Str: String;

Begin

 Str := ‘’; //Assegurando inicialização em zero

 Try

  Str := Table1[‘Nome’];

  ShowMessage(Str);

 Finally

  //Delphi Limpa os recursos à variável

 End;

End;

Para o Tipo Variant, a mesma regra se aplica, exceto quando a variável será usada novamente por um outro tipo de dado onde a inicialização será feita novamente e a variável será desalocada de recursos antes do bloco Try.

O Tipo Variant

Um dos principais usos do Tipo Variant se dá quando o desenvolvedor não sabe que dados irão ser inseridos em RunTime. Um Variant mudam os tipos dinamicamente. O código a seguir será executado corretamente:

Exemplo 2 – Uso do Tipo Variant

procedure TForm1.Button1Click(Sender: TObject);

Var

 V: Variant;

begin

 V := 'Eu sou um Tipo de Dado String';

  ShowMessage(V);

 V := 13;

  ShowMessage(V);

 V := True;

  ShowMessage(V);

 V := 13.13;

  ShowMessage(V);

end;

Tipos Variant podem suportar todos os tipos de dados simples como Inteiros, Ponto Flutuantes, Booleanos, Strings, Data e Hora, Moeda e Objetos OLE Automation. Variant´s não podem fazer referência a Objetos do Object Pascal nem a Ponteiros. Variant´s também podem fazer referência a um Array Não-Homogêneo cujos elementos podem fazer referência a qualquer um dos dados citados acima, inclusive a Arrays de Variant´s.

O Registro que define o Tipo Variant é implementado na unidade System da seguinte forma:

TVarType = Word;

PVarData = ^TVarData;

{$EXTERNALSYM PVarData}

TVarData = packed record

 case Integer of

  0: (VType: TVarType;

  case Integer of

   0: (Reserved1: Word;

   case Integer of

    0: (Reserved2, Reserved3: Word;

    case Integer of

     varSmallInt: (VSmallInt: SmallInt);

     varInteger: (VInteger: Integer);

     varSingle: (VSingle: Single);

     varDouble: (VDouble: Double);

     varCurrency: (VCurrency: Currency);

     varDate: (VDate: TDateTime);

     varOleStr: (VOleStr: PWideChar);

     varDispatch: (VDispatch: Pointer);

     varError: (VError: HRESULT);

     varBoolean: (VBoolean: WordBool);

     varUnknown: (VUnknown: Pointer);

     varShortInt: (VShortInt: ShortInt);

     varByte: (VByte: Byte);

     varWord: (VWord: Word);

     varLongWord: (VLongWord: LongWord);

     varInt64: (VInt64: Int64);

     varString: (VString: Pointer);

     varAny: (VAny: Pointer);

     varArray: (VArray: PVarArray);

     varByRef: (VPointer: Pointer);

    );

    1: (VLongs: array[0..2] of LongInt);

   );

   2: (VWords: array [0..6] of Word);

   3: (VBytes: array [0..13] of Byte);

  );

 1: (RawData: array [0..3] of LongInt);

end;

{$EXTERNALSYM TVarData}

Esta estrutura permite que vários campos de dados se sobreponham na mesma área de memória, o que não é a implementação do Tipo Variant e o leitor deve entender isso.

Notem que esta estrutura contem um campo chamado VType, que é justamente o campo que o desenvolvedor faz referência quando implementa uma variável Variant. Se VType contiver um valor varInteger, será executado o campo VInteger. Se bem entendido isso pelos leitores, deverá saber ele, que o campo VType pode ser acessado diretamente como é mostrado abaixo:

Exemplo 3 – Acesso direto a VType

Var

 P: TVarData;

begin

 P.VType := varInteger;

 P.VInteger := 13;

end;

Embora isso possa ser feito, é uma prática muito perigosa podendo ocasionar perda de memória se esquecidos de se referenciar os tipos de dados que VType receberá, deixemos isto para o Delphi.

Typecast de Variant´s

O Delphi permite que Typecasts de Tipos Variant. Para o leitor não familiarizado com o termo, Typecast é um conversão de tipos como: Str := IntToStr(I);.

Exemplo 4 – Typecast de Variant´s

procedure TForm1.Button1Click(Sender: TObject);

Var

 V: Variant;

 S: String;

 I: Integer;

 B: Boolean;

 D: Double;

begin

 V := 1.6;

 S := String(V); //conterá '1.6'

 I := Integer(V); //conterá o valor mais próximo, 2

 B := Boolean(V); //conterá False se V = 0; senão True

 D := Double(V); //conterá 1.6

 Variant(S); //TypeCast para Variant

end;

O exemplo acima ilustra como se executar um Typecast de Variant´s, e apenas isso. O código acima pode ser compilado e executado perfeitamente sem a necessidade de uma conversão, exceto pela última linha.

É importante salientar que, ao saber que tipo de dado que será usado em RunTime, não há a necessidade de se usar o Tipo Variant, de modo que, é aconselhável que se faça o quanto antes a conversão.

Expressões usando Variant´s

Você pode usar os seguintes operadores em expressões usando Variant´s: +, -, *, /, div, mod, shl, shr, and, or, xor, not, :=, <>, <, >, <= e >=.

Se duas Variant´s, V1 e V2, são strings o resultado de uma expressão com o operador + será uma concatenação. Se são inteiros, o resultado será uma soma. E se as variáveis contiverem valores diferentes? O Delphi usa regras de promoção para essa operação. Por exemplo, se V1 contiver uma string ‘10’ e V2 contiver um inteiro 3, V1 será convertido em inteiro e o resultado com o operador + será a soma de V1 e V2. Considerem o seguinte:

Exemplo 5 – Expressão Variant

procedure TForm1.Button1Click(Sender: TObject);

Var

 V1, V2, V3: Variant;

begin

 V1 := '1';

 V2 := '1';

 V3 := 2;

 V1 := V1 + V2 + V3;

  ShowMessage(V1);

end;

Aparentemente, este código gerará o resultado 4, entretanto, o leitor deve considerar que o Delphi executará esta soma da esquerda para a direita e com dois operandos de cada vez, isso quer dizer que a linha da soma ficaria: V1 := (V1 + V2) + V3;, resultando no valor 13. Se o Delphi não conseguir entender a expressão, uma exceção do tipo "conversão de tipo Variant inválida" é criada. Muitas vezes é melhor que se faça um Typecast antes de pensar em se implementar um código destes.

Os valores VarEmpty e VarNull de VType

Os valores VarEmpty e VarNull tem diferenças que devem ser entendidas pelo leitor deste. VarEmpty é o valor inicial de um Tipo Variant que quer dizer que a variável não tem valor algum. VarNull é um valor zero, nulo. Se você deseja atribuir estes valores a VType, use Unassigned para VarEmpty e Null para VarNull, lembrando que o uso incorreto e sem consciência dos mesmos provocará um erro. Voltando ao exemplo de como o Delphi gerencia as variáveis permanentemente, as variáveis Variant são inicializadas em Unassigned.

O autor desenvolveu um pequeno exemplo de como se fazer TypeCasts de Tipo Variant, bem como, trabalhar com expressões Variant. Logo estará no site para Download. Aguardem!

Continua...

A parte II deste artigo aborda algumas das mais importantes técnicas para se implementar Arrays de Tipo Variant, mostrando suas principais funções de manipulação. Até o momento, só tenho a agradecer a todos por essa instrutiva leitura.

Publicidade

Vote no artigo




Quantidade de votos: 0 votos
Aceitação: 0%


Detalhes do artigo

Categoria: Object pascal
Adicionado dia: 28/02/05
Por: Héracles Alencar
Visualizado: 36163 vezes

Planeta Delphi - Tudo sobre programação Delphi Planeta Delphi - www.planetadelphi.com.br - Todos os direitos reservados | Copyright 2001-2009