IComparer<> 和 C# 中的类继承
Posted
技术标签:
【中文标题】IComparer<> 和 C# 中的类继承【英文标题】:IComparer<> and class inheritance in C# 【发布时间】:2011-07-07 06:24:56 【问题描述】:有没有办法为基类类型实现专门的 IComparer,以便子类仍然可以使用它在特定集合中进行排序?
例子
public class A
public int X;
public class B:A
public int Y;
public AComparer:IComparer<A>
int Compare(A p1, A p2)
//...
所以下面的代码可以工作:
List<A> aList = new List<A>();
aList.Sort(new AComparer());
List<B> bList = new List<B>();
bList.Sort(new AComparer()); // <- this line fails due to type cast issues
如何解决这个问题以同时具有排序和专用集合的继承(并且不为每个子类复制 IComparer 类?
提前致谢!
【问题讨论】:
【参考方案1】:首先,请注意,这在 .NET 4 中已通过 通用逆变 得到修复 - 您的代码可以正常工作。编辑:如 cmets 中所述,CLR v2 中首先支持泛型变量,但各种接口和委托仅在 .NET 4 中变得协变或逆变。
但是,在 .NET 2 中创建转换器仍然相当容易:
public class ComparerConverter<TBase, TChild> : IComparer<TChild>
where TChild : TBase
private readonly IComparer<TBase> comparer;
public ComparerConverter(IComparer<TBase> comparer)
this.comparer = comparer;
public int Compare(TChild x, TChild y)
return comparer.Compare(x, y);
然后您可以使用:
List<B> bList = new List<B>();
IComparer<B> bComparer = new ComparerConverter<A, B>(new AComparer());
bList.Sort(bComparer);
编辑:如果不改变调用它的方式,您将无能为力。不过,您可能会使您的 AComparer
通用:
public class AComparer<T> : IComparer<T> where T : A
int Compare(T p1, T p2)
// You can still access members of A here
那么你可以使用:
bList.Sort(new AComparer<B>());
当然,这意味着让所有的比较器实现通用化,这有点难看 IMO。
【讨论】:
效果很好,但问题是它将执行委托给基类比较器,但仍然改变了调用方式。如果没有更好的方法,我将遵循此方法。不幸的是我不能使用 .NET 4.0 @Random:我添加了另一个选项。 非常感谢。这两种方法都非常有用,而且都很丑:) 我将坚持第一种选择,并让我的课程负责公开比较器(在 MSDN 上找到的实践)。这就是我至少将为其他开发人员获得通用实现方式的方式。 @JonSkeet 是 .NET 4 的通用逆变功能吗?我猜它会是 C#.. @nawfal:通用协方差是 CLR v2、C# v4 的一个特性,并在 .NET 4 的框架库中引入。我没有尝试过,但我认为它应该 可以在使用(比如)VS2010 并以 .NET 2 为目标时引入您自己的变体接口/委托......但IEnumerable<T>
在这种情况下不会是协变的。以上是关于IComparer<> 和 C# 中的类继承的主要内容,如果未能解决你的问题,请参考以下文章