【问题标题】:Record in TDictionary记录在 TDictionary
【发布时间】:2018-11-30 06:26:24
【问题描述】:

如何在TDictionary 中使用record

TMyRec = record
    a: Integer;
    b: Integer;
end;

...

dictionary = TDictionary<String, TMyRec>.create();

...

dictionary[key].a := 30;<<<

这里编译器给出一个错误:“左侧不能分配给”。如何在不创建单独的函数来编写myFunc(a, b: Integer): TMyRec 的情况下解决此问题?

【问题讨论】:

标签: delphi delphi-xe


【解决方案1】:

dictionary[key] 返回字典保存的记录的副本。编译器会阻止你修改它,因为它没有任何用处。

顺便说一句,旧版本的程序会接受您的代码,而且对记录的修改会丢失,这非常令人困惑。您会进行分配,但没有任何可见的变化,因为您分配的是一个无名的局部变量。

很明显,您打算修改集合中保存的记录。为此,您需要分配整个记录。将集合中的记录读入局部变量。修改局部变量。将更新后的值写回集合。像这样:

var
  rec: TMyRec;
...
rec := dictionary[key];
rec.a := 30;
dictionary[key] := rec;

其中一个令人沮丧的方面是代码需要执行两次字典查找,即使我们知道第二个会找到与第一个相同的记录。即使是强大的 Spring4d 字典也不能通过一次查找来做到这一点。

【讨论】:

  • 如果字典可以返回一个指向存储记录的指针,那将是可能的。那么就不需要双重查找了。但是 AFAIK 没有我知道的字典支持这一点,而且使用泛型编码可能并不容易。
  • FWIW,字典可以缓存最后搜索的键,如果下一次搜索使用相同的键,则不需要新的查找。毕竟,在这种情况下,相同的密钥会被使用两次。
  • @RudyVelthuis 我认为我不会这样做。我有类似更新方法的东西,procedure UpdateValue(const Key: TKey; const UpdateProc: TUpdateProc&lt;TValue&gt;);,其中TUpdateProc 由var a TValue 传递。我一直在与 Stefan 在 spring4d 字典的背景下讨论这个问题。
  • 你可以两者兼得。特定场景的特定更新方法,以及作为“隐藏”功能的缓存。后者的缺点是字典总是必须检查键是否相同,以便它可以使用缓存。根据使用情况,您在该检查中损失的周期数将超过通过访问缓存获得的周期数。也许还有第三种选择,有一个返回对项目的引用的方法?
  • @GolezTrol:“第三个选项”是我的第一个选项。 其他任何东西,例如 UpdateValue 事物或缓存,确实可能比指向存储项目的简单指针(不必是记录)慢。我想这三个的组合会很好。所以你可以选择最适合这种情况的一个。
【解决方案2】:

David Heffernans answer 是您所追求的,但我想提供一个额外的警告。记录可以像类一样具有属性,具有 getter 和 setter,如果您的记录具有这样的属性,您的代码将编译,但它仍然不会更改实际的记录值。

TMyRec = record
private
  FA : integer;
  procedure SetA(const Value: integer);
  function GetA : integer;
public
  { Warning: When used on result from dictionary lookup, only the COPY will be 
    altered, not the actual record in the dictionary! }
  property A : integer read GetA write SetA; 
end;

【讨论】:

  • 这不能回答所提出的问题。应该是评论吗?
【解决方案3】:

一个非常简单的解决方法是使用记录的 List 属性。

你可以说:

dictionary.list[key].a := 30;

这将通过 List 属性访问备份 TList 的动态数组。编译器已经支持直接访问动态数组。

如果您可以登录 quality.embarcadero.com,您可以看到关于此问题的完整讨论:RSP-23136: We should be able to assign a value to one element in a list of records - 发布于 2018 年 12 月 18 日,并于 2019 年 11 月 21 日解决。

问题已通过评论关闭:

“这按预期工作。提供了替代编码样式。”

【讨论】:

    猜你喜欢
    • 2014-11-27
    • 1970-01-01
    • 2016-02-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-01-02
    相关资源
    最近更新 更多