本文作者:icy

Delphi 键值记录(Key-Value Record)这样好用吗?

icy 06-19 69 抢沙发
Delphi 键值记录(Key-Value Record)这样好用吗?摘要: 最近Delphi使用的比较多了,之前一直都处于弃用状态,。,,,所以深思了一个问题在 Delphi 中使用记录(record)来存储键值对(key-value pairs),但不确...


Delphi 键值记录(Key-Value Record)这样好用吗?

最近Delphi使用的比较多了,之前一直都处于弃用状态,。,,,所以深思了一个问题

在 Delphi 中使用记录(record)来存储键值对(key-value pairs),但不确定这是否是一个好的设计选择。

type
  TKeyValue = record
    Key: string;
    Value: Variant;
  end;

然后,我可以使用动态数组或列表来管理多个键值对:

var
  KeyValuePairs: TArray<TKeyValue>;

或者:

var
  KeyValueList: TList<TKeyValue>;

问题是:

  1. 这种设计在 Delphi 中是否合理?

  2. Variant 类型是否适合存储不同类型的值(如整数、字符串、布尔值等)?

  3. 是否有更好的替代方案(比如使用 TDictionary 或其他数据结构)?

  4. 合理性

    • 如果键值对数量较少且结构简单,这种设计是可行的。

    • 但对于复杂或高性能场景,可能需要更专业的解决方案。

  5. 关于 Variant

    • Variant 可以存储多种类型,但会带来性能开销和类型安全风险。

    • 建议考虑泛型或特定类型的替代方案。

  6. 替代方案

    • 使用 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. 通过"不过除此之外...但..."的转折结构完整保留原文逻辑层次

    文章版权及转载声明

    作者:icy本文地址:https://zelig.cn/2025/06/39.html发布于 06-19
    文章转载或复制请以超链接形式并注明出处软角落-SoftNook

    觉得文章有用就打赏一下文章作者

    支付宝扫一扫打赏

    微信扫一扫打赏

    阅读
    分享

    发表评论

    快捷回复:

    验证码

    评论列表 (暂无评论,69人围观)参与讨论

    还没有评论,来说两句吧...