试图在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
答案 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
)