5

Argsフォーマット引数をFormat関数に渡したいと思います。その例をいくつか見つけましたが、 TVarRecメンバーに文字列定数を割り当てる方法がわかりません。次のコードは、 でのコンパイルに失敗します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;

文字列 (または AnsiString) 定数を TVarRec メンバーに設定する方法を教えてもらえますか? Delphi 2009 を使用しています。

どうもありがとう

4

3 に答える 3

10

これは 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;
于 2011-05-19T13:15:24.677 に答える
5

ちょうど私の2セント。TOndrejの答えは正しいですが、私はいくつかの点を強調したかっただけです。そして、コメントはそれを行うのに良い場所ではありません。

AnsiString常に参照する必要があることに注意してくださいTVarRec

たとえば、の配列を設定する関数を作成する場合は、関数内に作成された変数TVarRecの一時的なコピーを作成したことを確認する必要があります。この変数は、配列が使用されるAnsiStringまですべて保持されます。TVarRecそうしないと、ランダムアクセス違反が発生する可能性があります(毎回ではなく、MMがansistringメモリを再割り当てした場合のみ)。

たとえば、次のコードは正しくありません。

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;

プロシージャが終了すると、一時変数と一時変数が解放され、解放AnsiStringされたメモリをポイントするためです。UnicodeStringResults[].VString

クラスまたはレコードを一時的なプライベート文字列とともに使用すると、トリックが実行される場合があります。

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;

もちろん、プログラムには既存のクラスがある場合があります。この場合、メソッドといくつかのプライベート一時文字列を使用することをお勧めします。メソッドをマルチスレッドセーフ(つまり、再入可能)にするには、一時的な文字列をパラメーターとして指定する必要があります。

このトリックを使用して、クラスにコンテンツをTVarData含む動的配列を有効にします。AnsiString実際、TVarDataどちら TVarRecも文字列へのそのような参照されていないポインタを使用しているため、混乱する可能性があります。

pointer(S)同様のステートメントに関連する問題は追跡が難しい場合があることに注意してください。

于 2011-05-19T14:46:03.507 に答える