Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

E2506 Method of parameterized type declared in interface section must not use local symbol

could someone explain to me what is the reason that when creating a generic class I must move my private constans to the interface section? This is killing my design, I don't want others to see something that should be private.

unit Unit38;

interface

uses
  Generics.Collections;

type
  TSimpleClass<T> = class(TObject)
  private
    procedure DoSomethingInternal(const SomeString: string);
  public
    procedure DoSomething;
  end;

implementation

const
  MyString = 'some string'; //Why this must be public?

{ TSimpleClass<T> }

procedure TSimpleClass<T>.DoSomething;
begin
  DoSomethingInternal(MyString); //Compiler error
end;

procedure TSimpleClass<T>.DoSomethingInternal(const SomeString: string);
begin
  //-------
end;

end.

Thanks.

like image 787
Wodzu Avatar asked Oct 26 '11 06:10

Wodzu


3 Answers

Same error in D2010, so the generics fixes of D2010 did not address this. It is a bug: http://qc.embarcadero.com/wc/qcmain.aspx?d=79747

Fixed in build 15.0.3863.33207. Which I think is XE

Another QC on this is: http://qc.embarcadero.com/wc/qcmain.aspx?d=78022 which involves an enum and is still open.

The documentation on the error isn't very clear by the way. See:

E2506 Method of parameterized type declared in interface section must not use local symbol '%s'

It involves a class var in a generic class which cannot be assigned a literal (!) value in the class' constructor, the fix being to parameretrize the constructor... No idea why, but I guess it has to do with a compiler limitation.

like image 106
Marjan Venema Avatar answered Nov 10 '22 08:11

Marjan Venema


It's a consequence of the generics implementation in Delphi. When you instantiate a class by supplying a concrete T in another unit, code for the concrete class is written into that other unit. But that other unit can no longer see your private string constant. It's rather frustrating.

My understanding of the generics implementation suggests that Mikael's workaround will solve the problem because the class const will be visible when you instantiate your concrete type in another unit.

like image 41
David Heffernan Avatar answered Nov 10 '22 08:11

David Heffernan


Not an answer but a possible workaround could be to use private const in the class declaration.

TSimpleClass<T> = class(TObject)
private
    procedure DoSomethingInternal(const SomeString: string);
    const MyString = 'some string'; //Why this must be public?
public
    procedure DoSomething;
end;

This works in Delphi 2010, XE and XE2, not in Delphi 2009.

like image 4
Mikael Eriksson Avatar answered Nov 10 '22 10:11

Mikael Eriksson