Управление нулевыми значениями в вариантах с использованием Delphi - PullRequest
18 голосов
/ 09 мая 2011

Я работаю с COM-компонентом, который предоставляет множество Variant свойств, но иногда эти значения равны нулю.Когда я пытаюсь преобразовать эти значения в строку (или другой тип Delphi), приложение вызывает исключение, подобное этому:

Не удалось преобразовать вариант типа (Null) в тип (String)

Но если я использую .net для вызова тех же свойств и значения равны NULL, исключений не возникает, а значения NULL обрабатываются как пустые строки.

У меня есть вопрос, как справитьсяэти нулевые значения из Delphi, исключающие эти исключения?

Заранее спасибо.

Ответы [ 5 ]

28 голосов
/ 09 мая 2011

Попробуйте установить NullStrictConvert в значение False.

Поскольку это глобальная переменная, я использую ее следующим образом, чтобы минимизировать побочные эффекты:

var
  OldNullStrictConvert: Boolean;
begin
  OldNullStrictConvert := NullStrictConvert;
  NullStrictConvert := False;
  try
    // code containing conversions
  finally
    NullStrictConvert := OldNullStrictConvert;
  end;
end;

(На самом деле у меня естьиз этого сделал интерфейс хранителя.)

Примечание: там, где это возможно, я предпочитаю код типа Уоррен .

18 голосов
/ 10 мая 2011

Принятый ответ изменяет глобальную настройку и может привести к непреднамеренным побочным эффектам при работе другого кода, который работал до его изменения.

Во-первых, вы могли бы просто использовать VarToStrDef, во-вторых, если вы должны предоставить какую-то другую функциональность, кроме этого, я бы заставил мой код вызвать мою собственную функцию MyVarToStr и сделать это так:

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;

Поскольку кажется, что VarToStrDef должно быть достаточно, я лишь хочу продемонстрировать, что лучше написать свой код и вызвать собственный код, чем пытаться "глобально изменить" поведение по умолчанию кода библиотеки VCL / RTL.

14 голосов
/ 10 мая 2011

Это задокументированное поведение функции VarToStr. Нет необходимости изобретать велосипед.

Нулевой вариант - это отдельный тип (да, это тип, а не просто значение), который обозначает либо отсутствующие, либо неизвестные данные. Таким образом, строго говоря, обычный вариант динамическая типизация не должна происходить со значениями Null ( показано и отражено в значениях по умолчанию RTL).

Дано:

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;

ПРИМЕЧАНИЕ: Наиболее поздние версии Delphi.NET демонстрируют точно такое же поведение на пустых вариантах, поэтому замечание OP о .NET сомнительно.

5 голосов
/ 08 мая 2012

VarToStr() и VarToStrDef() являются правильным и правильным способом преобразования Null Variant в String, поскольку они явно проверяют наличие нулевых значений внутри.

4 голосов
/ 09 февраля 2012

.. из кода user422039 используйте VarToStr, иначе S: = V передает неявное преобразование, которое может привести к разным результатам в другой среде:

S := VarToStr(V);
or
S := VarToStrDef(V, yourdefaultvalue);
...