我从来没有用默认构造函数编写过有状态的IComparer<T>。我在Reflector中检查过的所有标准库实现也都是无状态的。因此,我假设我可以像这样自由地缓存IComparer<T>:
PriorityQueue<TPriority, TComparer> where TComparer : IComparer<TPriority>, new()
{
private static TComparer _comparer = new TComparer();
public PriorityQueue() {...}
...
}而不是
PriorityQueue<TPriority>
{
private IComparer<TPriority> _comparer;
public PriorityQueue(IComparer<TPriority> comparer) {
_comparer = comparer;
...
}
...
}所以这里有一个问题:你有没有写过/见过这样的IComparer<T>会崩溃?如果是,这种情况有多普遍?
编辑:在这种情况下,我真的不想要第二个版本的开销的原因是它的数据结构是持久的。它被实现为一个树,其中的节点没有父/根引用。所以它不会是每个队列对比较器的一个引用,而是每个节点对比较器的一个引用!我最初的设计只是为了使用IComparable<T>,并推荐编写一个包装器结构来进行自定义比较。
发布于 2009-07-21 21:25:12
嗯,拥有一个静态比较器意味着你不能在不同的队列上进行不同的比较;这可能是一个问题……有时,人们确实需要一个自定义比较;例如,如果他们不能控制类型。我的默认方法是:
PriorityQueue<TPriority>
{
private IComparer<TPriority> _comparer;
public PriorityQueue(IComparer<TPriority> comparer) {
_comparer = comparer;
...
}
public PriorityQueue() : this(Comparer<T>.Default) {}
}Re状态比较器;是的,我已经写了几个--特别是为了编写LINQ风格的投影比较器……例如,如下所示:
public static class ProjectionComparer<TSource>
{
public static IComparer<TSource> CompareBy<TValue>(
Func<TSource, TValue> selector)
{
return CompareBy<TValue>(selector, Comparer<TValue>.Default);
}
public static IComparer<TSource> CompareBy<TValue>(
Func<TSource, TValue> selector,
IComparer<TValue> comparer)
{
return new ProjectionComparerItem<TValue>(
selector, Comparer<TValue>.Default);
}
class ProjectionComparerItem<TValue> : IComparer<TSource>
{
private readonly IComparer<TValue> comparer;
private readonly Func<TSource, TValue> selector;
public ProjectionComparerItem(
Func<TSource, TValue> selector,
IComparer<TValue> comparer)
{
this.selector = selector;
this.comparer = comparer;
}
public int Compare(TSource x, TSource y)
{
// TODO: some null stuff...
return comparer.Compare(selector(x), selector(y));
}
}
}这允许:
IComparer<Customer> comparer = ProjectionComparer<Customer>
.CompareBy(cust => cust.Name);实例“按名称排序”比较。
发布于 2009-07-21 21:23:51
是的,我有,但我认为这是相当不常见的。
在极少数情况下,您希望实现依赖于其他数据的比较。例如,我们有一些空间例程,其中我们提供了一个轴,作为IComparer的一部分用于比较。
也就是说,只需使用一个单独的比较器类就可以很容易地解决这个问题,而且在许多方面这可能是一个更好的设计。但是,您对确实需要存在的IComparer<T>实现进行了限制,因此我将记录您的理由。
我个人的偏好是让IComparer<T>成为非静态的,并提供两个构造函数-一个接受外部实例,另一个创建默认比较器。每个队列都有一个比较器的额外开销,但这是非常小的(如果没有状态,则几乎为0,因为它只是对“空”对象的单个对象引用)。
发布于 2009-07-31 12:56:47
另一种可能的方法是:
private class PriorityQueueImpl<TPriority, TComparer> where TComparer : IComparer<TPriority> {
// all methods accept a TComparer
// generic in TComparer to avoid boxing for struct TComparers and permit inlining for sealed TComparers
}
public struct PriorityQueue<TPriority, TComparer> where TComparer : IComparer<TPriority> {
private readonly PriorityQueueImpl<TPriority, TComparer> _impl;
private readonly TComparer _comparer;
// methods delegate to _impl
}至少在某些情况下,我可能会使用它。
https://stackoverflow.com/questions/1161811
复制相似问题