#419 – Override Relational Operators When You Implement IComparable

When a class implements IComparable, it must implement the CompareTo method.  For completeness, you should also override the relational operators.

Here’s an example.

    public class Rectangle : IEquatable<Rectangle>, IComparable<Rectangle>
    {
        public int Height { get; set; }
        public int Width { get; set; }

        public Rectangle(int height, int width)
        {
            Height = height;
            Width = width;
        }

        public override bool Equals(object obj)
        {
            return this.Equals(obj as Rectangle);
        }

        public override int GetHashCode()
        {
            return Height.GetHashCode() ^ Width.GetHashCode();
        }

        public bool Equals(Rectangle r)
        {
            if (ReferenceEquals(r,null))
                return false;

            return ((Height == r.Height) && (Width == r.Width) ||
                    (Height == r.Width) && (Width == r.Height));
        }

        public static bool operator ==(Rectangle r1, Rectangle r2)
        {
            if (ReferenceEquals(r1, null))
            {
                return ReferenceEquals(r2, null) ? true : false;
            }

            return r1.Equals(r2);
        }

        public static bool operator !=(Rectangle r1, Rectangle r2)
        {
            return !(r1 == r2);
        }

        // Result:
        //  < 0 : this instance less than r
        //  = 0 : this instance equivalent to r
        //  > 0 : this instance greater than r
        public int CompareTo(Rectangle r)
        {
            if (ReferenceEquals(r, null))
                return 1;  

            if (this.Equals(r))
                return 0;

            else if (this.Area() == r.Area())
                return this.Width - r.Width;

            else
                return this.Area() - r.Area();
        }

        public static bool operator <(Rectangle r1, Rectangle r2)
        {
            if (ReferenceEquals(r1, null))
                return false;

            else
                return (r1.CompareTo(r2) < 0) ? true : false;
        }

        public static bool operator >(Rectangle r1, Rectangle r2)
        {
            if (ReferenceEquals(r1, null))
                return false;

            else
                return (r1.CompareTo(r2) > 0) ? true : false;
        }

        public static bool operator <=(Rectangle r1, Rectangle r2)
        {
            return (r1 < r2) || (r1 == r2);
        }

        public static bool operator >=(Rectangle r1, Rectangle r2)
        {
            return (r1 > r2) || (r1 == r2);
        }

        public int Area()
        {
            return Height * Width;
        }
    }
Advertisements

About Sean
Software developer in the Twin Cities area, passionate about software development and sailing.

4 Responses to #419 – Override Relational Operators When You Implement IComparable

  1. Sayuri0903 says:

    public static bool operator <=(Rectangle r1, Rectangle r2)
    {
    return (r1 < r2) || (r1 == r2);
    }

    I think we shouldn't check <= like that. If after check r1 is not < r2, so it check again whether r1 == r2?
    Maybe we can "return (r1.CompareTo(r2) <= 0)". And do the same with others.
    Best regard,

    P.s: Thanks very much for your useful posts 🙂

  2. Kudos for using “ReferenceEquals(r, null)” instead of “r == null” in your greaterThan and lessThan overloads! In this example it looks like it would have been safe to use either, but if someone else comes along and changes the “==” overload at a later date, it could end up breaking the others.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

w

Connecting to %s

%d bloggers like this: