Categories
Delphi Programming

Enumerations as class type in a generic class/record

Last night I had a really strange compiler error when I tried to translate my new array record. You have to know that I have rewritten the complete record and added generic support to it. Here is a lil’ bit of the code which you need to unterstand why I got this error.

TApArray<T> = record
public type
  TArrayPosition = (apBegin, apEnd, apIndex);
private
  FData : TArray<T>;
public
  function TApArray<T>.Add(const Items: TArray<T>; const APosition: TArrayPosition = apEnd; const Index: Integer = -1): TArray<T>;
  { ... }
end;

{ ... }

function TApArray<T>.Add(const Items: TArray<T>; const APosition: TArrayPosition = apEnd; const Index: Integer = -1): TArray<T>;
var
  i : Integer;
  L : Integer;
begin
  if (APosition = apIndex) and ((Index < 0) or (Index > Length() - 1)) then
    raise Exception.Create('Index out of range.');

  { ... }
end;

When I wanted to compile the source Delphi gave me the following error message and jumped to the end of the source file:

[DCC Fatal Error] Project1.dpr(1): F2084 Internal Error: AV221E0FCF-R0000000C-0

I wondered what that message wanted to tell me because I’ve never seen that before. So I asked the most-used web search engine because I had definitely no idea why I got this message – Delphi didn’t even jump to the position where the problem was. But there were no answers, not a single page mentions this error.

After some time I found the position of the error: the first usage of an element of  TArrayPosition. Well, when I commented the line with the if in the Add() method there was no error message any more. After some time of thinking about the problem it was clear: the problem was that I have declared the type TArrayPosition as a class type of TApArray<T>.

For every instance of TApArray<T> this would lead to a new class type TArrayPosition which itself would not result in a problem yet. But what about the usage of an element? And exactly here is the problem: in my example above the apIndex is not unique any more because there are more versions of TArrayPosition and so there are more versions of apIndex. The compiler can’t know to which type apIndex belongs to so it throws this error message.

Now, what are possible solutions for this problem? I think there are two ways how to fix it:

  1. Instead of using apIndex you can use TApArray<T>.TArrayPosition.apIndex which addresses a unique element of a specific instance of TArrayPosition. But you have to write more code than you really want to. Especially there is no reason to do this for a public class type. But when you want to use a (strict) private class type this is the solution you should choose.
  2. The second solution is not to declare TArrayPosition as a class type but as a normal type like this:
    TArrayPosition = (apBegin, apEnd, apIndex);
    TApArray<T> = record
      { ... }
    end;

    This should be the preferred version when you don’t need a private type.

Leave a Reply

Your email address will not be published. Required fields are marked *

Captcha * Time limit is exhausted. Please reload CAPTCHA.