Why is Self assignable in Delphi?
Asked Answered
T

5

17

This code in a GUI application compiles and runs:

procedure TForm1.Button1Click(Sender: TObject);
begin
  Self := TForm1.Create(Owner);
end;

(tested with Delphi 6 and 2009)

  • why is Self writable and not read-only?
  • in which situations could this be useful?

Edit:

  • is this also possible in Delphi Prism? (I think yes it is, see here)

Update: Delphi applications/libraries which make use of Self assignment:

Tobiastobie answered 2/5, 2009 at 10:0 Comment(0)
T
11

That's not as bad as it could be. I just tested it in Delphi 2009, and it would seem that, while the Self parameter doesn't use const semantics, which you seem to be implying it should, it also doesn't use var semantics, so you can change it all you want within your method without actually losing the reference the caller holds to your object. That would be a very bad thing.

As for the reason why, one of two answers. Either a simple oversight, or what Marco suggested: to allow you to pass Self to a var parameter.

Turnpike answered 2/5, 2009 at 12:24 Comment(0)
G
7

Maybe to allow passing to const or var parameters?

It could be an artefact, since system doesn't have self anywhere on the left of := sign.

Grimonia answered 2/5, 2009 at 11:40 Comment(2)
For passing self as const no special allowance is needed, for that Self can be const too. Passing it as a Var parameter is just another form of assigning, the question remains.Overrefinement
@Henk Holterman: Maybe it is just for convenience: Imagine that there is a function (from some library) that requires an object reference as a var parameter even though you might know that it does not actually change it. If self was not assignable, you would have to declare an additional variable, assign self to it and pass that variable. Since self is assignable you can just pass self to the function.Tel
O
5

Assigning to Self is so illogical and useless that this 'feature' is probably an oversight. And as with assignable constants, it's not always easy to correct such problems.

The simple advice here is: don't do it.

Overrefinement answered 2/5, 2009 at 17:16 Comment(0)
W
2

In reality, "Self" is just a name reference to a place on the stack that store address pointing to object in the heap. Forcing read-only on this variable is possible, apparently the designer decided not to. I believe the decision is arbitrary.

Can't see any case where this is useful, that'd merely change a value in stack. Also, changing this value can be dangerous as there is no guarantee that the behavior of the code that reference instance's member will be consistence across compiler versions.

Updated: In response to PatrickvL comment

The 'variable' "Self" is not on the stack (to my knowledge, it never is); Instead it's value is put in a register (EAX to be exact) just before a call to any object method is made. –

Nope, Self has actual address on the memory. Try this code to see for yourself.

procedure TForm1.Button1Click(Sender: TObject);
begin
  ShowMessage(IntToStr(Integer(@Self)));
end;

procedure TForm1.Button2Click(Sender: TObject);
var
  newform: TForm;
  p: ^Integer;
begin
  Self.Caption := 'TheOriginal';
  newform := TForm.Create(nil);
  try
    newform.Caption := 'TheNewOne';
    // The following two lines is, technically, the same as
    //   Self := newform;
    p := Pointer(@Self);
    p^ := Integer(newform);
    ShowMessage(Self.Caption);  // This will show 'TheNewOne' instead of 'TheOriginal'
  finally
    Self.Free; // Relax, this will free TheNewOne rather than TheOriginal
  end;
end;
Whence answered 2/5, 2009 at 12:4 Comment(7)
Changing a value in the stack could be dangerous - what will happen to the old object instance? Memory Leaking I guess.Tobiastobie
@mjustin: No problem with changing the stack value, it is just a reference (pointer) to the object, the calling code / the owner would still have the reference to finally free the object.Mainstay
Self is implemented as an ordinary object reference, to ordinary even as this question shows.Overrefinement
It's not a "by convention" name. It's built into the language. You can't choose to go against the convention use a different name in your own programs.Diazotize
The 'variable' "Self" is not on the stack (to my knowledge, it never is); Instead it's value is put in a register (EAX to be exact) just before a call to any object method is made.Ithaman
Hm, SO lost my previous comment, but you're wrong. Just ignore the @Self test and look at the disassembly of "Self := nil", it'll become something like "xor eax,eax"Ithaman
It should be called optimization. Yes, most of the time "Self" is does not stored in the stack. But I believe it's fair to make assumption that it's on the stack, since compiler will always make it look so.Whence
I
1

Sometimes, when you want to optimize a method for as far as you can take it (without resorting to assembly), 'Self' can be (ab)used as a 'free' variable - it could just mean the difference between using stack and using registers.

Sure, the contents of the stack are most probably already present in the CPU cache, so it should be fast to access, but registers are even faster still.

As a sidenote : I'm still missing the days when I was programming on the Amiga's Motorola 68000 and had the luxury of 16 data and 16 address registers.... I can't believe the world chose to go with the limited 4 registers of the 80x86 line of processors!

And as a final note, I choose to use Self sometimes, as the Delphi's optimizer is, well, not optimizing that well, actually. (At least, it pales compared to what trickery one can find in the various LLVM optimizers for example.) IMHO, and YMMV of course.

Ithaman answered 30/3, 2010 at 11:49 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.