Необработанные/нестандартные параметры в Delphi

Какими типами являются параметры без типа типа в классе TStringStream:

function Read(var Buffer; Count: Longint): Longint; override;

Каков тип параметра Buffer (это тип указателя?).

Ответ 1

Я написал статью об этой теме несколько лет назад:

Что такое нетипизированный параметр?

Нетипированные параметры используются в нескольких ситуациях; метод TStream.Read, который вы задаете, наиболее точно соответствует процедуре Move, о которой я писал. Вот выдержка:

procedure Move(const Source; var Dest; Count: Integer);

Процедура Move копирует данные из произвольной переменной в любую другую переменную. Он должен принимать источники и адресатов все типы, что означает, что он не может требовать какого-либо одного типа. Процедура не изменяет значение переменной, переданной для Source, так что В объявлении параметров используется const вместо var, который является более общий модификатор для нетипизированных параметров.

В случае TStream.Read источник - это содержимое потока, поэтому вы не передаете это как параметр, но пунктом назначения является параметр Buffer, указанный в вопросе. Вы можете передать любой тип переменной, который вы хотите для этого параметра, но это означает, что вам нужно быть осторожным. Это ваша работа, а не компилятор, чтобы убедиться, что содержимое потока действительно является допустимым значением для типа параметра, который вы предоставляете.

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

Ответ 2

Обратитесь к справочной системе Delphi для "Untyped parameters"

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

Ответ 3

var в списке параметров есть синтаксис Delphi для вызов по ссылке. Он может быть напечатан, например. параметр AllowChange в обработчике OnChanging Listview:

procedure TSomeForm.LVOnChanging(Sender: TObject; ...; var AllowChange: Boolean);
begin
  if SomeProblemOccurred then
    AllowChange := False;
end;

или нетипизированный, как в вашем примере.

Ответ 4

Возможно, удивительно, что законно указывать разыменованный указатель как нетипизированный параметр. И сам указатель даже не должен иметь тип.

procedure SomeMethod(var aParameter);
  ∶

procedure CallSomeMethod(aIsInteger : Boolean);
type
  buffer    : Pointer;
  intValue  : Integer;
  realValue : Single;
begin
  if aIsInteger then
  begin
    buffer := @intValue;
  end
  else
  begin
    buffer := @realValue;
  end;
  SomeMethod(buffer^);

Конечно, было бы легче, если бы параметр SomeMethod() был указателем, но это может быть не под вашим контролем.