我们有一个C#库类,它继承自List但由于List.Contains很慢而很慢。我们无法将类更改为继承自Dictionary或HashSet之类的其他类,因为许多客户端代码依赖于此类,并且它太过涉及更改接口。有没有一种简单的方法来加速这种方法而不改变它?有些列表非常大,所以我们不希望在内存中有两个副本。我们也不想覆盖List的每个方法。
public class UniqueList<T> : List<T>, IList<T>
{
public new void Add(T item)
{
if (!this.Contains(item) && item != null)
{
base.Add(item);
}
}
答案 0 :(得分:2)
继承List是一个非常糟糕的主意,因为您无法控制客户端代码如何使用您的类
List.Contains是 O(n)操作。 Dictionary.ContainsKey是一个 O(1),所以我认为使用Dictionary是给出的最佳建议,但如果你真的不想使用它,另一种可能性是保持列表排序为获得 O(log n)
public void Add(T item)
{
int index = BinarySearch(item);
if (index < 0)
{
Insert(~index, item);
}
}
如果元素已经在列表中,BinarySearch将返回其索引。 如果元素不在列表中,则BinarySearch方法返回一个负数,它是第一个元素的索引的二进制补码,该索引大于我传递给二分搜索方法的元素。
在您的方案中可能无法使用BinarySearch,因为它取决于T可以是什么: http://msdn.microsoft.com/en-us/library/w4e7fxsh.aspx
此方法使用类型T的默认比较器Comparer.Default来确定列表元素的顺序。 Comparer.Default属性检查类型T是否实现IComparable通用接口并使用该实现(如果可用)。如果不是,Comparer.Default检查类型T是否实现IComparable接口。如果类型T没有实现任何一个接口,Comparer.Default会抛出InvalidOperationException。
答案 1 :(得分:2)
简而言之。
因为你继承自List<>
,你实际上是搞砸了,因为即使你对Contains方法有影响,你也无法阻止客户端代码将UniqueList
传递给接受的方法List<>
,这将隐藏您的新包含,并使用现有的包含。
您需要以困难的方式解决此问题,删除List<>
上的继承,实现您自己的包含,从列表中重新实现您需要的任何方法(在内部您可以使用private List<>
进行存储,并在必要时委托给那个,并修复此更改中断的所有代码。
当你破坏事物的时候,你可以看一下C5集合类,这些类可以促进对接口的开发,帮助你解决这个问题(我知道,在马拴住之后更多关闭谷仓门)< / p>
我知道这不是你要找的答案,但你不会得到你想要的答案(实际上没有办法解决这个问题,你可以试试Castle Interceptors之类的东西,但我不认为他们会在这种情况下工作......但是我不能确定他们不会这样做。
再次,对于无法真正帮助而道歉。
答案 2 :(得分:0)
你可以拥有一个类级别的私有字典并首先检查字典,如果它没有在字典中找到然后转到列表并检查,它只是一个优化它不是纯粹的解决方案,并且还要花费额外的内存< / p>