Delphi - records with variant parts

I want to have a record (structure) with "polymorphic" content. It will have several fields used in all cases, and I want to use other fields only when I need them. I know that I can accomplish this according to the options declared in the entries. I don’t know if it’s possible that during development I can only access the elements that I need. To be more specific, look at the example below

program consapp; {$APPTYPE CONSOLE} uses ExceptionLog, SysUtils; type a = record b : integer; case isEnabled : boolean of true : (c:Integer); false : (d:String[50]); end; var test:a; begin test.b:=1; test.isEnabled := False; test.c := 3; //because isenabled is false, I want that the c element to be unavailable to the coder, and to access only the d element. Writeln(test.c); readln; end. 

Is it possible?

+6
source share
3 answers

All field options in the record variant are always available, regardless of the tag value.

To achieve the accessibility controls you are looking for, you will need to use properties and have runtime checks to control availability.

 type TMyRecord = record strict private FIsEnabled: Boolean; FInt: Integer; FStr: string; // ... declare the property getters and settings here public property IsEnabled: Boolean read FIsEnabled write FIsEnabled; property Int: Integer read GetInt write SetInt; property Str: string read GetString write SetString; end; ... function TMyRecord.GetInt: Integer; begin if IsEnabled then Result := FInt else raise EValueNotAvailable.Create('blah blah'); end; 
+7
source

Even if I had heard that according to the original definition of Niklaus Wirth Pascal, everything should work as you expected, I have not seen this behavior in Delphi, starting with its ancestor, Turbo Pascal 2.0 . A quick look at FreePascal showed that its behavior is the same. As stated in the Delphi Documentation :

You can read or write in any field of any option at any time; but if you write in a field in one embodiment, and then in a field in another embodiment, you can rewrite your own data. The tag, if any, functions as an additional field (of type ordinalType) in the non-invariant part of the record. "

As for your intention, as I understand it, I would use two different classes, like

  a = class b : Integer end; aEnabled = class(a) c: Integer end; aDisabled = class(a) d: String //plus this way you can use long strings end; 

This way, you can get some support from the IDE code editor even during development. More useful, however, is that it will be much easier to modify and maintain later.

However, if you need to quickly switch the values ​​of recording variables at runtime, @David Heffernan variant , using properties and checking the runtime is more reasonable.

+3
source

The above example is NOT a record option; it includes all fields all the time.

The true version of the recording has options that share the same memory. You simply use the syntax "case discinator: DiscType of .....", there is no need for a separate field telling you which option is active.

-3
source

Source: https://habr.com/ru/post/900122/


All Articles