CrossTalk Archive

Enums

Enums

.NET and Delphi handle enumerations quite differently. Because of this CrossTalk has to do a bit of a translation.

CrossTalk cannot translate .NET enums into Delphi enums. For one thing, Delphi enums have no namespace. This is why Delphi enums typically have a prefix. i.e. clRed, clBack, etc. Let’s take the example of System.Xml.ConformanceLevel which is an enum that look like this:

public enum ConformanceLevel {
    Auto, Fragment, Document
}

If CrossTalk translated it as:

type ConformanceLevel = (Auto, Fragment, Document);

Then Auto, Fragment, and Document become global identifiers and would easily conflict with other identifiers. CrossTalk could have prefixed each like this:

type ConformanceLevel = (ConformanceLevel_Auto, ConformanceLevel_Fragment, ConformanceLevel_Document);

This gets a bit ugly, but potentially in many cases could create conflicts as well. Because of these factors CrossTalk instead creates a class with class functions.

type
  ConformanceLevel = class
  public
    class function Auto: Longword;
    class function Fragment: Longword;
    class function Document: Longword;
  end;

implementation

{ System.Xml.ConformanceLevel }

class function ConformanceLevel.Auto: Longword;
begin
   Result := 0;
end;

class function ConformanceLevel.Fragment: Longword;
begin
   Result := 1;
end;

class function ConformanceLevel.Document: Longword;
begin
   Result := 2;
end;

We also considered using read only properties as this would be more efficient to read values, however this has the drawback of requiring the class to be created first, and also then later destroyed.

CrossTalk also translates any enum references to LongWord.

property ConformanceLevel: Longword {Enum: ‘System.Xml.ConformanceLevel} read ConformanceLevelRead write ConformanceLevelWrite;

While this removes type safety of enums, it allows natural code to be written.

xSettings := XmlReaderSettings.Create; try
    xSettings.ConformanceLevel := ConformanceLevel.Fragment;
    xSettings.IgnoreWhitespace := true;
    xSettings.IgnoreComments := true;
    ……..
finally xSettings.Free; end;

We also considered emitting one enum per unit and using unit qualifications. The problem is that to do this the unit still has to be added to the uses clause, thus entering it into that units global namespace. This does not really enable namespaces, so much as it forces disambiguation. Not only would the reference to the enum need to be qualified, but so would the opposite conflicting symbol(s). With a lot of conflicts (as would exist most definitely) it creates quite a mess.