{"id":21916915,"url":"https://github.com/bemobolo/bem.collections.weakdictionary","last_synced_at":"2025-03-22T09:41:18.055Z","repository":{"id":205299334,"uuid":"567175891","full_name":"bemobolo/Bem.Collections.WeakDictionary","owner":"bemobolo","description":"WeakDictionary using weak keys with the ability to use custom IEqualityComparer on them","archived":false,"fork":false,"pushed_at":"2023-11-03T19:43:50.000Z","size":43,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-01-27T09:29:39.025Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"C#","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"gpl-3.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/bemobolo.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2022-11-17T08:28:49.000Z","updated_at":"2023-11-06T10:00:42.000Z","dependencies_parsed_at":null,"dependency_job_id":"9f42b964-a73b-42c2-ad5a-a027704152df","html_url":"https://github.com/bemobolo/Bem.Collections.WeakDictionary","commit_stats":null,"previous_names":["bemobolo/bem.collections.weakdictionary"],"tags_count":2,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bemobolo%2FBem.Collections.WeakDictionary","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bemobolo%2FBem.Collections.WeakDictionary/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bemobolo%2FBem.Collections.WeakDictionary/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bemobolo%2FBem.Collections.WeakDictionary/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/bemobolo","download_url":"https://codeload.github.com/bemobolo/Bem.Collections.WeakDictionary/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":244937740,"owners_count":20535124,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-11-28T19:21:42.542Z","updated_at":"2025-03-22T09:41:18.035Z","avatar_url":"https://github.com/bemobolo.png","language":"C#","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Bem.Collections.WeakDictionary\n![Nuget (with prereleases)](https://img.shields.io/nuget/v/Bem.Collections.WeakDictionary)\n![GitHub release (latest by date)](https://img.shields.io/github/v/release/bemobolo/Bem.Collections.WeakDictionary)\n![Azure DevOps builds (branch)](https://img.shields.io/azure-devops/build/dbalogh/Bem.Collections.WeakDictionary/17/main)\n![Azure DevOps tests](http://bemobolo.ddns.net/azure-devops/tests/dbalogh/Bem.Collections.WeakDictionary/17/main?compact_message)\n![Azure DevOps coverage (branch)](http://bemobolo.ddns.net/azure-devops/coverage/dbalogh/Bem.Collections.WeakDictionary/17/main)\n# Overview\nA thread-safe dictionary implementation that stores values with weekly referenced keys. See [`WeakReference\u003cT\u003e`](https://learn.microsoft.com/en-us/dotnet/api/system.weakreference-1).  \nOnce a key is not strong-referenced anymore the entry will be removed automatically from `WeakDictionary\u003cTKey,TValue\u003e`.  \nThis collection can be used for similar purposes as [`ConditionalWeakTable\u003cTKey,TValue\u003e`](https://learn.microsoft.com/en-us/dotnet/api/system.runtime.compilerservices.conditionalweaktable-2) except that `WeakDictionary\u003cTKey,TValue\u003e` can accept custom [`IEqualityComparer\u003cT\u003e`](https://learn.microsoft.com/en-us/dotnet/api/system.collections.generic.iequalitycomparer-1) instance for key comparison. [`ConditionalWeakTable\u003cTKey,TValue\u003e`](https://learn.microsoft.com/en-us/dotnet/api/system.runtime.compilerservices.conditionalweaktable-2) can only compare keys by reference no matter if [`GetHashCode()`](https://learn.microsoft.com/en-us/dotnet/api/system.object.gethashcode) and [`Equals()`](https://learn.microsoft.com/en-us/dotnet/api/system.object.equals) methods are overridden or not.  \nInternally `WeakDictionary\u003cTKey,TValue\u003e` uses a combination of [`Dictionary\u003cTKey,TValue\u003e`](https://learn.microsoft.com/en-us/dotnet/api/system.collections.generic.dictionary-2) and [`ConditionalWeakTable\u003cTKey,TValue\u003e`](https://learn.microsoft.com/en-us/dotnet/api/system.runtime.compilerservices.conditionalweaktable-2) types to manage entries.\n# Usage\nUse the same way as a generic [`Dictionary\u003cTKey,TValue\u003e`](https://learn.microsoft.com/en-us/dotnet/api/system.collections.generic.dictionary-2).  \n\n```csharp\nvar dictionary = new WeakDictionary\u003cMyReferenceType, AnyType\u003e(optionalEqualityComparer);\n```\nNote that `WeakDictionary\u003cTKey,TValue\u003e` implements only [`IDictionary\u003cTKey,TValue\u003e`](https://learn.microsoft.com/en-us/dotnet/api/system.collections.generic), [`IEnumerable\u003cT\u003e`](https://learn.microsoft.com/en-us/dotnet/api/system.collections.generic.ienumerable-1) and [`IEnumerable`](https://learn.microsoft.com/en-us/dotnet/api/system.collections.ienumerable) interfaces.  \nNote that `TKey` must be reference type, but `TValue` can be anything you want.  \n**Also note that `TValue` by default is not stored as a [`WeakReference\u003cT\u003e`](https://learn.microsoft.com/en-us/dotnet/api/system.weakreference-1). Therefore if key and value reference the same object GC can not collect the instance!**  \nConsider this if you plan to use `WeakDictionary\u003cTKey,TValue\u003e` as a [`HashSet\u003cT\u003e`](https://learn.microsoft.com/en-us/dotnet/api/system.collections.generic.hashset-1) and avoid using the same instance for key and value.  \n## Use Cases\nThe single use case of this library is when you need to use a custom [`IEqualityComparer\u003cT\u003e`](https://learn.microsoft.com/en-us/dotnet/api/system.collections.generic.iequalitycomparer-1) for the weakly referenced keys. If this is not a requirement use the [`ConditionalWeakTable\u003cTKey,Tvalue\u003e`](https://learn.microsoft.com/en-us/dotnet/api/system.runtime.compilerservices.conditionalweaktable-2) instead.\n# Thread Safety\nAll public and protected members of `WeakDictionary\u003cTKey,TValue\u003e` are thread-safe and may be used concurrently from multiple threads. However, members accessed through one of the interfaces the `WeakDictionary\u003cTKey,TValue\u003e` implements, including extension methods, are not guaranteed to be thread safe and may need to be synchronized by the caller.  \n\n# Benchmarks\nThe below results show that `WeakDictionary\u003cTKey,TValue\u003e` has some performance cost compared to the other data structures probably because of all the locks surrounding the logic of the internal data structure mutations.\n\n\n## Runtime=.NET 7.0\n### Populating\n|                   Method |      N |      Mean |      Error |   StdDev | Ratio | RatioSD |\n|------------------------- |------- |----------:|-----------:|---------:|------:|--------:|\n|       WeakDictionary_Add | 100000 | 217.97 ms | 117.891 ms | 6.462 ms |  4.56 |    1.12 |\n| ConcurrentDictionary_Add | 100000 |  49.66 ms |   9.680 ms | 0.531 ms |  1.04 |    0.24 |\n|           Dictionary_Add | 100000 |  18.18 ms |  47.396 ms | 2.598 ms |  0.37 |    0.07 |\n| ConditionalWeakTable_Add | 100000 |  49.44 ms | 177.786 ms | 9.745 ms |  1.00 |    0.00 |\n### Getting items\n|                           Method |      N |     Mean |    Error |   StdDev | Ratio | RatioSD |\n|--------------------------------- |------- |---------:|---------:|---------:|------:|--------:|\n|       WeakDictionary_TryGetValue | 100000 | 71.26 ms | 48.43 ms | 2.655 ms |  2.09 |    0.27 |\n| ConcurrentDictionary_TryGetValue | 100000 | 12.10 ms | 36.76 ms | 2.015 ms |  0.35 |    0.04 |\n|           Dictionary_TryGetValue | 100000 | 20.75 ms | 31.57 ms | 1.730 ms |  0.61 |    0.09 |\n| ConditionalWeakTable_TryGetValue | 100000 | 34.57 ms | 89.00 ms | 4.879 ms |  1.00 |    0.00 |\n### Updating items\n|                   Method |      N |      Mean |     Error |    StdDev | Ratio | RatioSD |\n|------------------------- |------- |----------:|----------:|----------:|------:|--------:|\n|       WeakDictionary_Set | 100000 | 378.94 ms | 746.94 ms | 40.942 ms | 18.87 |    0.79 |\n| ConcurrentDictionary_Set | 100000 |  26.72 ms |  32.10 ms |  1.759 ms |  1.33 |    0.04 |\n|           Dictionary_Set | 100000 |  22.34 ms |  17.56 ms |  0.963 ms |  1.12 |    0.14 |\n| ConditionalWeakTable_Set | 100000 |  20.07 ms |  33.44 ms |  1.833 ms |  1.00 |    0.00 |\n### Removing items\n|                      Method |      N |      Mean |     Error |    StdDev | Ratio | RatioSD |\n|---------------------------- |------- |----------:|----------:|----------:|------:|--------:|\n|       WeakDictionary_Remove | 100000 | 130.70 ms | 262.21 ms | 14.373 ms |  8.85 |    3.03 |\n| ConcurrentDictionary_Remove | 100000 |  23.11 ms |  38.31 ms |  2.100 ms |  1.53 |    0.26 |\n|           Dictionary_Remove | 100000 |  14.89 ms |  39.01 ms |  2.138 ms |  0.99 |    0.22 |\n| ConditionalWeakTable_Remove | 100000 |  15.49 ms |  59.07 ms |  3.238 ms |  1.00 |    0.00 |\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbemobolo%2Fbem.collections.weakdictionary","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fbemobolo%2Fbem.collections.weakdictionary","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbemobolo%2Fbem.collections.weakdictionary/lists"}