Gestionando valores nulos en variantes usando Delphi
null delphi-xe (5)
..desde el código de user422039 use VarToStr de lo contrario S: = V retransmite en una conversión implícita que puede crear un resultado diferente en un entorno diferente:
S := VarToStr(V);
or
S := VarToStrDef(V, yourdefaultvalue);
Estoy trabajando con un componente COM que expone muchas propiedades Variant
, pero a veces estos valores son nulos. Cuando intento convertir estos valores en una cadena (u otro tipo de Delphi), la aplicación genera una excepción como esta:
No se pudo convertir la variante de tipo (nulo) en tipo (cadena)
Pero si uso .net para llamar a las mismas propiedades y los valores son nulos, no se generan excepciones y los valores nulos se tratan como cadenas vacías.
Mi pregunta: ¿hay una manera de manejar estos valores nulos de Delphi evitando estas excepciones?
Gracias por adelantado.
Este es un comportamiento documentado de la función VarToStr
. No hay necesidad de reinventar una rueda.
La variante nula es un tipo distinto (sí, es un tipo, no simplemente un valor), que denota datos faltantes o desconocidos . Por lo tanto, estrictamente hablando, la variante dinámica de tipificación regular no debería ocurrir con valores Null
( illustrated y reflejados en valores predeterminados de RTL).
dado:
var
V: Variant;
S: string;
mejor código
S := VarToStr(V); { stongly-typed explicit conversion }
código relativamente bueno
if not VarIsNull(V) then { program knows what it does, but reproduces RTL behaviour }
S := V
else
S := NullAsStringValue;
código malo
NullStrictConvert := False; { smelly, from now on Null variant loses its specifics }
S := V;
código aún peor
try
S := V;
except on Eaten: Exception do { stinky PHP-style, hiding error instead of fixing it }
S := NullAsStringValue;
end;
NOTA: La mayoría de Delphi.NET tardío exhibe exactamente el mismo comportamiento en las variantes Null, por lo que la observación de OP sobre .NET es cuestionable.
Intente establecer NullStrictConvert en False.
Como es una variable global, la uso de la siguiente manera para minimizar los efectos secundarios:
var
OldNullStrictConvert: Boolean;
begin
OldNullStrictConvert := NullStrictConvert;
NullStrictConvert := False;
try
// code containing conversions
finally
NullStrictConvert := OldNullStrictConvert;
end;
end;
(En realidad he hecho una interfaz de guardián de esto).
NB: Donde sea factible, prefiero código como el de Warren .
La respuesta aceptada cambia una configuración global y podría tener efectos secundarios no deseados en el funcionamiento de otro código que funcionaba antes de que lo cambiara.
Primero, podría usar VarToStrDef
; en segundo lugar, si debe proporcionar alguna otra funcionalidad que no sea esa, entonces mi código llamará a mi propia función MyVarToStr y lo hará así:
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;
Como parece que VarToStrDef debería ser suficiente, solo quiero demostrar que es mejor escribir su código y llamar a su propio código, que intentar "cambiar globalmente" el comportamiento predeterminado del código de biblioteca VCL / RTL.
VarToStr()
y VarToStrDef()
son la forma correcta y correcta de convertir una Variant
nula en una String
, ya que comprueban explícitamente los valores nulos internamente.