Pergunta

Quero passar os argumentos de formatação Args no Formatar função.Encontrei alguns exemplos disso, mas não consigo descobrir como atribuir uma constante de string no TVarRec membro.O código a seguir falha na compilação com E2089 Invalid typecast.

procedure TForm1.Button1Click(Sender: TObject);
var Arguments: array of TVarRec;
begin
  SetLength(Arguments, 2);

  Arguments[0].VInteger := 111;
  Arguments[1].VAnsiString :=  PAnsiString('Text'); // I want to set this member

  ShowMessage(Format('Decimal: %d, String: %s', Arguments));
end;

Alguém pode me sugerir como definir a constante string (ou AnsiString) para o membro TVarRec?Estou usando o Delphi 2009.

Muito obrigado

Foi útil?

Solução

Isso parece funcionar no XE:

var
  Args: array[0..1] of TVarRec;
  S: AnsiString;
  U: UnicodeString;
begin
  S := 'Hello';
  U := 'world';
  Args[0].VType := vtAnsiString;
  Args[0].VAnsiString := Pointer(S);
  Args[1].VType := vtUnicodeString;
  Args[1].VUnicodeString := Pointer(U);

  Writeln(Format('%s, %s!', Args));
end;

Outras dicas

Apenas meus dois centavos.A resposta de TOndrej está correta, mas queria apenas enfatizar alguns pontos.E os comentários não são um bom lugar para fazer isso.

Por favor, esteja ciente de que o AnsiString deve ser referenciado durante todo o tempo TVarRec será usado.

Por exemplo, se você escrever uma função definindo um array de TVarRec, você deve garantir que fez uma cópia temporária do AnsiString criado dentro da função para uma variável que permanecerá até todo o tempo TVarRec matriz é usada.Caso contrário você poderá ter alguma violação de acesso aleatório (não sempre, mas apenas quando o MM reatribuir o ansistring memória).

Por exemplo, o código a seguir é incorreta:

type
  TVarRec2 = array[0..1] of TVarRec;

procedure SetVarRec(a,b: integer; var Result: TVarRec2);
begin
  Result[0].VType := vtAnsiString;
  Result[0].VString := pointer(AnsiString(IntToStr(a)));
  Result[1].VType := vtUnicodeString;
  Result[1].VString := pointer(UnicodeString(IntToStr(b)));
end;

Porque o AnsiString e UnicodeString variáveis ​​temporárias serão liberadas quando o procedimento terminar, e Results[].VString ainda apontará para a memória liberada ...

Usar uma classe ou um registro com alguma string privada temporária pode resolver o problema:

type
  TMyVar2 = record
  private
    tmpA: AnsiString;
    tmpB: UnicodeString; 
  public
    VarRec: TVarRec2;
    procedure SetVarRec(a,b: integer);
  end;

procedure TMyVar2.SetVarRec(a,b: integer);
begin
  VarRec[0].VType := vtAnsiString;
  tmpA := AnsiString(IntToStr(a));
  VarRec[0].VString := pointer(tmpA);
  VarRec[1].VType := vtUnicodeString;
  tmpB := UnicodeString(IntToStr(b));
  VarRec[1].VString := pointer(tmpB);
end;

Claro, no seu programa você pode já ter uma turma existente.Nesse caso, é melhor usar um método e algumas strings temporárias privadas.Para que o método seja seguro para vários threads (ou seja,reentrante) você deve fornecer as strings temporárias como parâmetros ...

Eu uso esse truque para validar uma matriz dinâmica de TVarData contendo alguns AnsiString conteúdo de uma aula.Na verdade, TVarData e TVarRec ambos usam ponteiros não referenciados para strings, o que pode ser confuso.

Esteja ciente de que questões envolvendo pointer(S) declarações semelhantes podem ser difíceis de rastrear.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top