Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Record methods and const parameters in Delphi

It looks like the Delphi compiler does not honor const record parameters when "records-with-methods" are involved.

Having not tried to abuse the const convention previously, I was a little surprised to find the compiler accepted code like that:

type
    TTest = record
       Field : String;
       procedure Update;
    end;

procedure TTest.Update;
begin
    Field := Field + '+1';
end;

procedure DoStuff(const t : TTest);
begin
    ShowMessage(t.Field);
    t.Update;
    ShowMessage(t.Field);
end;

While if you try to do a t.Field:='doh'; in DoStuff f.i., the compiler will properly complain, but you're allowed to call methods that modify the "const" record without even a hint or warning. So this is different behavior than for reference types (such as classes or dynamic arrays), where direct field writes are allowed (as const only restricts changes to the parameter itself).

Addendum: this allows to modify declared compile-time constants this way too, as in:

const
   cTest : TTest = (Field : '1');
...
cTest.Update;              // will show '1' then '1'+'1'
ShowMessage(cTest.Field);  // will show '1' (because optimized at compile-time)

Is that an accepted/documented behavior? or just a compiler shortcoming?

like image 625
Eric Grange Avatar asked Sep 14 '11 09:09

Eric Grange


2 Answers

const never places any restrictions on method calls in Delphi, be they on records or instances of classes. So I don't think there is anything inconsistent with the treatment of method calls.

If methods could not be called on record passed as a const parameter, then that would pretty much render records with methods useless. It would mean, for example, that a property getter could not be called. In order to place restrictions on such records passed as const, there would need to be an equivalent concept to the const member functions of C++. That would allow the compiler to know that certain methods were non-mutating.

like image 83
David Heffernan Avatar answered Nov 11 '22 23:11

David Heffernan


David analyzed the restriction pretty well. If the compiler was to check out such details it could really do it with some penalty. Additionally I don't see anything wrong with the compiler's behaviour. The method which gets the record can't directly alter its data, but only when using the method it contains. The record in this case works like an object: you can in the same way an object as a const and still have the same problem you described, ie. the object's methods can be used to alter its data.

The benefit of the object is, that such methods can be declared to be private, which enables you to protect its data. You could even create an inherited class which does just that, namely hiding all possibility to alter its data. Maybe you want to try this approach?

like image 4
Fotis MC Avatar answered Nov 11 '22 22:11

Fotis MC