Nigel Thomas 36 Posted Saturday at 02:19 AM 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 19 Posted Saturday at 04:43 AM (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 Saturday at 04:44 AM by bravesofts Share this post Link to post
David Heffernan 2361 Posted Saturday at 05:14 AM 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 1465 Posted Saturday at 06:18 PM (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 Saturday at 06:22 PM by Remy Lebeau 2 Share this post Link to post
Nigel Thomas 36 Posted Saturday at 07:14 PM 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