IComparer<>以及 C# 中的类继承

发布于 2024-11-19 03:08:44 字数 573 浏览 2 评论 0 原文

有没有办法为基类类型实现专门的 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 类?

提前致谢!

Is there any way to implement specialized IComparer for the base class type so a child class could still use it for sorting in speciliazed collections?

Example

public class A
{
   public int X;
}

public class B:A
{
   public int Y;
}

public AComparer:IComparer<A>
{
    int Compare(A p1, A p2)
    {
        //...
    }

}

so following code will work:

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 

How to approach this issue to have both - inheritance of sorting and specialized collections (and do not copy IComparer classes for each of children classes?

Thanks in advance!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

野稚 2024-11-26 03:08:44

首先,请注意,这是通过通用逆变在 .NET 4 中修复的 - 您的代码可以简单地工作。编辑:如评论中所述,通用方差首先在 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>());

当然,这意味着使所有比较器实现通用,在我看来,这有点难看。

Firstly, note that this is fixed in .NET 4 via generic contravariance - your code would simply work. EDIT: As noted in comments, generic variance was first supported in CLR v2, but various interfaces and delegates only became covariant or contravariant in .NET 4.

However, in .NET 2 it's still fairly easy to create a converter:

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);
    }
}

You can then use:

List<B> bList = new List<B>();
IComparer<B> bComparer = new ComparerConverter<A, B>(new AComparer());
bList.Sort(bComparer);

EDIT: There's nothing you can do without changing the way of calling it at all. You could potentially make your AComparer generic though:

public class AComparer<T> : IComparer<T> where T : A
{
    int Compare(T p1, T p2)
    {
        // You can still access members of A here
    }    
}

Then you could use:

bList.Sort(new AComparer<B>());

Of course, this means making all your comparer implementations generic, and it's somewhat ugly IMO.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文