Reputation: 16472
I'm working with a COM component which exposes a lot of Variant
properties, but sometimes these values are null. When I try to convert these values to string (or another Delphi type) the application raises an exception like this:
Could not convert variant of type (Null) into type (String)
But if I use .net to call the same properties and the values are null, no exceptions are raised and the null values are treated as empty strings.
My question there is a way to handle these null values from Delphi avoiding these exceptions?
Thanks in advance.
Upvotes: 18
Views: 42022
Reputation: 595971
VarToStr()
and VarToStrDef()
are the correct and proper way to convert a Null Variant
to a String
, as they explicitially check for Null values internally.
Upvotes: 9
Reputation: 71
..from user422039 code use VarToStr otherwise S:=V relays on an implicit conversion which may create different result on different environment:
S := VarToStr(V);
or
S := VarToStrDef(V, yourdefaultvalue);
Upvotes: 4
Reputation: 68892
The accepted answer changes a global setting, and could have unintended side effects on the operation of other code that was working before you changed it.
First you could just use VarToStrDef
, secondly, if you must provide some functionality other than that, then I would have my code call my own function MyVarToStr, and do it like this:
resourcestring
SNilValue = '[nil]';
function VarIsAssigned(v:Variant):Boolean; inline;
begin
result := (v<>Variants.Null) and (not VarIsNull(V));
end;
function MyVarToStr( v:Variant):String;
begin
if VarIsAssigned(v) then
result := VarToStr(v)
else
result := SNilValue;
end;
Since it seems that VarToStrDef should be enough, I only mean to demonstrate that it's better to write your code and call your own code, than to try to "globally change" the default behaviour of VCL/RTL library code.
Upvotes: 21
Reputation: 1458
This is a documented behaviour of VarToStr
function. There is no need to reinvent a wheel.
Null variant is distinct type (yes, it is a type, not merely a value), which denotes either missing or unknown data. So, strictly speaking, regular variant dynamic-typing should not happen with Null
values (illustrated and reflected in RTL defaults).
var
V: Variant;
S: string;
S := VarToStr(V); { stongly-typed explicit conversion }
if not VarIsNull(V) then { program knows what it does, but reproduces RTL behaviour }
S := V
else
S := NullAsStringValue;
NullStrictConvert := False; { smelly, from now on Null variant loses its specifics }
S := V;
try
S := V;
except on Eaten: Exception do { stinky PHP-style, hiding error instead of fixing it }
S := NullAsStringValue;
end;
NOTE: Most late Delphi.NET exhibits exactly the same behaviour on Null variants, so OP's remark about .NET is questionable.
Upvotes: 14
Reputation: 14001
Try setting NullStrictConvert to False.
As it's a global variable I use it like follows to minimize side effects:
var
OldNullStrictConvert: Boolean;
begin
OldNullStrictConvert := NullStrictConvert;
NullStrictConvert := False;
try
// code containing conversions
finally
NullStrictConvert := OldNullStrictConvert;
end;
end;
(In reality I have made a guardian interface out of this.)
NB: Where it's feasible I prefer code like Warren's.
Upvotes: 30