3

I'm trying to write an helper class function without statically referencing to the helped class:

  TMyEnum = (meA, meB, meC);
  TMyEnumHelper = record helper for TMyEnum
  public
    class function InRange(AValue : integer) : Boolean; static;
  end;

...

class function TMyEnumHelper.InRange(AValue : Integer) : Boolean;
begin
  Result := (
    (AValue >= Ord(Low(TMyEnum))) and
    (AValue <= Ord(High(TMyEnum)))
  );
end;

Is there a way to dynamically get the helped class? I mean something like the following code:

class function TMyEnumHelper.InRange(AValue : Integer) : Boolean;
begin
  Result := (
    (AValue >= Ord(Low(HelpedClass))) and
    (AValue <= Ord(High(HelpedClass)))
  );
end;

I've tried using Self but Delphi says E2003 Undeclared identifier: 'Self'

Fabrizio
  • 7,603
  • 6
  • 44
  • 104
  • If the enumeration is contiguous, you can use a generics "helper" class to get the range using RTTI. See [Using an enum with generics](https://stackoverflow.com/a/12382861/576719) – LU RD Jan 31 '20 at 08:43
  • Yeah, don't use a helper class. Do it with a type like this: https://stackoverflow.com/a/27902039/505088 – David Heffernan Jan 31 '20 at 09:11

1 Answers1

3

Static class methods have no "self" parameter. They also cannot access any instance members. (They still have access to class fields, class properties, and class methods.)

In this case (the helper is a record helper), the class method must be declared as static.

As @David points out, an ordinary class method (not static) can refer to its type with the "Self" key, but only when it is referring to a class.
Example:

type
  TMyClass = class
  end;
  TMyClassHelper = class helper for TMyClass   
     class function NameOfClass : String;
  end;

class function TMyClassHelper.NameOfClass : String;
begin
  Result := Self.ClassName;
end;

If the enumeration is contiguous, you can use a generics "helper" method to get the range using RTTI.

type  
  TRttiHelp = record
    class function EnumInRange<TEnum>(AValue: Integer) : Boolean; static;
  end;

class function TRttiHelp.EnumInRange<TEnum>(AValue: Integer) : Boolean;
var
  typeData: PTypeData;
begin
  if GetTypeKind(TEnum) <> tkEnumeration then
    raise EInvalidCast.CreateRes(@SInvalidCast);

  typeData := GetTypeData(TypeInfo(TEnum));
  Result := (AValue >= typeData.MinValue) and (AValue <= typeData.MaxValue);
end; 

type
  TMyEnum = (a,b,c); 
begin
  WriteLn(TRttiHelp.EnumInRange<TMyEnum>(2));  // Writes true
end. 
LU RD
  • 34,438
  • 5
  • 88
  • 296