Record in TDictionary

record synonym
record pronunciation
record and record
record definition computer
record definition database
record voice
online dictionary
define track record

How can I use record in TDictionary?

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

...

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

...

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

Here the compiler gives an error: "Left side cannot be assigned to". How can I solve this problem without creating a separate function for writing myFunc(a, b: Integer): TMyRec?

dictionary[key] returns a copy of the record held by the dictionary. The compiler prevents you from modifying that because it would serve no purpose.

As an aside, older versions of the program would accept your code and it was very confusing that the modification to the record would be lost. You'd make an assignment but nothing visible changed because what you assigned was a nameless local variable.

Clearly you intend to modify the record held in the collection. In order to do that you need to assign the entire record. Read the record from the collection into a local variable. Modify the local variable. Write the updated value back to the collection. Like so:

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

One of the frustrating aspects of this is that the code needs to perform two dictionary lookups, even though we know that the second one will find the same record as the first one. Not even the mighty Spring4d dictionary can do this with a single lookup.

Record, synonyms: account(s), document(s), documentation, data, file(s), dossier(s), information, evidence, report(s), annal(s), archive(s), chronicle(s), note(s), minutes, transactions, proceedings, transcript(s), certificate(s), deed(s), instrument(s), diary, journal, memoir, register, log, logbook, yearbook, almanac, inventory, list, catalog, case history, case study, casebook, proc├Ęs-verbal, act(s), muniment(s) record noun (INFORMATION) B2 [ C or U ] a piece of information or a description of an event that is written on paper or stored on a computer: The weather centre keeps a record of the weather.

David Heffernans answer is what you're after, but I would like to offer an additional warning. Records can have properties just like classes, with getters and setters, and if your record has such properties your code will compile, but it will still not change the actual record value.

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;

RECORD, the sum of the past achievements or actions of a person or organization; a person or thing's previous conduct or performance. Definition of record. (Entry 1 of 4) transitive verb. 1 a (1) : to set down in writing : furnish written evidence of. (2) : to deposit an authentic official copy of record a deed. b : to state for or as if for the record voted in favor but recorded certain reservations.

A very simple workaround is to use the List property of the record.

You can say:

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

This will access the dynamic array that backs up the TList via the List property. The compiler already supports direct access to a dynamic array.

If you can login to quality.embarcadero.com, you can see the full discussion of this issue raised as: RSP-23136: We should be able to assign a value to one element in a list of records - posted Dec 18, 2018 and resolved Nov 21, 2019.

The issue was closed with the comment:

"This works as expected. Alternative coding style was provided."

RECORD (noun) definition and synonyms, synonyms: previous conduct/performance, track record, career to date, history, past, life history, background, reputation, curriculum vitae Clearly you intend to modify the record held in the collection. In order to do that you need to assign the entire record. Read the record from the collection into a local variable. Modify the local variable. Write the updated value back to the collection. Like so: var rec: TMyRec; rec := dictionary[key]; rec.a := 30; dictionary[key] := rec;

RECORD (verb) definition and synonyms, (especially in sports) the best performance or most remarkable event of its kind that has been officially measured and noted. record in (something) 1. To capture audio or video from or within a particular location. We had to record in my basement until we'd saved up enough money to start using a real studio.

Record, synonyms: best performance, highest achievement, star performance, best time, fastest time, furthest distance, personal best, world record Yes, you can use records as keys in a TDictionary but you should provide your own IEqualityComparer when creating the dictionary because the default one for records just does a dumb binary compare of the record.

Record, a thin plastic disk carrying recorded sound, especially music, in grooves on each surface, for reproduction by a record player. Recording definition, the act or practice of a person or thing that records. See more.

Comments
  • Did you try assigning whole dictionary[key] := someRec; ?
  • Related to stackoverflow.com/questions/620506/…
  • It would be possible if the dictionary could return a pointer to the stored record. Then no double lookup would be required. But AFAIK no dictionary I know supports this, and it is probably not so easy to code with generics anyway.
  • FWIW, a dictionary could cache the last key searched, and if the next search uses the same key, no new lookup is required. In scenarios like this, the same key is used twice, after all.
  • @RudyVelthuis That's not how I would do it I think. I'd have something like an update method, procedure UpdateValue(const Key: TKey; const UpdateProc: TUpdateProc<TValue>); where TUpdateProc is passed by var a TValue. I've been discussing this in the context of the spring4d dictionary with Stefan.
  • You could have both. The specific update method for specialized scenarios, and the caching as a 'hidden' feature. The disadvantage of the latter is that the dictionary will always have to check if the key is the same so it can use the cache. Depending on the use, you will lose more cycles over that check than you will gain by hitting the cache. Maybe there is a third option, to have a method that returns a reference to the item?
  • @GolezTrol: that "third option" was my first. <g> Anything else, e..g the UpdateValue thing, or the cache, could indeed be slower than a simple pointer to the store item (doesn't have to be a record). I guess a combination of all three would be nice., so you could choose the one best suited to the situation.
  • This does not answer the question that was asked. Should it have been a comment?