Why can I have a local variable in a method that out-scopes a class property without a hint or warning?

Why can I have a local variable in a method that out-scopes a class property without a hint or warning?

One thing is allowing name overlaps for method parameters, but for local variables - does that even make sense?

type
  TBadClass = class
  private
    FValue: Integer;
    procedure SetValue(const Value: Integer);
  public
    procedure CheckValue;
    property Value: Integer read FValue write SetValue;
  end;

procedure TBadClass.SetValue(const Value: Integer);
begin
  FValue := Value;
end;

procedure TBadClass.CheckValue;
var
  Value: Integer;
begin
  Value := 1;
  Writeln('Value ', Value);
  Writeln('Self ', Self.Value);
  Self.Value := 2;
  Writeln('Value ', Value);
  Writeln('Self ', Self.Value);
end;

Output is
Value 1
Self 0
Value 1
Self 2

#XE6

Comments

  1. I think this has been how the language behaves (and most other languages do). I know this is very odd, but technically you can access both, as your code shows. Same for a parameter matching a field.
    What if you have some perfectly working code and you add a field? What if the field is added to a base class? Too many scenarios, I think, some of which could have merit...

    ReplyDelete
  2. This is how Delphi scope rules work. Inner block declarations always take precedence over outer block. 

    Adding warnings to that kind of behaviour would very likely result in having warnings all over your code.

    ReplyDelete
  3. I think that is one of the things that some metric tools like Pascal Analyzer can spot (not sure about the metrics that are included in higher versions of Delphi though)
    P.S. FWIW thats an instance property and not a class property

    ReplyDelete
  4. A hint would make sense in many cases TBH.

    Yes, it would be annoying in the scenario described by Marco Cantù but on the other hand if you keep adding fields or methods with names overlapping local ones, you will eventually end up with a big ball of hard to maintain code.

    ReplyDelete
  5. You could use Pascal Analyzer by Peganza.com to find ambigious references or symbol overlapping.

    ReplyDelete
  6. Eric Grange Yes, some hints the compiler could generate would be useful for sure. I think it goes into the same direction of the reintroduce keyword where you tell the compiler "YES, I know what I am doing and that I am hiding a virtual method!"

    ReplyDelete
  7. it reminds me of how grateful I am to Pascal not to impose the Self. prefix like $this-> in PHP :)

    ReplyDelete
  8. For this reason i use a prefix for local variables (LValue), just like the F of FValue. Only properties dont have a prefix in my code.

    ReplyDelete
  9. I'd certainly like an option that would warn me of namespace pollution for local variables and withs, possibly also for unit scope clashes - with the option of turning it off per unit with a compiler directive.

    ReplyDelete
  10. A hint which can be disabled wouldn't hurt, but personally I'd much prefer making the language case sensitive. But apparently I'm weird like that :)

    ReplyDelete
  11. Asbjørn Heid I would like to have the language "case-exclusive" personally ie. you declare "Something" then you have to use "Something" everywhere, and can't declare "something" alongside, ie. no C/Java-like horror "Class class;"

    ReplyDelete
  12. Eric Grange I've used C++ far too much not to enjoy that ;)

    ReplyDelete

Post a Comment