Dla wewnętrznych puppies napisałem BiDictionary
. Nie jest to kuloodporne, ponieważ nie ujawniam go użytkownikowi, więc działa dobrze dla mnie. Pozwala mi uzyskać klucz, tak jak ja potrzebuję.
Konieczne jest, aby KeyPair<,>
móc wdrożyć metodę IEnumerable<,>
, a tym samym Add
, abyśmy mogli korzystać z inicjalizatora obiektu.
internal class KeyPair<TKey1, TKey2>
{
public TKey1 Key1 { get; set; }
public TKey2 Key2 { get; set; }
}
Jest to główny klasy jako dynamiczny obiektu tak, że przy pobieraniu wartości możemy użyć nazwy klawiszy od niego:
internal class BiDictionary<TKey1, TKey2> : DynamicObject, IEnumerable<KeyPair<TKey1, TKey2>>
{
private readonly Dictionary<TKey1, TKey2> _K1K2 = new Dictionary<TKey1, TKey2>();
private readonly Dictionary<TKey2, TKey1> _K2K1 = new Dictionary<TKey2, TKey1>();
private readonly string _key1Name;
private readonly string _key2Name;
public BiDictionary(string key1Name, string key2Name)
{
_key1Name = key1Name;
_key2Name = key2Name;
}
public override bool TryGetMember(GetMemberBinder binder, out object result)
{
if (binder.Name == _key1Name)
{
result = _K1K2;
return true;
}
if (binder.Name == _key2Name)
{
result = _K2K1;
return true;
}
result = null;
return false;
}
public void Add(TKey1 key1, TKey2 key2)
{
_K1K2.Add(key1, key2);
_K2K1.Add(key2, key1);
}
public IEnumerator<KeyPair<TKey1, TKey2>> GetEnumerator()
{
return _K1K2.Zip(_K2K1, (d1, d2) => new KeyPair<TKey1, TKey2>
{
Key1 = d1.Key,
Key2 = d2.Key
}).GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
}
Przykład:
dynamic bidic = new BiDictionary<string, string>("Key1", "Key2")
{
{ "foo", "bar" },
{ "baz", "qux" }
};
var bar = bidic.Key1["foo"];
var foo = bidic.Key2["bar"];
Mogą zsynchronizować, jeśli zmodyfikujesz dowolny ze słowników na zewnątrz. W tym celu używam ObservableDictionary
, dzięki czemu mogę zaktualizować drugi, jeśli się zmieni, ale dla uproszczenia usunąłem tę część kodu, aby zdemontować główną logikę.
Wprowadź wartość części klucza. –
Nie ma takiej klasy w .NET Framework. Ale możesz łatwo skonstruować jeden ze Słownika i HashSet lub dwa Słowniki. – dtb
@Robert Harvey: jeśli to zrobi, nie może już "d [1]", co pokonuje cel Słownika. Może również użyć HashSet <> –