tags:

views:

266

answers:

4

What type are parameters without type like in the class TStringStream:

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

What is the type of Buffer parameter (is it a type of Pointer ?).

+1  A: 

Check out the Delphi help for "Untyped parameters"

You can pass in any type, but you have to cast it in the implementation. Help says that you cannot pass it a numeral or untyped numeric constant. So basically you have to be know what type to expect, and compiler can not help you, so you need a good reason to do it this way. I suppose it could be of use if you need the method to handle incompatible types, but then again you could write several overloaded versions for each expected type, I would suggest that as a better solution.

Daniel Maurić
The `Buffer` parameter is not a pointer. Treat it like a pointer, and things will crash. It is the *actual buffer* want to change, not a pointer to a buffer. The address of the parameter is the address of the buffer.
Rob Kennedy
I stand corrected
Daniel Maurić
A: 

var in a parameter list is the Delphi syntax for call by reference. It can be typed as e.g. the AllowChange parameter in the OnChanging handler of an Listview:

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

or untyped as in your example.

Ulrich Gerhardt
+9  A: 

I wrote an article about this very topic a few years ago:

What is an untyped parameter?

Untyped parameters are used in a few situations; the TStream.Read method you ask about most closely matches with the Move procedure I wrote about. Here's an excerpt:

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

The Move procedure copies data from an arbitrary variable into any other variable. It needs to accept sources and destinations of all types, which means it cannot require any single type. The procedure does not modify the value of the variable passed for Source, so that parameter’s declaration uses const instead of var, which is the more common modifier for untyped parameters.

In the case of TStream.Read, the source is the stream's contents, so you don't pass that in as a parameter, but the destination is the Buffer parameter shown in the question. You can pass any variable type you want for that parameter, but that means you need to be careful. It's your job, not the compiler's, to ensure that the contents of the stream really are a valid value for the type of parameter you provide.

Read the rest of my article for more situations where Delphi uses untyped parameters.

Rob Kennedy
+1 @Rob, very nice article.
RRUZ
A: 

Perhaps surprisingly, it is legal to pass a dereferenced pointer as an untyped parameter. And the pointer itself doesn't even have to have a type.

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^);

Of course it would probably have been easier if the parameter to SomeMethod() had been a pointer, but this might not be under your control.

Ian Goldby