我需要一个更健壮的字典式结构来获取:
此外,我想扩展这种类字典结构的功能,以便键可以与多个值相关联。
通过this讨论,this回答和this other one提供了实施该工具的工具。我决定从BiDictionary(Jon Skeet的答案)中删除“按索引访问”,因为模糊性会比我想要的更频繁(例如,将字符串映射到字符串时)。我想出的字典式“结构”是:
using System.Collections.Generic;
public interface IBiLookup<TLeft, TRight>
{
IDictionary<TLeft, ICollection<TRight>> LeftToRight { get; }
IDictionary<TRight, ICollection<TLeft>> RightToLeft { get; }
bool TryGetByLeft(TLeft left, out ICollection<TRight> rights);
bool TryGetByRight(TRight right, out ICollection<TLeft> lefts);
void Add(TLeft left, TRight right);
}
public class BiLookup<TLeft, TRight> : IBiLookup<TLeft, TRight>
{
public IDictionary<TLeft, ICollection<TRight>> LeftToRight
{
get { return this.leftToRight; }
}
public IDictionary<TRight, ICollection<TLeft>> RightToLeft
{
get { return this.rightToLeft; }
}
public bool TryGetByLeft(TLeft left, out ICollection<TRight> rights)
{
return LeftToRight.TryGetValue(left, out rights);
}
public bool TryGetByRight(TRight right, out ICollection<TLeft> lefts)
{
return RightToLeft.TryGetValue(right, out lefts);
}
public void Add(TLeft left, TRight right)
{
AddLeftToRight(left, right);
AddRightToLeft(right, left);
}
private void AddLeftToRight(TLeft left, TRight right)
{
ICollection<TRight> rights;
// 1) Is there an entry associated with the "left" value?
// 2) If so, is the "right" value already associated?
if (!TryGetByLeft(left, out rights))
{
// Then we have to add an entry in the leftToRight dictionary.
rights = new List<TRight> { right };
}
else
{
// So there are entries associated with the "left" value.
// We must verify if the "right" value itself is not there.
if (((List<TRight>)rights).FindIndex(element => element.Equals(right)) < 0)
{
// We don't have that association yet.
rights.Add(right);
}
else
{
// The value is already in the list: do nothing.
return;
}
}
LeftToRight[left] = rights;
}
private void AddRightToLeft(TRight right, TLeft left)
{
ICollection<TLeft> lefts;
// 1) Is there an entry associated with the "right" value?
// 2) If so, is the "left" value already associated?
if (!TryGetByRight(right, out lefts))
{
// Then we have to add an entry in the leftToRight dictionary.
lefts = new List<TLeft> { left };
}
else
{
// So there are entries associated with the "right" value.
// We must verify if the "right" value itself is not there.
if (((List<TLeft>)lefts).FindIndex(element => element.Equals(left)) < 0)
{
// We don't have that association yet.
lefts.Add(left);
}
else
{
// The value is already in the list: do nothing.
return;
}
}
RightToLeft[right] = lefts;
}
#region Fields
private IDictionary<TLeft, ICollection<TRight>> leftToRight = new Dictionary<TLeft, ICollection<TRight>>();
private IDictionary<TRight, ICollection<TLeft>> rightToLeft = new Dictionary<TRight, ICollection<TLeft>>();
#endregion
}
我担心将Add(...)方法拆分为两个更具体的方法是一个很好的实现,因为BiLookup类将被广泛使用,并且要记住性能。此外,此线程的目的是讨论接口和类实现是否尽可能好,或者可以对它们进行改进。
如果我将Interface和“deafult”实现同时保存到类库项目中,那么设计是否足以重用?
答案 0 :(得分:0)
在没有实际使用它的情况下,无法确定“设计是否足以重复使用”。您需要尝试以几种不同的方式使用您的代码(所有单元测试都算作一个)以查看它是否有意义并鼓励编写可读代码。
如果您没有任何特定要求(性能或其他方面),只需确保代码的单元测试覆盖率良好,所有测试都通过,测试将涵盖您的预期使用方案。
关于代码的注释:强制转换(即((List<TLeft>)lefts)
)看起来是不必要的。 FindIndex
次调用(使用O(number_of_items)进行线性搜索)不会在性能敏感代码中查看主页。