C # - список <T>.Remove () всегда удаляет первый объект в списке - PullRequest
5 голосов
/ 16 сентября 2009

Работа в Visual Studio 2008 (C #) ... Я использую коллекцию List для хранения экземпляров моего пользовательского класса (Shift).

Я хочу удалить определенный сдвиг из списка с помощью метода Remove.

Но List.Remove () всегда удаляет первый найденный элемент.

Я реализовал интерфейс IComparable для своего Shift, я подумал, что этого будет достаточно, затем я добавил реализацию IEqualityComparer, и она все еще не действует.

Вот выдержка из моей реализации:

регион IComparable Члены

    public int CompareTo(object obj)
    {
        Shift s1 = this;
        Shift s2 = (Shift)obj;
        if (s1.start.time != s2.start.time)
            return s1.start.CompareTo(s2.start);
        else
            return s1.end.CompareTo(s2.end);
    }

endregion

регион Пользователи IEqualityComparer

    public bool Equals(Shift x, Shift y)
    {

        if ((x.opening) != (y.opening)) return false;
        if ((x.closing) != (y.closing)) return false;
        if (!x.opening) if (x._start != y._start) return false;
        if (!x.closing) if (x._end != y._end) return false;
        if (x.when != y.when) return false;
        if (x.day != y.day) return false;
        if (x.EmployeeID != y.EmployeeID) return false;
        return true;
    }

    public int GetHashCode(Shift obj)
    {
        return obj.ToString().ToLower().GetHashCode();
    }

endregion

И все же, еще - когда в Списке две смены, скажите «8:00 - 15:00»; «12:00 - 16:00», вызов Remove («12: 00-16: 00») приводит к удалению «8:00 - 15:00», а последний остается в коллекции!

Что здесь не так? Thx

Ответы [ 4 ]

10 голосов
/ 16 сентября 2009

Вы можете переопределить object.GetHashCode и object.Equals:

public override bool Equals(object obj)
{
    if(obj == null)
    {
        return false;
    }
    return Equals(this, obj as Shift);
}

public override int GetHashCode()
{
    return this.GetHashCode(this);
}

Вы также, вероятно, должны сделать нулевую проверку в Equals(x, y).

3 голосов
/ 16 сентября 2009

IComparable обычно не используется для сравнения на равенство (используется для упорядочивания), поэтому List<T>.Remove() игнорирует его.

IEqualityComparer не является эквивалентом IComparable для целей равенства. Предполагается, что он будет реализован объектом сравнения , то есть объектом, который сравнивает других объектов на равенство. Если вы хотите, чтобы сравнения равенства были присущи вашему классу, то вам лучше реализовать IEquatable<T>. Или просто переопределите Object.Equals() и Object.GetHashCode() в своем классе, без реализации каких-либо интерфейсов.

0 голосов
/ 16 сентября 2009

В приведенном вами примере вы звоните:

List<Shift>.Remove("12:00 - 16:00");

"12:00 - 16:00" в этом случае является значением String, а не фактическим Shift объектом. Убедитесь, что в вашем методе CompareTo ваш код правильно приводит значение String к объекту Shift. В противном случае, когда он сравнивает время начала ... все может пойти наперекосяк.

0 голосов
/ 16 сентября 2009

Remove использует EqualityComparer<T>.Default для определения равенства и выбора объекта для удаления, который будет использовать IEquatable<T>, если он реализован на вашем объекте, в противном случае он будет использовать равенство ссылок.

У вас есть два варианта поведения, которое вы хотите:

1) Заставить Shift реализовать IEquatable<T> (не просто переопределить Object.Equals или создать метод, но сделать Shift - Shift : IEquatable<Shift>)

2) Использование List<T>.RemoveAt

...