IComparable в C#

У меня есть объект с именем Shape, который содержит поле public int[,] coordinate { get; set; }.

У меня есть отдельный класс, в котором есть коллекция объектов Shape. В определенный момент я хочу проверить:

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

Итак, в классе Shape я добавил ссылку IComparable и вставил метод CompareTo:

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

Однако я получаю сообщение об ошибке:

Cannot implicitly convert type 'bool' to 'int'

Как мне сформулировать return так, чтобы он возвращал int, а не bool, как это делается в данный момент?

ОБНОВЛЕНИЕ

Если я изменю код возврата на:

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

Я получаю следующее сообщение об ошибке:

Ошибка 1 «ShapeD.Game_Objects.Shape» не реализует элемент интерфейса «System.IComparable.CompareTo(ShapeD.Game_Objects.Shape)». «ShapeD.Game_Objects.Shape.CompareTo(ShapeD.Game_Objects.Shape)» не может реализовать «System.IComparable.CompareTo(ShapeD.Game_Objects.Shape)», поскольку у него нет соответствующего возвращаемого типа «int». C:\Users\Usmaan\Documents\Visual Studio 2012\Projects\ShapeD\ShapeD\ShapeD\Game Objects\Shape.cs 10 18 ShapeD


person Subby    schedule 06.08.2013    source источник
comment
Новое сообщение об ошибке довольно просто решить, измените public int CompareTo(Shape other) на public int CompareTo(object other), но тогда вы столкнетесь с проблемами приведения, а CompareTo делает не существует для многомерных массивов.   -  person Adriaan Stander    schedule 06.08.2013


Ответы (4)


IComparable подразумевает, что два объекта можно сравнивать в том смысле, что вы можете сказать, какой объект имеет более высокую ценность. Обычно используется для сортировки. Вместо этого вы должны переопределить метод Equals. Вы также должны использовать структуру Point вместо массива.

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()
    }
}
person Nikita B    schedule 06.08.2013
comment
@Subby @Nikita Эти реализации Equals и GetHashCode кажутся неправильными. Ваши координаты представляют собой многомерный массив, и вы, вероятно, не хотите основывать свое равенство на ReferenceEquals. - person Eren Ersönmez; 06.08.2013
comment
@ErenErsönmez, в моем примере нет многомерного массива. Мне показалось, что ОП использовал его, чтобы просто установить координаты x и y одной точки, поэтому я заменил его на структуру Point. Я также не вижу проблемы с использованием ReferenceEquals. Я что-то пропустил? - person Nikita B; 06.08.2013
comment
@NikitaBrizhak OP требует многомерного массива (см. первое предложение в вопросе). Для типов значений и массивов ReferenceEquals редко имеет смысл. Скорее всего, вы хотите сравнить на основе значений внутри массива (а не на основе двух ссылок, указывающих на один и тот же экземпляр массива). - person Eren Ersönmez; 06.08.2013
comment
@ErenErsönmez, я говорил о намерении. Если намерение состоит в том, чтобы хранить единственное значение координаты (слово coordinate, единственное число, привело меня к такому выводу), то вообще нет смысла использовать массив, как я указал в своем примере. Если цель состоит в том, чтобы сохранить некоторую геометрию пути, то coordinate должен быть IList<Point> или какой-либо другой, возможно, специальной коллекцией. Использование многомерного массива для хранения координат кажется мне неправильным в любом случае, это была моя точка зрения. Что касается ReferenceEquals, это имеет смысл, так как сравнивает две ссылки на Shape объекты, а не на массивы. - person Nikita B; 06.08.2013

Поскольку вы хотите проверить только равенство, реализуйте интерфейс IEquatable не IComparable. IComparable используется для сортировки

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

}

ПРИМЕЧАНИЕ

IEquatable должен быть реализован для любого объекта, который может храниться в коллекции generic, иначе вам также придется переопределить метод Equals объекта. Также, как указано в другом, используйте Point вместо многомерного массива

person Anirudha    schedule 06.08.2013

Для выполнения проверки «Содержит» вам необходимо переопределить оператор Equals в классе Shape.

person Imran    schedule 06.08.2013

Воскрешение старого вопроса только потому, что он все еще может вызвать попадание в Google, несмотря на некоторые действительно плохие ответы. Вы не должны использовать ни CompareTo, ни Equals. Ни один из них не соответствует тому, что вы пытаетесь сделать, и вызовет только путаницу, о чем свидетельствуют ответы, написанные здесь. Напишите свой собственный метод под названием IntersectsWith. Загляните в любую приличную библиотеку геометрии (например, boost, если вам нравится работать с С++), чтобы узнать, как это сделать. Что касается приведения типа bool к int, то это можно легко сделать, используя bool с ключом ? тернарный оператор.

person Paul Childs    schedule 15.03.2021