Home > Blockchain >  interface IComparer C#
interface IComparer C#

Time:04-11

how to right use IComparer with Generics

CodePudding user response:

Your question is a bit unclear. If compare "by room volume" means in fact compare Area() values and you want to imeplement a corresponding comparer, you can put something like this

public sealed class ShapeComparerByArea<T> : IComparer<T> where T : IShape
{
    public int Compare(T left, T right) 
    {
        if (ReferenceEquals(left, right))         
            return 0;
        if (left == null)
            return 1;
        if (right == null)
            return -1;

        return left.Area().CompareTo(right.Area());     
    }        
}

If you want to define comparable Room class (which has Shape Floor) you can put it as

  public class Room : IComparable<Room> {
    public Room(IShape floor, double height) {
      Floor = floor ?? throw new ArgumentNullException(nameof(floor));
      
      Height = height > 0 
        ? height 
        : throw new ArgumentOutOfRangeException(nameof(height));
    }

    public IShape Floor { get; }

    public double Height { get; }

    public double Volume => Floor.Area() * Height;

    public int CompareTo(Room other) {
      if (ReferenceEquals(this, other))
        return 0;
      if (other is null)
        return 1;

      return Volume.CompareTo(other.Volume);
    }
  }

Finally, RoomComparerByVolume can be

  public sealed class RoomComparerByVolume : IComparer<Room> {
    public int Compare(Room left, Room right) {
      if (ReferenceEquals(left, right))
        return 0;
      if (left == null)
        return 1;
      if (right == null)
        return -1;

      return left.Volume.CompareTo(right.Volume);
    }
  }

Demo:

Room myRoom = new Room(
  new Trapezoid() { Length1 = 5, Length2 = 7, Width = 3}, 
  2.8);

Room myOtherRoom = new Room(
  new Rectangle() { Length = 3, Width = 4 }, 
  2.5);

Console.WriteLine(myRoom.CompareTo(myOtherRoom));

RoomComparerByVolume comparer = new RoomComparerByVolume();

Console.WriteLine(comparer.Compare(myRoom, myOtherRoom));

CodePudding user response:

I would assume that the desired declaration should look like

public class RoomComparerByVolume<T> : IComparer<Room<T>> where T : IShape, ICloneable, IComparable{
    public int Compare(Room<T> left, Room<T> right) {
        ...
    }

That way you can compare the two rooms. But note that the two rooms need to be the same shape using this method. Also note that you need to use the same generic constraints as you are using for Room<T>.

Also note that in many cases you do not need to create a specific comparer type. Often you can use a delegate to do the actual comparison:

Comparer<Room<Trapezoid>>.Create((l, r) => l.Volume().CompareTo(r.Volume));
  • Related