Nigel Thomas 36 Posted January 25 Using D12.1 CE. I can do this: TMyRec = record private function ConvertStrAToNum: Integer; . function ConvertStrNToNum: Integer; public StrA: string; . StrN: string; property IntA: Integer read ConvertStrAToNum; . property IntN: Integer read ConvertStrNToNum; end; function TMyRec.ConvertStrAToNum: Integer; begin Result := StrToInt(StrA); end; . function TMyRec.ConvertStrNToNum: Integer; begin Result := StrToInt(StrN); end; What I'd like to be able to do: TMyRec = record private function ConvertStrToInt(const StrToConvert: string): Integer; public StrA: string; . StrN: string; property IntA: Integer read ConvertStrToInt(StrA); . property IntN: Integer read ConvertStrToInt(StrN); end; function TMyRec.ConvertStrToInt(const StrToConvert: string): Integer; begin Result := StrToInt(StrToConvert); end; But I can't. Context: I'm reading strings into the record, as that is how they are read from a datafile. I could just parse the string data into integers as I read the file, but I thought the above option might be more elegant, as the conversion would only be done if later in the app I require the integer representation of the string data. Share this post Link to post
bravesofts 25 Posted January 25 (edited) sorry, i can't understand your question --- are you trying to make more than one property read from single universal function, or you are trying to build a record for converting strings to integers ? --- or are you trying to build a dictionary of integers based on given strings ? this is what i can help for, if i get exactly what you want: if a dictionary: unit API.MyDictionary; interface uses System.SysUtils, System.Generics.Collections; type TDictionaryContainer = TDictionary<string, Integer>; TMyDictionary = class private fStrDictionary: TDictionaryContainer; function GetValueOrDefault(const aKey: string): Integer; procedure Log(const aMessage: string); public constructor Create(const aStrList: array of string); destructor Destroy; override; procedure AddOrUpdateKey(const aKey: string; aValue: Integer); procedure RemoveKey(const aKey: string); function TryGetValue(const aKey: string; out aValue: Integer): Boolean; property Dictionary: TDictionaryContainer read fStrDictionary; property Values[const aKey: string]: Integer read GetValueOrDefault; end; implementation { TMyDictionary } constructor TMyDictionary.Create(const aStrList: array of string); var I: Integer; begin fStrDictionary := TDictionaryContainer.Create; Log('Dictionary created.'); for I := Low(aStrList) to High(aStrList) do begin fStrDictionary.Add(aStrList[I], 0); // Initialize all keys with a default value of 0 Log(Format('Key "%s" added with default value 0.', [aStrList[I]])); end; end; destructor TMyDictionary.Destroy; begin Log('Dictionary destroyed.'); fStrDictionary.Free; inherited; end; procedure TMyDictionary.Log(const aMessage: string); begin // Simple console output for logging. // Replace this with your custom logging if needed. Writeln('[LOG] ', aMessage); end; procedure TMyDictionary.AddOrUpdateKey(const aKey: string; aValue: Integer); begin if fStrDictionary.ContainsKey(aKey) then begin fStrDictionary.AddOrSetValue(aKey, aValue); Log(Format('Key "%s" updated with value %d.', [aKey, aValue])); end else begin fStrDictionary.Add(aKey, aValue); Log(Format('Key "%s" added with value %d.', [aKey, aValue])); end; end; procedure TMyDictionary.RemoveKey(const aKey: string); begin if not fStrDictionary.ContainsKey(aKey) then begin Log(Format('Failed to remove key "%s": Key not found.', [aKey])); raise Exception.CreateFmt('Key "%s" does not exist in the dictionary.', [aKey]); end; fStrDictionary.Remove(aKey); Log(Format('Key "%s" removed.', [aKey])); end; function TMyDictionary.GetValueOrDefault(const aKey: string): Integer; begin if not fStrDictionary.TryGetValue(aKey, Result) then begin Result := 0; // Default value Log(Format('Key "%s" not found. Returning default value %d.', [aKey, Result])); end else Log(Format('Key "%s" found with value %d.', [aKey, Result])); end; function TMyDictionary.TryGetValue(const aKey: string; out aValue: Integer): Boolean; begin Result := fStrDictionary.TryGetValue(aKey, aValue); if Result then Log(Format('Key "%s" found with value %d.', [aKey, aValue])) else Log(Format('Key "%s" not found.', [aKey])); end; end. the dpr console test: program DictionaryPrj; {$APPTYPE CONSOLE} {$R *.res} uses System.SysUtils, API.MyDictionary in 'API\API.MyDictionary.pas'; procedure TestMyDictionary; var MyDict: TMyDictionary; Value: Integer; begin // Create the dictionary with initial keys MyDict := TMyDictionary.Create(['Key1', 'Key2']); try MyDict.AddOrUpdateKey('Key1', 10); MyDict.AddOrUpdateKey('Key3', 15); MyDict.TryGetValue('Key2', Value); MyDict.Values['Key1']; MyDict.Values['Key4']; // Returns default value (0) MyDict.RemoveKey('Key1'); MyDict.AddOrUpdateKey('Key1', 100); MyDict.Dictionary.Items['Key1']; finally MyDict.Free; end; end; begin try TestMyDictionary; except on E: Exception do Writeln(E.ClassName, ': ', E.Message); end; Readln; end. i hope this what you looking for.. Edited January 25 by bravesofts 1 Share this post Link to post
David Heffernan 2398 Posted January 25 Read the section on index specifiers https://docwiki.embarcadero.com/RADStudio/Sydney/en/Properties_(Delphi) 3 1 Share this post Link to post
Remy Lebeau 1529 Posted January 25 (edited) 15 hours ago, Nigel Thomas said: What I'd like to be able to do: ... But I can't. This has nothing to do with records. Properties simply don't allow you to directly pass in parameters to the getter/setter methods of the read/write specifiers. However, there is an alternative - put the strings into an array, and then use an index specifier on the property, which will get passed to the getter method when it is called, eg: type TMyRec = record private function ConvertStrToInt(IndexOfStrToConvert: Integer): Integer; public const N = ...; public StrArr: array[0..N-1] of string; property IntA: Integer index 0 read ConvertStrToInt; //... property IntN: Integer index N-1 read ConvertStrToInt; end; function TMyRec.ConvertStrToInt(IndexOfStrToConvert: Integer): Integer; begin Result := StrToInt(StrArr[IndexOfStrToConvert]); end; Edited January 25 by Remy Lebeau 1 2 Share this post Link to post
Nigel Thomas 36 Posted January 25 It is now apparent to me that checking the documentation more often would be time well spent! Thanks all. Share this post Link to post