【问题标题】:IComparer<> and class inheritance in C#IComparer<> 和 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 类?

提前致谢!

【问题讨论】:

    标签: collections .net-2.0 c#-2.0


    【解决方案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; 在这种情况下不会是协变的。
    猜你喜欢
    • 2015-12-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-05-04
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多