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&lt;T&gt; 在这种情况下不会是协变的。

以上是关于IComparer<> 和 C# 中的类继承的主要内容,如果未能解决你的问题,请参考以下文章

C# 重写IComparer 接口

C#中的IComparable和IComparer接口

C#中的IComparable和IComparer接口

[译]在C#中使用IComparable和IComparer接口

C#接口汇总

C#接口汇总