2012-03-12 36 views
8

バリアントはいつも楽しいですね。Delphiのバリアントが空の文字列かどうかを確認するには?

私はDelphi XEに移行するために、D2007の最後のレガシーアプリケーションを開発中です。

暫定的に変種がかなり変更されました。

このコード行:

if (VarType(Value) = varString) and (Value = '') then 
    Exit; 

はtrueを返しとD2007に終了したが、デルファイXEではありません。

私はこれまで、それを変更した:

if VarIsStr(Value) and (VarToStr(Value) = '') then 
    Exit; 

私は、これは行くための「最良」の方法です確信していません。 Variantsユニットには、これを行うための特定の呼び出しがありません。これは過去の人々の問題であることは確かです。しかし、検索ではライブラリー機能やその他の承認された方法は明らかにされていません。

"正しい"またはより良い方法はありますか?

+0

なお、 'v = '''は 'v:= ''に明示的に代入すると真です; - 私の推測では、複数のバリアント文字列のサブタイプ、おそらくB_STRなどがあるので、たとえコンテンツが同じであっても、要素の比較は失敗します。 –

+0

'もしVarToStr(Value)= '''だけが仕事をしたら? – kobik

+1

@kobikこれは、たとえば、 'Value'が' Null'に等しいときに失敗します。 –

答えて

3

更新日:文字列固有の例外を避けるために:

if VarIsStr(Value) and (Length(VarToStr(v))=0) then ... 

Update3とを:あなたはより良いパフォーマンスとより少ない文字列のヒープメモリの浪費をしたい場合は、これを試してみてください。 文字列の長さが64Kであるとします。上のコードはVarToStrを実行し、おそらく64 KBのUnicodeStringヒープ領域を確保してデータを保持しています。ちょうどBSTRの文字列の終わりにnulターミネータを、他の型のnil-pointerを探すことができます。

以下のコードは一般的にバリアントの内部表現には届かないという点で少し奇妙ですが、Davidはバグを指摘し、再検証して動作しますが、保証は表示されませんまたは暗示される。この子犬の単体テストは良いでしょう。将来、Delphi RTLの神がVariant構造体フィールドの内部表現の名前を変更することに決めた場合、以下のコードを変更する必要があります。

function VarStrEmpty(v:Variant):Boolean; 
var 
    data:PVarData; 
begin 
    data := FindVarData(V); 
    case data^.VType of 
    varOleStr: 
      result := (data^.VOleStr^=#0); 
    varString: 
      result := (data^.VString=nil); 
    varUString: 
      result := (data^.VUString=nil); 
    else 
     result := false; 
    end; 
end; 
+2

Nickは、バリアントが文字列に強制変換できないときに発生する例外を回避しようとしています。だから彼は最初のチェックと短絡の評価が必要です。 –

+1

私は余分な複雑さが何をもたらしているかを見るのに苦労しています。また、空のOleStrに対して誤った答えを与えるでしょう。なぜなら、それらは単一のnull wchar_tとして表されるからです。それとも間違っていたのですか? ''と比較して何が悪いですか? –

+0

VartoStringを使ってUnicodeStringにフラット化しない限り、常に機能するとは限りません。アナロジーを作成するには、すべてのペニーを1つ1つカウントしてANYを確実に持つようなものです。それは不必要で無駄です。 –

12

VarIsStrは完全に考えられる方法です。あなたが見ているの変化が本当に原因UnicodeのD2009の変化ではなく、亜種への変更に、当然のことながら、ある

function VarTypeIsStr(const AVarType: TVarType): Boolean; 
begin 
    Result := (AVarType = varOleStr) or (AVarType = varString) 
    or (AVarType = varUString); 
end; 

function VarIsStr(const V: Variant): Boolean; 
begin 
    Result := VarTypeIsStr(FindVarData(V)^.VType); 
end; 

:これは、次のように実装されています。文字列はvarUString、別名UnicodeStringとなります。もちろん、VarIsStrAnsiString/varStringWideString/BSTR/varOleStrを選択します。

あなたのDelphi 2007のコードの真の忠実な変換をしたいなら、あなたが書くでしょう:

if (VarType(Value) = varUString) and (Value = '') then 
    Exit; 

正確にあなたが何をする必要があるか、あなただけが知っていることができますが、重要なのは、あなたが考慮しなければならないということです新しく到着したのはvarUStringです。

0

バリアントには、数値または文字列を使用できます。

バリアント(数値)が負の値(-15)のときに問題が発生する可能性があります。

また、あなたのライン

(VarType(Value) = varString) and (Value = '') 

私はいつも()

((VarType(Value) = varString) and (Value = '')) 
+1

あなたはその質問を誤解しました。負の数はここでは関係ありません。また、about()についての2番目の点は単に間違っています。 –

-1
if VarToStrDef(value, '') = '' then 

が私のためにトリックをい配置する必要があります。

+1

'value'が真である文字列でない場合、すべての場合をデフォルトにします。その論理は質問と一致しません。 –

関連する問題