我正在编写bijective dictionary class,但我想确保这两种泛型不是同一类型,原因有两个。
首先,我希望它在两个方向上实现IDictionary
接口,但是
public class BijectiveDictionary<TKey, TValue>
: IDictionary<TKey, TValue>, IDictionary<TValue, TKey>
给我“'BijectiveDictionary&lt; TKey,TValue&gt;'无法实现'IDictionary&lt; TKey,TValue&gt;'和'IDictionary&lt; TValue,TKey&gt;'因为它们可能统一某些类型参数替换“(这是可以理解的,但不可取的。)
其次,如果两种类型相同,我想写一个优化的解决方案。
public class BijectiveDictionary<TKey, TValue>
: IDictionary<TKey, TValue> where TValue : TKey
{
// Optimized solution
}
public class BijectiveDictionary<TKey, TValue>
: IDictionary<TKey, TValue>, IDictionary<TValue, TKey> where TValue : !TKey
{
// Standard solution
}
这可能吗?
如果没有,我可以考虑不实施IDictionary
,但我不能保证TValue this[TKey key]
和TKey this[TValue key]
会有所不同,这是不幸的。
这里的问题似乎是当两种类型相同时,会出现特殊情况。
我最初的意图是创建一个字典,将一个键恰好映射到一个值,反之亦然,这样每KeyValuePair<TKey, TValue>(X, Y)
个KeyValuePair<TValue, TKey>(Y, X)
也存在。{/ p>
当TKey
= TValue
时,这可以简化为单个词典:
public T this[T key]
{
get { return this[key]; }
set
{
base.Add(key, value);
base.Add(value, key);
}
}
在这种情况下,您不能Add(2,3); Add(3,4)
,因为Add(2,3)
也会将3
映射到2
,而[3]
会返回2
。< / p>
但是,Jaroslav Jandek's solution建议使用第二个词典为TKey
!= TValue
的情况执行此操作。虽然这对于那些情况非常有用,(以及最终我决定实施的内容)但TKey
= TValue
时,Add(2,3); Add(3,4)
= 3
并不完全符合我原来的意图将单个键2
映射到两个值(4
在一个方向上,{{1}}在另一个方向上,但我认为严格来说仍然是一个有效的双射函数。
答案 0 :(得分:3)
这个(不同方法)怎么样:
public class BijectiveDictionary<TKey, TValue> : Dictionary<TKey, TValue>
{
public BijectiveDictionary<TValue, TKey> Reversed { get; protected set; }
public BijectiveDictionary()
{
this.Reversed = new BijectiveDictionary<TValue,TKey>(true);
this.Reversed.Reversed = this;
}
protected BijectiveDictionary(bool reversedWillBeSetFromTheCallingBiji) { }
protected void AddRaw(TKey key, TValue value)
{
base.Add(key, value);
}
// Just for demonstration - you should implement the IDictionary interface instead.
public new void Add(TKey key, TValue value)
{
base.Add(key, value);
this.Reversed.AddRaw(value, key);
}
public static explicit operator BijectiveDictionary<TValue, TKey>(BijectiveDictionary<TKey, TValue> biji)
{
return biji.Reversed;
}
}
并在代码中:
BijectiveDictionary<int, bool> a = new BijectiveDictionary<int, bool>();
a.Add(5, true);
a.Add(6, false);
Console.WriteLine(a[5]);// => True
Console.WriteLine(((BijectiveDictionary < bool, int>)a)[true]);// => 5
//or
Console.WriteLine(a.Reversed[true]);// => 5
答案 1 :(得分:2)
简而言之,没有。重新优化它,一个选项可能是基于静态初始化程序的策略,为相同类型的情况选择适当的具体实现,否则;即。
public class BijectiveDictionary<TKey, TValue>
: IDictionary<TKey, TValue>
{
static readonly ISomeStrategy strategy;
static BijectiveDictionary() {
if(typeof(TKey) == typeof(TValue)) {
strategy = ...
} else {
strategy = ...
}
}
}
但你几乎肯定会发现自己使用MakeGenericType
和反射来创建实例(但是一旦创建它应该没问题 - 而且你只做了一次)。
答案 2 :(得分:2)
在某种程度上,这可以做到!我使用差异化方法,而不是限制类型的限定符。
它没有统一,事实上它可能比它更好,因为你可以分开挑逗单独的接口。
在此处查看我的帖子,在另一个上下文中提供完整的工作示例。 https://stackoverflow.com/a/12361409/471129
基本上,您要做的是向IIndexer
添加另一个类型参数,使其成为IIndexer <TKey, TValue, TDifferentiator>
。
然后当你使用它两次时,你将“First”传递给第一次使用,将第二次传递给第二次使用
因此,课程测试成为:class Test<TKey, TValue> : IIndexer<TKey, TValue, First>, IIndexer<TValue, TKey, Second>
因此,您可以new Test<int,int>()
第一和第二是微不足道的:
interface First { }
interface Second { }
答案 3 :(得分:-1)
即使你可以,这段代码的输出是什么?
var dict = new BijectiveDictionary<int, int>();
dict.Add(2,3);
dict.Add(3,4);
Console.WriteLine(dict[3]); // Do I get 2 or 4?
也许你可以用另一种不模糊的方式重构你的代码?