IComparable in C#
Asked Answered
F

4

8

I have an object called Shape which contains a public int[,] coordinate { get; set; } field.

I have a separate class which has a collection of Shape objects. At a particular point, I wish to check:

if(shapes.Contains(shape))
{
   // DoSomething
}

So in the Shape class I have added the IComparable reference and inserted the CompareTo method:

public int CompareTo(Shape other)
{
    return this.coordinate.Equals(other.coordinate);
}

I am however getting an error:

Cannot implicitly convert type 'bool' to 'int'

How do I therefore phrase the return so that it returns an int and not a bool as it is doing so at the moment?

UPDATE

If I change the return code to:

return this.coordinate.CompareTo(other.coordinate);

I get the following error mesage:

Error 1 'ShapeD.Game_Objects.Shape' does not implement interface member 'System.IComparable.CompareTo(ShapeD.Game_Objects.Shape)'. 'ShapeD.Game_Objects.Shape.CompareTo(ShapeD.Game_Objects.Shape)' cannot implement 'System.IComparable.CompareTo(ShapeD.Game_Objects.Shape)' because it does not have the matching return type of 'int'. C:\Users\Usmaan\Documents\Visual Studio 2012\Projects\ShapeD\ShapeD\ShapeD\Game Objects\Shape.cs 10 18 ShapeD

Faustofaustus answered 6/8, 2013 at 5:31 Comment(1)
The new error message is fairly simple to resolve, change public int CompareTo(Shape other) to public int CompareTo(object other) but then you will face casting problems and CompareTo does not exist for multi dimentional arrays.Aircrewman
C
2

IComparable implies, that two object can be compared in a sense, that you can tell which object has "higher value". It is generally used for sorting purposes. You should override Equals method instead .You should also use Point struct instead of array.

class Shape : IEquatable<Shape>
{
    public Point coordinate { get; set; }

    public bool Equals(Shape other)
    {
        if (other == null) return false;
        return coordinate.Equals(other.coordinate);
    }

    public override bool Equals(object other)
    {
        if (other == null) return false;
        if (ReferenceEquals(this, other)) return true;
        var shape = other as Shape;
        return Equals(shape);
    }

    public override int GetHashCode()
    {
        return coordinate.GetHashCode()
    }
}
Codeine answered 6/8, 2013 at 6:2 Comment(4)
@Faustofaustus @Nikita These Equals and GetHashCode implementations seem wrong. Your coordinates are a multidimantional array, and you probably don't want to base your equality on ReferenceEquals.Retrorocket
@ErenErsönmez, there is no multidimensional array in my example. It seemed to me that OP was using it to simply set x and y coordinate of single point, so i replaced it with Point struct. I also dont see an issue with using ReferenceEquals. Am i missing something?Codeine
@NikitaBrizhak the OP requires a multidimensional array (see the first sentence in the question). For value types and arrays, ReferenceEquals rarely makes sense. Most likely, you want to compare based on the values inside the array (and not based on two references pointing to the exact same instance of the array).Retrorocket
@ErenErsönmez, i was talking about intent. If the intent is to store single coordinate value (the word coordinate, singular form, led me to this conclusion), then it makes no sense to use array at all, as i pointed out in my example. If the intent is to store some path geometry, then coordinate should indead be a IList<Point> or some other, probably dedicated, collection. Using a multidimensional array to store coordinates seems wrong to me either way, that was my point. As for ReferenceEquals, it makes sense, since it compares two references to Shape objects, not arrays.Codeine
B
2

Since you only want to check for equality implement IEquatable interface not IComparable. IComparable is used for sorting purpose

public bool Equals(Shape s)
{

    int count=0;
    int[] temp1=new int[this.coordinate.Length];
    foreach(int x in this.coordinate)temp1[count++]=x;//convert to single dimention

    count=0;
    int[] temp2=new int[s.coordinate.Length];
    foreach(int x in s.coordinate)temp2[count++]=x;//convert to single dimention

    return temp1.SequenceEqual(temp2);//check if they are equal

}

NOTE

IEquatable should be implemented for any object that might be stored in a generic collection else you would have to also override Object's Equals method.Also as pointed out in other ans use Point struct instead of multidimentional array

Bryon answered 6/8, 2013 at 6:6 Comment(0)
T
1

For performing Contains check you need to override Equals operator in Shape class.

Thymus answered 6/8, 2013 at 5:52 Comment(0)
T
0

Resurrecting an old question only because it can still cause google hits despite some really poor answers. You should not be using either CompareTo or Equals. Neither of these fits with what you are trying to do and will only cause confusion, as evidenced by the answers written here. Write your own method called something like IntersectsWith. Have a look into any decent geometry library (e.g. boost if you're happy pulling from c++) as how to go about doing this. As to casting from bool to int, this can be easily done by using the bool with the ? ternary operator.

Tortola answered 15/3, 2021 at 4:57 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.