2012-03-12 8 views
8

Le varianti sono sempre divertenti, eh?Come capire se una variante di Delphi è una stringa vuota?

Sto lavorando a un'applicazione legacy che era l'ultima in D2007 per migrarlo a Delphi XE.

Le varianti sono cambiate un po 'nel frattempo.

Questa riga di codice:

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

restituito Vero e usciti in D2007, ma non lo fa in Delphi XE.

ho cambiato a questo:

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

non sono convinto questo è il modo "migliore" per andare. L'unità Variants non ha una chiamata specifica per farlo, e certamente ricordo che questo è un problema per la gente in passato. Tuttavia, una ricerca non ha rivelato alcuna funzione di libreria o altro modo accettato.

Esiste un modo "corretto" o migliore?

+0

Per inciso 'v = ''' è vero, se lo assegno esplicitamente a 'v: = '';' - La mia ipotesi è che ci sia più di un sottotipo di stringa variante, forse B_STR e qualcos'altro, e quindi il confronto degli elementi fallisce, anche se il contenuto è lo stesso. –

+0

Wont 'se VarToStr (Value) = ''' solo esegue il lavoro? – kobik

+1

@kobik Questo fallisce, ad esempio, quando "Valore" è uguale a "Nullo". –

risposta

3

Aggiornato: per evitare specifici String eccezioni:

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

Update3: Se si desidera migliorare le prestazioni e meno spreco di memoria delle stringhe mucchio provare questo. Immagina che le stringhe siano lunghe 64 KB. Il codice sopra fa un VarToStr e alloca forse 64K di spazio heap UnicodeString per contenere i dati, solo così possiamo solo cercare il terminatore nul alla fine della stringa per BSTR e per i puntatori nil per altri tipi.

Il codice sotto è un po 'strano in quanto non si raggiunge comunemente la rappresentazione interna delle varianti, ma David ha indicato gli errori e io l'ho ri-testato e sembra funzionare, anche se non viene espressa alcuna garanzia o implicito. Un test unitario per questo cucciolo sarebbe buono. In qualche data futura, se le divisioni di Delphi RTL decidessero di rinominare la rappresentazione interna dei campi della struttura Variant, sarebbe necessario modificare il codice seguente.

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 sta cercando di evitare le eccezioni che si presentano quando la variante non può essere forzata ad una stringa. Ecco perché ha bisogno del primo controllo e valutazione del cortocircuito. –

+1

Sto faticando a vedere cosa porta tutta la complessità extra qui. Inoltre, fornirò una risposta errata per un OleStr vuoto perché sono rappresentati come un singolo null wchar_t. O ho sbagliato? Cosa c'è di male nel confronto con ""? –

+0

Non funziona sempre a meno che non lo si appiattisca su UnicodeString con VartoString. Per fare un'analogia, è come contare tutti i penny uno per uno per essere sicuri di averne QUALSIASI. È inutile e dispendioso. –

12

VarIsStr è un modo perfettamente plausibile per farlo. Questo viene implementato come:

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; 

Il cambiamento che state vedendo è, ovviamente, in realtà a causa della Unicode cambia in D2009, piuttosto che modifiche alle varianti. La stringa sarà varUString, alias UnicodeString. Naturalmente, VarIsStr riprende anche AnsiString/varString e WideString/BSTR/varOleStr.

Se si vuole una conversione veramente fedele del codice Delphi 2007, allora si avrebbe scritto:

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

Esattamente quello che devi fare, solo tu puoi sapere, ma la cosa fondamentale è che si deve rendere conto per il nuovo arrivato varUString.

0

Le varianti possono essere un numero o una stringa.

Potrebbe esserci un problema quando Variant (Number) ha un valore negativo (-15).

anche la vostra linea

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

devo sempre mettere ()

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

Hai frainteso la domanda. Numeri negativi non rilevanti qui. Anche il tuo secondo punto() è semplicemente sbagliato. –

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

fa il trucco per me.

+1

Tutti i casi saranno predefiniti quando 'value' non è una stringa su true. Quella logica non corrisponde alla domanda. –

Problemi correlati