7

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

Cristian Lupascu
  • 39,078
  • 16
  • 100
  • 137
Subby
  • 5,370
  • 15
  • 70
  • 125
  • 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. – Adriaan Stander Aug 06 '13 at 05:46

4 Answers4

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()
    }
}
Nikita B
  • 3,303
  • 1
  • 23
  • 41
  • 1
    @Subby @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`. – Eren Ersönmez Aug 06 '13 at 07:16
  • @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? – Nikita B Aug 06 '13 at 08:26
  • 1
    @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). – Eren Ersönmez Aug 06 '13 at 09:23
  • @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` 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. – Nikita B Aug 06 '13 at 09:36
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

Anirudha
  • 32,393
  • 7
  • 68
  • 89
1

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

Imran
  • 694
  • 5
  • 12
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.

Paul Childs
  • 229
  • 2
  • 9