<PackageReference Include="Newtonsoft.Json" Version="13.0.2" />

BidirectionalDictionary<TFirst, TSecond>

class BidirectionalDictionary<TFirst, TSecond>
using System; using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; using System.Globalization; using System.Runtime.CompilerServices; namespace Newtonsoft.Json.Utilities { [System.Runtime.CompilerServices.NullableContext(1)] [System.Runtime.CompilerServices.Nullable(0)] internal class BidirectionalDictionary<TFirst, TSecond> { private readonly IDictionary<TFirst, TSecond> _firstToSecond; private readonly IDictionary<TSecond, TFirst> _secondToFirst; private readonly string _duplicateFirstErrorMessage; private readonly string _duplicateSecondErrorMessage; public BidirectionalDictionary() : this((IEqualityComparer<TFirst>)EqualityComparer<TFirst>.Default, (IEqualityComparer<TSecond>)EqualityComparer<TSecond>.Default) { } public BidirectionalDictionary(IEqualityComparer<TFirst> firstEqualityComparer, IEqualityComparer<TSecond> secondEqualityComparer) : this(firstEqualityComparer, secondEqualityComparer, "Duplicate item already exists for '{0}'.", "Duplicate item already exists for '{0}'.") { } public BidirectionalDictionary(IEqualityComparer<TFirst> firstEqualityComparer, IEqualityComparer<TSecond> secondEqualityComparer, string duplicateFirstErrorMessage, string duplicateSecondErrorMessage) { _firstToSecond = new Dictionary<TFirst, TSecond>(firstEqualityComparer); _secondToFirst = new Dictionary<TSecond, TFirst>(secondEqualityComparer); _duplicateFirstErrorMessage = duplicateFirstErrorMessage; _duplicateSecondErrorMessage = duplicateSecondErrorMessage; } public void Set(TFirst first, TSecond second) { if (_firstToSecond.TryGetValue(first, out TSecond value) && !value.Equals(second)) throw new ArgumentException(_duplicateFirstErrorMessage.FormatWith(CultureInfo.InvariantCulture, first)); if (_secondToFirst.TryGetValue(second, out TFirst value2) && !value2.Equals(first)) throw new ArgumentException(_duplicateSecondErrorMessage.FormatWith(CultureInfo.InvariantCulture, second)); _firstToSecond.Add(first, second); _secondToFirst.Add(second, first); } public bool TryGetByFirst(TFirst first, [System.Runtime.CompilerServices.Nullable(2)] [System.Diagnostics.CodeAnalysis.NotNullWhen(true)] out TSecond second) { return _firstToSecond.TryGetValue(first, out second); } public bool TryGetBySecond(TSecond second, [System.Runtime.CompilerServices.Nullable(2)] [System.Diagnostics.CodeAnalysis.NotNullWhen(true)] out TFirst first) { return _secondToFirst.TryGetValue(second, out first); } } }