Почему происходит сбой Format, когда с Variant используется что-либо, кроме %s?

Я работаю с функцией SysUtils.Format и значениями variant и обнаружил, что это функция работает, только если строка формата %s. Я проверил документацию о функции Format, но не существует никаких ссылок на то, как обрабатываются варианты значений.

Рассмотрим это простое приложение:

{$APPTYPE CONSOLE}

uses
  Variants,
  SysUtils;

procedure TestFormat;
var
  v : Variant;
begin
  v:=100;
  writeln(Format('The VarType of v is %s',[VarTypeAsText(VarType(v))]));
  writeln(Format('The value of v is %s',[v]));//ok

  v:='100';
  writeln(Format('The VarType of v is %s',[VarTypeAsText(VarType(v))]));
  writeln(Format('The value of v is %s',[v]));//ok

  v:=100;
  writeln(Format('The VarType of v is %s',[VarTypeAsText(VarType(v))]));
  writeln(Format('The value of v is %d',[v]));//raise a EConvertError exception EConvertError: Format '%d' invalid or incompatible with argument
end;


begin
  try
     TestFormat;
  except
    on E: Exception do
      Writeln(E.ClassName, ': ', E.Message);
  end;
  readln;
end.

Это ошибка или простое ограничение этой функции?

Я проверил это поведение в Delphi 5, Delphi 2007 и Delphi XE.


person RRUZ    schedule 04.04.2011    source источник


Ответы (2)


Это ограничение функции. В Delphi XE соответствующая часть в SysUtils начинается со строки 10870, которая выглядит следующим образом:

@CvtVariant:
        CMP     CL,'S'
        JNE     @CvtError

Это вызывается для любого вариантного аргумента. Регистр CL имеет тип, требуемый строкой формата для этого конкретного аргумента, для чего-либо, отличного от «S», возникает исключение.

person jachguate    schedule 04.04.2011
comment
Вы примерно на минуту быстрее читаете ассемблер, чем я; Я, должно быть, заржавел. (Или вы начали раньше. ‹g›) +1 - person Ken White; 04.04.2011
comment
@ Кен, ха-ха, я не очень хорошо разбираюсь в ассемблере, но я пытаюсь его улучшить ... рад видеть, что у меня все получается. :D - person jachguate; 04.04.2011
comment
@RRUZ С удовольствием, Родриго ;). Usualmente меня pregunto си се vale hablar ип poco де español aquí. :D - person jachguate; 04.04.2011
comment
se siente un poco extraño postear en español en SO, pero a veces lo hago tambien en comentarios. ;) - person RRUZ; 04.04.2011

Это ограничение функции. Чтобы получить более многофункциональную версию Format, попробуйте функцию WideFormat из JCL. (Я его автор.) Он поддерживает Variant различных типов, Boolean и TClass. Он также принимает типы указателей символов для формата %p и значения Int64 и Variant для аргументов индекса.

Несмотря на свои расширения, он был удален из дистрибутива JCL около года назад, поскольку его основной целью был Delphi 5, который не предоставлял родную версию WideString для Format, а JCL больше не поддерживает Delphi 5. Последняя версия, включавшая его. было 3140.

person Rob Kennedy    schedule 04.04.2011
comment
Как включить его в Firemonkey? - person Machado; 09.03.2016
comment
Я предполагаю, что вы включили бы его так же, как и все остальное в Firemonkey, @Tardoandre. Если у вас возникли проблемы, рассмотрите возможность задать вопрос о переполнении стека. Включите детали того, что вы пытались сделать, и что именно пошло не так. - person Rob Kennedy; 09.03.2016