Marco van de Voort
Marco van de Voort

Reputation: 26356

TDictionary. Setting a valuetype value while iterating

Is there a safe way to mutate the value of a tdictionary, while iterating?

The first naive try:

var p: tpair<keytype,valuetype>;

begin
  for p in coll do
    // p.value is readonly for valuetypes and their fields.
 end;

failed, and also wrapping the valuetype in a RECORD doesn't help.

Iterating over keys and using dosetvalue might work, but it is private only.

I could of course use a reference type, but that seems a bit silly to me, since the state is an integer. Not elegant.

Added, complete sample:

program gendicttest;
//  tests if you can set valuetype key.

{$APPTYPE CONSOLE}

uses
  generics.collections;

type
  TCycleList = tdictionary<integer,integer>; // the value a record type doesn't work either.

var cyclelist :TCycleList;
    p : tpair<integer,integer>;
    j:integer;
begin
  cyclelist:=tcyclelist.Create;
  cyclelist.Add(3,4);
  for  p in cyclelist do
    writeln(p.Key, ' ',p.Value);

  if cyclelist.TryGetValue(3,j) then
    cyclelist.AddOrSetValue(3,j+1);
  for  p in cyclelist do
   p.Value:=0;     // <-- here, and alternative to do this.r

  for  p in cyclelist do
    writeln(p.Key, ' ',p.Value);    
end.

Upvotes: 0

Views: 208

Answers (1)

Rudy Velthuis
Rudy Velthuis

Reputation: 28806

Of course it won't work! The pair returned is a copy. So you can at best modify the copy, which makes no sense.

If you only want to clear the values, then get a copy of the keys and enumerate over them to set the value of each key to 0.

for var I in cycleList.Keys do
  cycleList.AddOrSetValue(I, 0);

Alternatively, you can use Items, which can be indexed with a key:

for var I in cycleList.Keys do
  cycleList.Items[I] := 0;

note: can also be done without Rio syntax

Upvotes: 1

Related Questions