BidirectionalDictionary 3.1.3
See the version list below for details.
dotnet add package BidirectionalDictionary --version 3.1.3
NuGet\Install-Package BidirectionalDictionary -Version 3.1.3
<PackageReference Include="BidirectionalDictionary" Version="3.1.3" />
<PackageVersion Include="BidirectionalDictionary" Version="3.1.3" />
<PackageReference Include="BidirectionalDictionary" />
paket add BidirectionalDictionary --version 3.1.3
#r "nuget: BidirectionalDictionary, 3.1.3"
#:package BidirectionalDictionary@3.1.3
#addin nuget:?package=BidirectionalDictionary&version=3.1.3
#tool nuget:?package=BidirectionalDictionary&version=3.1.3
BidirectionalDictionary
Proper implementation of a bidirectional dictionary, also known as "bidirectional map" or "two-way dictionary", for .NET Standard 2.0 and higher.
Quick sample
using System.Collections.Generic;
var countryCapitals = new BidirectionalDictionary<string, string>()
{
["Italy"] = "Rome",
["India"] = "New Delhi",
["USA"] = "Washington, D.C.",
};
Console.WriteLine(countryCapitals["Italy"]); // "Rome"
Console.WriteLine(countryCapitals.Inverse["Rome"]); // "Italy"
Read-only support
You can expose a read-only view over an existing bidirectional dictionary, keeping inversion capabilities intact. The wrapper uses the same underlying data and blocks modifications through the read-only API.
From BidirectionalDictionary:
using System.Collections.Generic;
BidirectionalDictionary<Key, Value> bidirectionalDictionary = ...;
var readOnly = bidirectionalDictionary.AsReadOnly();
From IBidirectionalDictionary:
using System.Collections.Generic;
using System.Collections.ObjectModel;
IBidirectionalDictionary<Key, Value> bidirectionalDictionary = ...;
var readOnly = new ReadOnlyBidirectionalDictionary<Key, Value>(dictionary);
Thread safety
You can use ConcurrentBidirectionalDictionary for multi-threaded scenarios:
using System.Collections.Concurrent;
var countryCapitals = new ConcurrentBidirectionalDictionary<string, string>();
countryCapitals.TryAdd("Italy", "Rome");
Console.WriteLine(countryCapitals["Italy"]); // "Rome"
Console.WriteLine(countryCapitals.Inverse["Rome"]); // "Italy"
The concurrent implementation keeps read operations lock-free. Write operations use fine-grained key/value stripe locks instead of locking the whole dictionary.
Interfaces
To support abstraction-friendly code, the package exposes two interfaces:
IBidirectionalDictionaryIReadOnlyBidirectionalDictionary
BidirectionalDictionary, ReadOnlyBidirectionalDictionary, and ConcurrentBidirectionalDictionary
all implement these interfaces, so you can depend on contracts instead of concrete types when needed.
LINQ extensions
The package includes LINQ-extensions to create a BidirectionalDictionary directly from sequences.
From KeyValuePair<TKey, TValue>:
using System.Linq;
IEnumerable<KeyValuePair<int, string>> source = new[]
{
new KeyValuePair<int, string>(1, "one"),
new KeyValuePair<int, string>(2, "two")
};
var bidirectionalDictionary = source.ToBidirectionalDictionary();
From tuple sequence:
using System.Linq;
IEnumerable<(string Key, string Value)> source = new[]
{
(Key: "US", Value: "United States"),
(Key: "IT", Value: "Italy")
};
var bidirectionalDictionary = source.ToBidirectionalDictionary();
From arbitrary source with selectors:
using System.Linq;
var users = new[]
{
new { Id = 10, Email = "a@example.com" },
new { Id = 20, Email = "b@example.com" }
};
var bidirectionalDictionary = users.ToBidirectionalDictionary(user => user.Id, user => user.Email);
You can also pass custom comparers via overloads with keyComparer and valueComparer.
Benchmarks
Benchmark highlights:
- Key lookups stay close to
Dictionary<TKey, TValue>. - Reverse lookups by value are
O(1). - Additional mutation cost is the tradeoff for keeping both indexes synced.
More details can be found in benchmarks/BidirectionalDictionary.Benchmarks.
License
The library is licensed under the MIT license.
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net5.0 was computed. net5.0-windows was computed. net6.0 is compatible. net6.0-android was computed. net6.0-ios was computed. net6.0-maccatalyst was computed. net6.0-macos was computed. net6.0-tvos was computed. net6.0-windows was computed. net7.0 was computed. net7.0-android was computed. net7.0-ios was computed. net7.0-maccatalyst was computed. net7.0-macos was computed. net7.0-tvos was computed. net7.0-windows was computed. net8.0 was computed. net8.0-android was computed. net8.0-browser was computed. net8.0-ios was computed. net8.0-maccatalyst was computed. net8.0-macos was computed. net8.0-tvos was computed. net8.0-windows was computed. net9.0 is compatible. net9.0-android was computed. net9.0-browser was computed. net9.0-ios was computed. net9.0-maccatalyst was computed. net9.0-macos was computed. net9.0-tvos was computed. net9.0-windows was computed. net10.0 was computed. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
| .NET Core | netcoreapp2.0 was computed. netcoreapp2.1 was computed. netcoreapp2.2 was computed. netcoreapp3.0 was computed. netcoreapp3.1 was computed. |
| .NET Standard | netstandard2.0 is compatible. netstandard2.1 is compatible. |
| .NET Framework | net461 was computed. net462 was computed. net463 was computed. net47 was computed. net471 was computed. net472 was computed. net48 was computed. net481 was computed. |
| MonoAndroid | monoandroid was computed. |
| MonoMac | monomac was computed. |
| MonoTouch | monotouch was computed. |
| Tizen | tizen40 was computed. tizen60 was computed. |
| Xamarin.iOS | xamarinios was computed. |
| Xamarin.Mac | xamarinmac was computed. |
| Xamarin.TVOS | xamarintvos was computed. |
| Xamarin.WatchOS | xamarinwatchos was computed. |
-
.NETStandard 2.0
- No dependencies.
-
.NETStandard 2.1
- No dependencies.
-
net6.0
- No dependencies.
-
net9.0
- No dependencies.
NuGet packages (1)
Showing the top 1 NuGet packages that depend on BidirectionalDictionary:
| Package | Downloads |
|---|---|
|
Scover.Dialogs
A Windows TaskDialog wrapper that also supports navigation and hyperlinks. |
GitHub repositories (1)
Showing the top 1 popular GitHub repositories that depend on BidirectionalDictionary:
| Repository | Stars |
|---|---|
|
dotnet/XAMLStudio
XAML Studio is a rapid prototyping tool for WinUI-based XAML that can then be easily copied into Visual Studio!
|
| Version | Downloads | Last Updated |
|---|---|---|
| 3.1.4 | 48 | 5/22/2026 |
| 3.1.3 | 178 | 5/17/2026 |
| 3.1.2 | 103 | 5/16/2026 |
| 3.1.1 | 155 | 5/13/2026 |
| 3.1.0 | 97 | 5/12/2026 |
| 3.0.0 | 130 | 5/6/2026 |
| 2.0.2 | 86 | 5/17/2026 |
| 2.0.1 | 85 | 5/6/2026 |
| 2.0.0 | 1,241 | 4/9/2026 |
| 1.4.2 | 89 | 5/17/2026 |
| 1.4.1 | 94 | 5/6/2026 |
| 1.4.0 | 353 | 3/9/2026 |
| 1.3.0 | 34,555 | 8/11/2023 |
| 1.2.0 | 921 | 3/17/2023 |
| 1.1.1 | 1,653 | 8/27/2022 |
| 1.1.0 | 829 | 8/26/2022 |
| 1.0.1 | 630 | 8/24/2022 |
| 1.0.0 | 644 | 8/24/2022 |