【问题标题】:IComparer<T> could not use class as a parameterIComparer<T> 不能使用类作为参数
【发布时间】:2014-11-03 05:22:57
【问题描述】:

正如我在 my previous question 中询问的那样,我被 IComparer&lt;T&gt; 实现所困。

我有一个接口和类,实现一个:

public interface IRoom
{
    // ...
}

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

还有一个比较器的父子类:

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

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

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

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

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

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

现在,我需要使用我的IRoom 孩子和RoomComparer 孩子作为此类的泛型类型参数:

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

    public Hotel(int stars, TRoom[] rooms)
    {
        Rooms = new List<TRoom>();
        _stars = stars;
        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 convertTComparer' 表达式为 键入“System.Collections.Generic.IComparer”(CS1503)

在我看来,OOP 模型是正确的,如果Hotel 类构造函数的参数实现IRoom,就像这样:new Hotel&lt;Room, SquareMetersComparer&gt;,那么它应该正确传递给RoomsComparer 类构造函数和,那么,RoomComparer 应该正确地传递给 List.Sort() 方法。但是编译器以其他方式思考......

所以,问题是:怎么了?

如果这有帮助:我在 Ubuntu 14.04 上使用 Mono 5.10.0

【问题讨论】:

  • RoomComparer 比较 Room 类的实例是否正确,但其他比较器使用 IRoom 接口?
  • @takemyoxygen 抱歉,已修复。刚刚复制了这两个类的旧代码版本(来自上一个问题)
  • @takemyoxygen 是的,请忽略我的评论 - 误解了您所指的内容。

标签: c# oop generics mono


【解决方案1】:

TComparer 定义为继承RoomComparer。 这意味着它实现了IComparerRoom。 您的列表包含 TRoom 的实例,它实现了 IRoom,而不是 Room

【讨论】:

    【解决方案2】:

    首先,您需要修复 SquareMetersComparerStandardMultipliedSquareMetersComparer 类中的错误。它们覆盖了public override int Compare(IRoom a, IRoom b),但它们应该覆盖public override int Compare(Room a, Room b)

    其次,你想在 comparer 和 TRoom 之间使用裸约束,例如:

    where TRoom : class, IRoom 
    where TComparer : IComparer<TRoom>, new()
    

    此外,协方差适用于 IComparer,这意味着您还可以在必要时指定此类约束:

    where TRoom : class, IRoom 
    where TComparer : IComparer<IRoom>, new()
    

    【讨论】:

    • 对不起,那是这两个类的旧代码 - 只是从我的上一个复制的。问题 - 他们实际上实现了Compare(Room a, Room b)
    猜你喜欢
    • 2014-12-27
    • 2019-08-23
    • 2017-11-20
    • 1970-01-01
    • 2018-11-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多