IComparer <t>子作为通用参数无法在Sort </t>中使用

时间:2014-10-30 22:02:13

标签: c# sorting generics mono

试图在C#中对List<>进行排序时遇到困难。

我有一个接口类型及其实现类:

public interface IRoom
{
    // ...
}

public class Room : IRoom
{
    // ...
}

我的比较器的基类:

public abstract class RoomComparer : IComparer<IRoom>
{
    public RoomComparer()
    {
    }

    public abstract int Compare(IRoom x, IRoom y);
}

还有两个孩子:

public class StandardMultipliedSquareMetersComparer : RoomComparer
{
    public StandardMultipliedSquareMetersComparer()
    {
    }

    public override int Compare(IRoom a, IRoom b)
    {
        // ...
    }
}

public class SquareMetersComparer : RoomComparer
{
    public SquareMetersComparer()
    {
    }

    public override int Compare(IRoom a, IRoom b)
    {
        // ...
    }
}

现在,问题就出现了:我得到了一个通用类Hotel,其中包含我的Room个实例列表:

public class Hotel<TRoom, TComparer> : IHotel, IEnumerable<TRoom> 
    where TRoom : IRoom 
    where TComparer : RoomComparer, new()
{
    public List<TRoom> Rooms;
    protected TComparer Comparer;

    public Hotel(TRoom[] rooms)
    {
        Rooms = new List<TRoom>();
        Rooms.AddRange(rooms);
        Comparer = new TComparer();
        Rooms.Sort(Comparer);
    }
}

这就是麻烦 - 我在Rooms.Sort(Comparer);行上遇到两个错误:

  

错误CS1502:最佳重载方法匹配   `System.Collections.Generic.List.Sort(System.Collections.Generic.IComparer)”   有一些无效的参数(CS1502)

     

错误CS1503:参数#1' cannot convert TComparer'表达式为   输入`System.Collections.Generic.IComparer'(CS1503)

我尝试了很多不同的解决方案,但没有结果。发生了什么事?

注意:在Ubuntu上使用Mono 3.10.0

2 个答案:

答案 0 :(得分:7)

您尝试对此使用通用逆变(如果比较器可以比较两个TRoom值,它应该能够比较两个IRoom值),这通常 很好 - 但只有当TRoom被认为是类类型时才会这样。您可以通过要求TRoom是引用类型来解决此问题:

where TRoom : class, IRoom

此时,逆变工作正常,一切顺利。当然,它确实要求所有房间类型都是真正的课程。

你肯定需要酒店像这样通用吗?对我来说似乎有点太过分了......

答案 1 :(得分:1)

以下是解决此问题的方法:

where TComparer : IComparer<IRoom>, new()

(至于为什么,请参阅Jon的回答)

您还可以稍微简化一下代码:

Rooms = rooms.OrderBy(room => room, new TComparer()).ToList();

(只需添加using System.Linq

See working demo