2013-02-28 6 views
8
uses 
    SysUtils, Variants; 

var 
    VariantSingle: Variant; 
    VTSingle: TVarType; 
    SingleTest: Single; 
    VariantDouble: Variant; 
    DoubleTest: Double; 
    VTDouble: TVarType; 

begin 
    SingleTest := 1.234; 
    VariantSingle := SingleTest; 
    VTSingle := VarType(VariantSingle) and varTypeMask; 

    DoubleTest := 1.23456; 
    VariantDouble := DoubleTest; 
    VTDouble := VarType(VariantDouble) and varTypeMask; 

    WriteLn(Format('VarType: Single: %d, Double %d', [VTSingle, VTDouble])); 
end. 

Il seguente output:Perché assegnare una singola a una variante produce una variante varDouble?

VarType: Singolo: 5, doppio 5

Da System.pas

varSingle = $0004; { vt_r4   4 } 
varDouble = $0005; { vt_r8   5 } 

Quindi, mi aspetto VTSingle a be - non 5
Cosa mi manca?

risposta

5

Le librerie Delphi scelgono di implementare tutte le assegnazioni in virgola mobile alle varianti tramite una chiamata a _VarFromReal. E che la funzione è simile al seguente:

procedure _VarFromReal(var V: TVarData; const Value: Real); 
begin 
    if (V.VType and varDeepData) <> 0 then 
    VarClearDeep(V); 
    V.VType := varDouble; 
    V.VDouble := Value; 
end; 

Si noti che questo utilizza un tipo di varDouble. E include una conversione implicita in Real che è un alias per Double. Non sono sicuro del motivo per cui i progettisti hanno scelto quella particolare rotta, ma la conseguenza di questa scelta è il comportamento che osservate.

Un modo semplice per fare una variante varSingle è possibile utilizzare:

VariantSingle := VarAsType(SingleTest, varSingle); 

Anche se questo convertirà SingleTest a Double, e poi di nuovo a Single.

Per evitare che la conversione inutile, scrivere il proprio aiutante:

function VarFromSingle(const Value: Single): Variant; 
begin 
    VarClear(Result); 
    TVarData(Result).VSingle := Value; 
    TVarData(Result).VType := varSingle; 
end; 

che si può chiamare in questo modo:

VariantSingle := VarFromSingle(SingleTest); 

Quest'ultimo approccio è la soluzione giusta a mio parere.

+0

Hai tradotto la procedura '_VarFromReal' da asm a Pascal? Almeno in Delphi 2009, è implementato come procedura 'asm'. –

+0

@AndreasRejbrand Modern Delphis ha anche versioni Pascal a beneficio dei nuovi target non x86. Quindi ho usato la versione Pascal qui. –

Problemi correlati