One of the most important features of the custom variant type for you to implement is typecasting. The flexibility of variants arises, in part, from their implicit typecasts.
There are two methods for you to implement that enable the custom Variant type to perform typecasts: Cast, which converts another variant type to your custom variant, and CastTo, which converts your custom Variant type to another type of Variant.
When implementing either of these methods, it is relatively easy to perform the logical conversions from the built-in variant types. You must consider, however, the possibility that the variant to or from which you are casting may be another custom Variant type. To handle this situation, you can try casting to one of the built-in Variant types as an intermediate step.
For example, the following
Cast method, from the
TComplexVariantType class uses the type Double as an intermediate type:
procedure TComplexVariantType.Cast(var Dest: TVarData; const Source: TVarData); var LSource, LTemp: TVarData; begin VarDataInit(LSource); try VarDataCopyNoInd(LSource, Source); if VarDataIsStr(LSource) then TComplexVarData(Dest).VComplex := TComplexData.Create(VarDataToStr(LSource)) else begin VarDataInit(LTemp); try VarDataCastTo(LTemp, LSource, varDouble); TComplexVarData(Dest).VComplex := TComplexData.Create(LTemp.VDouble, 0); finally VarDataClear(LTemp); end; end; Dest.VType := VarType; finally VarDataClear(LSource); end; end;
In addition to the use of Double as an intermediate Variant type, there are a few things to note in this implementation:
- The last step of this method sets the
VTypemember of the returned
TVarDatarecord. This member gives the Variant type code. It is set to the VarType property of
TComplexVariantType, which is the Variant type code assigned to the custom variant.
- The custom variant's data (
Dest) is typecast from
TVarDatato the record type that is actually used to store its data (
TComplexVarData). This makes the data easier to work with.
- The method makes a local copy of the source variant rather than working directly with its data. This prevents side effects that may affect the source data.
When casting from a complex variant to another type, the
CastTo method also uses an intermediate type of Double (for any destination type other than a string).
procedure TComplexVariantType.CastTo(var Dest: TVarData; const Source: TVarData; const AVarType: TVarType); var LTemp: TVarData; begin if Source.VType = VarType then case AVarType of varOleStr: VarDataFromOleStr(Dest, TComplexVarData(Source).VComplex.AsString); varString: VarDataFromStr(Dest, TComplexVarData(Source).VComplex.AsString); else VarDataInit(LTemp); try LTemp.VType := varDouble; LTemp.VDouble := TComplexVarData(LTemp).VComplex.Real; VarDataCastTo(Dest, LTemp, AVarType); finally VarDataClear(LTemp); end; end else RaiseCastError; end;
Note that the
CastTo method includes a case where the source variant data does not have a type code that matches the
VarType property. This case only occurs for empty (unassigned) source variants.