具有唯一键和值的C#字典类型

我想知道C#中是否有内置类型,就像’Dictionary’,但TKey和TValue都必须是唯一的。

例如::

d.Add(1, "1"); d.Add(2, "1"); // This would not be OK because "1" has already been used as a value. 

我知道这有点奇特,但似乎因为BCL中有大约10亿个集合类型,它可能存在。 有任何想法吗?

如何使用Dictionary和HashSet / secondary reverse Dictionary – 它将解决问题,并且比单个Dictionary上的检查表现更好。

像这样的东西,包装成类:

 HashSet secondary = new HashSet(/*StringComparer.InvariantCultureIgnoreCase*/); Dictionarydictionary = new Dictionary(); object syncer = new object(); public override void Add(int key, string value) { lock(syncer) { if(dictionary.ContainsKey(key)) { throw new Exception("Key already exists"); } if(secondary.Add(value) { throw new Exception("Value already exists"); } dictionary.Add(key, value); } } 

对于内部目的,我写了一个BiDictionary 。 它不是防弹的我不会将它暴露给用户所以它对我来说工作正常。 它允许我获得任何一个键,因为我需要。

KeyPair<,>必须能够实现IEnumerable<,> ,从而实现Add方法,以便我们可以使用对象初始化器。

 internal class KeyPair { public TKey1 Key1 { get; set; } public TKey2 Key2 { get; set; } } 

这是作为动态对象的主类,以便在检索值时可以在其上使用键名:

 internal class BiDictionary : DynamicObject, IEnumerable> { private readonly Dictionary _K1K2 = new Dictionary(); private readonly Dictionary _K2K1 = new Dictionary(); 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> GetEnumerator() { return _K1K2.Zip(_K2K1, (d1, d2) => new KeyPair { Key1 = d1.Key, Key2 = d2.Key }).GetEnumerator(); } IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } } 

例:

 dynamic bidic = new BiDictionary("Key1", "Key2") { { "foo", "bar" }, { "baz", "qux" } }; var bar = bidic.Key1["foo"]; var foo = bidic.Key2["bar"]; 

如果您修改外部的任何字典,它们可能会不同步。 为此,我使用ObservableDictionary以便我可以更新另一个,如果一个更改,但为了简单起见,我删除了这部分代码,只是说明主逻辑。

这里有一个项目有这样的类型。 它被称为PairDictionary,它工作得很好。 不是最好的答案,但对于需要那个定制课程的人来说。

我通过将数据存储为Dictionary>来解决了这个问题。 如果您想要一个具有2个主键的值,可以用另一个Dictionary替换HashSet。

 Dictionary> _myUniquePairOfIntegerKeys; // OR Dictionary> _myUniquePairOfStringKeysWithABooleanValue;