The Wiert Corner – irregular stream of stuff

Jeroen W. Pluimers on .NET, C#, Delphi, databases, and personal interests

  • My badges

  • Twitter Updates

  • My Flickr Stream

  • Pages

  • All categories

  • Enter your email address to subscribe to this blog and receive notifications of new posts by email.

    Join 1,437 other followers

Delphi: updating a (potentially non-existing) item in a generic TDictionary: use ExtractPair. Except in Delphi 2010/XE.

Posted by jpluimers on 2018/11/06

“Documented” in Delphi 2010, [Archive.is] Generics.Collections.TDictionary.ExtractPair – RAD Studio VCL Reference, and functioning bug-free since Delphi XE2, but still hardly documented, [Archive.is] System.Generics.Collections.TDictionary.ExtractPair – XE2 API Documentation is the easiest way to get a value out of a dictionary and updating it, even if it does not exist.

ExtractPair extracts the TPair<TKey, TValue> if it exists (and removes it from the dictionary) or returns a Default initialised one if not. Though Default is still not documented, you can find an example at [WayBack] How to properly free records that contain various types in Delphi at once? – Stack Overflow.

Example code for ExtractPair:

  FEceptionDictionary := TDictionary<TExceptionKey, Integer>.Create();

...

var
  ExceptionCountPair: TPair<TExceptionKey,Integer>;
begin
  TMonitor.Enter(FEceptionDictionary);
  try
    ExceptionCountPair := FEceptionDictionary.ExtractPair(ExceptObj.ClassType); // extracts and removed from dictionary!
    FEceptionDictionary.Add(ExceptionCountPair.Key, ExceptionCountPair.Value + 1); // use Value as count
  finally
    TMonitor.Exit(FEceptionDictionary);
  end;
end;

In Delphi 2010 and XE it was buggy (see [WayBack] QualityCentral 80947: TDictionary.ExtractPair Fails and creates memory leak via [WayBack] generics – Delphi TPair Exception – Stack Overflow), but since then it works fine, and now is properly documented:

[WayBack] System.Generics.Collections.TDictionary.ExtractPair – RAD Studio API Documentation

Returns the TPair<TKey,TValue> pair with the specified Key and [WayBackremoves the returned pair from a dictionary.

If the dictionary does not contain the specified Key, the returned pair contains a default TValue.

–jeroen

5 Responses to “Delphi: updating a (potentially non-existing) item in a generic TDictionary: use ExtractPair. Except in Delphi 2010/XE.”

  1. David Heffernan said

    This is a terrible design. It means you can’t tell whether or not there was a value already in the collection. They need a TryExtract, just as we added to the spring dict.

  2. Remy said

    You don’t need to extract a pair in order to update a value. TDictionary‘s TryGetValue() method also returns a defaulted value if the key does not exist (and yes, that is documented behavior), and TDictionary also has an AddOrSetValue() method to update an existing key with a new value.

    var
      Count: Integer;
    begin
      TMonitor.Enter(FEceptionDictionary);
      try
        FEceptionDictionary.TryGetValue(ExceptObj.ClassType, Count);
        FEceptionDictionary.AddOrSetValue(ExceptObj.ClassType, Count + 1);
      finally
        TMonitor.Exit(FEceptionDictionary);
      end;
    end;
    

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

 
%d bloggers like this: