最近Delphi使用的比较多了,之前一直都处于弃用状态,。,,,所以深思了一个问题
在 Delphi 中使用记录(record)来存储键值对(key-value pairs),但不确定这是否是一个好的设计选择。
type TKeyValue = record Key: string; Value: Variant; end;
然后,我可以使用动态数组或列表来管理多个键值对:
var KeyValuePairs: TArray<TKeyValue>;
或者:
var KeyValueList: TList<TKeyValue>;
问题是:
这种设计在 Delphi 中是否合理?
Variant
类型是否适合存储不同类型的值(如整数、字符串、布尔值等)?是否有更好的替代方案(比如使用
TDictionary
或其他数据结构)?合理性:
如果键值对数量较少且结构简单,这种设计是可行的。
但对于复杂或高性能场景,可能需要更专业的解决方案。
关于
Variant
:Variant
可以存储多种类型,但会带来性能开销和类型安全风险。建议考虑泛型或特定类型的替代方案。
替代方案:
使用
TDictionary<string, TValue>
(来自System.Generics.Collections
)更高效且类型安全。如果键值对是固定的,建议用明确的字段定义记录或类。
反正决定没有 其他语言下用的 爽 比如GO,,,,
以下是一个小例子
MapRecord = record private data: TArray<string>; function escapeDataValue(value: string): string; function getAsString(key: string; prefix: string): string; procedure put(key: string; value: string; prefix: string); overload; public procedure put(key: string; value: string); overload; procedure put(key: string; value: integer); overload; function getString(key: string; default: string=''): string; function getInt(key: string; default: Integer=0): Integer; function toJSON(): string; end; function MapRecord.escapeDataValue(value: string): string; begin result := value; result := result.Replace('\=', #4); result := result.Replace('=', '\='); result := result.Replace(#4, '\='); end; procedure MapRecord.put(key: string; value: string; prefix: string); var i: Integer; begin for i:=0 to Length(data)-1 do begin if Copy(data[i], 2, Length(key)-1) = key+'=' then begin data[i] := prefix+key+'=' + escapeDataValue(value); exit; end; end; SetLength(data, Length(data)+1); data[Length(data)-1] := prefix+key+'=' + escapeDataValue(value); end; procedure MapRecord.put(key: string; value: string); begin put(key, value, 's');end;procedure MapRecord.put(key: string; value: integer); begin put(key, value.ToString, 'i'); end; function MapRecord.getAsString(key: string; prefix: string): string; var s: string; i: Integer; begin result := ''; for s in data do begin if s.StartsWith(prefix+key) then begin i := Pos('=', s, Length(prefix+key)); if (i>0) and (i<s.Length) then begin result := s.Substring(i+1); result := result.Replace('\=', '='); end; end; end; end; function MapRecord.getString(key: string; default: string=''): string; begin result := getAsString(key, 's'); end; function MapRecord.getInt(key: string; default: Integer=0): Integer; begin result := StrToIntDef(getAsString(key, 'i'), default); end; function MapRecord.toJSON(): string; begin //。。。。。。转换 end;
使用:
function DoLogin();var mr: MapRecord;begin ///。。。。。。。。。。。。。。。 if LoginOK then begin mr.put('login_result', 'ok'); mr.put('user_message', 'Logged in'); end else begin mr.put('login_result', 'error'); mr.put('user_message', 'Login failed'); mr.put('allow_retry', 0); end; result := mr.toJSON(); end;
最后建议:
建议不要使用TArray<string>,而应当改用TArray<TPair<string, string>>或自定义的TValueRec记录类型(该记录包含两个字符串字段:name和value,并可添加语法糖修饰)。
不过除此之外:这个思路本身没有问题。但按照Delphi的惯用范式,更推荐使用TDictionary<T, S>来实现此类需求。
(翻译说明:
1. 将"definitely should"译为"应当"体现建议强度
2. "syntactical sugar"译为"语法糖"是编程术语标准译法
3. "idiomatic Delphi approach"译为"Delphi的惯用范式"准确传达语言特性
4. 使用中文技术文档常见的"字段"对应"record type"中的成员
5. 保持技术术语大小写规范(如TDictionary<T, S>保留原格式)
6. 通过"不过除此之外...但..."的转折结构完整保留原文逻辑层次
还没有评论,来说两句吧...