Как проверить, содержит ли список элемент [дубликат]

Как говорит Винай, есть некоторые части общих установок, которые нельзя просто скопировать. Кроме того, имейте в виду, что скрипты setup.py могут выполнять произвольную работу, например, они могут тестировать версию Python и изменять, как они устанавливают вещи, или могут записывать записи в реестре или создавать файлы .rc и т. Д. [ ! d0]

Я согласен: переустановите пакеты.

Кроме того, еще одно преимущество для повторной установки: если вы только что закончили, просто потеряете первый раз, когда что-то таинственным образом не сработает, и вы попытаетесь его отладить. сделайте это, когда вам нужен пакет, тогда вы не потрудитесь переустановить пакеты, которые вам больше не нужны.

25
задан user2029077 20 October 2014 в 21:11
поделиться

3 ответа

Метод Contains не использует оператор ==

Нет - он использует Equals, который вы не переопределили ... так что вы получаете поведение по умолчанию Equals, которое должно проверять вместо ссылочного идентификатора. Вы должны переопределить Equals(object) и GetHashCode, чтобы они были согласованы друг с другом - и для здравого смысла, в соответствии с вашей перегрузкой ==.

Я также рекомендовал бы реализовать IEquatable<Element>, который List<Element> будет использовать предпочтение Equals(object), так как EqualityComparer<T>.Default подбирает его соответствующим образом.

О, и ваши перегрузки оператора должны обрабатывать и нулевые ссылки.

Я бы также сильно рекомендуют использовать частные поля вместо общедоступных и сделать ваш тип неизменным - запечатать его и сделать id только для чтения. Реализация равенства для изменяемых типов может привести к возникновению нечетных ситуаций. Например:

Dictionary<Element, string> dictionary = new Dictionary<Element, string>();
Element x = new Element(10);
dictionary[x] = "foo";
x.id = 100;
Console.WriteLine(dictionary[x]); // No such element!

Это произойдет потому, что хэш-код будет меняться (по крайней мере, в большинстве реализаций), поэтому хеш-таблица, лежащая в основе словаря, не сможет найти даже ссылку на тот же самый объект, который уже там.

Итак, ваш класс будет выглядеть примерно так:

internal sealed class Element : IEquatable<Element>
{
    private readonly int id;

    public int Id { get { return id; } }

    public Element(int id)
    {
        this.id = id;
    }

    public static implicit operator Element(int d)  
    {
        return new Element(d);
    }

    public static bool operator ==(Element e1, Element e2)
    {
        if (object.ReferenceEquals(e1, e2))
        {
            return true; 
        }
        if (object.ReferenceEquals(e1, null) ||
            object.ReferenceEquals(e2, null))
        {
            return false; 
        }
        return e1.id == e2.id;
    }

    public static bool operator !=(Element e1, Element e2)
    {
        // Delegate...
        return !(e1 == e2);
    }

    public bool Equals(Element other)
    {
        return this == other;
    }

    public override int GetHashCode()
    {
        return id;
    }

    public override bool Equals(object obj)
    {
        // Delegate...
        return Equals(obj as Element);
    }
}

(Я не уверен в достоинствах неявное преобразование, кстати - я, как правило, держаться подальше от них.)

55
ответ дан Firo 15 August 2018 в 18:37
поделиться
  • 1
    Предполагается, что id однозначно идентифицирует объект. Это, безусловно, очень распространено, но есть ситуации (например, Entity Framework), где идентификатор может быть первоначально установлен на 0 до тех пор, пока идентификатор не будет назначен позже (например, когда объект будет сохранен). Я не уверен, что Equals будут иметь смысл в этом контексте, но если это возможность для OP, это нужно учитывать. – Eric J. 20 October 2014 в 19:52
  • 2
    +1 для объяснения странных побочных эффектов мутирования объекта, который используется в словаре или другом месте, где используется хэш-код. – Mike 20 October 2014 в 21:42
  • 3
    Мне не нравится использовать IEquatable<T> для непечатаемых типов. Даже если один реализует IEquatable<T>, все равно нужно будет переопределить Equals(Object) для семантической корректности; если IEquatable<T>.Equals(T) не будет Equals(Object) [в этом случае интерфейс не будет служить никакой цели], для производных классов будет сложно определить любые новые критерии, связанные с равенством. Кстати, мне также не нравится перегрузка == в ссылочных типах. – supercat 21 October 2014 в 00:14
  • 4
    @supercat: Согласился на герметичность - именно поэтому я и сделал класс герметичным. К сожалению, редактирование примерно в то же время удалило мой пример кода ... Для перегрузки == я нахожусь на заборе - я очень рад, что он is перегружен для ==, например , но это, безусловно, может быть преувеличено. – Jon Skeet 21 October 2014 в 06:54
  • 5
    Метод Equals(object obj) должен возвращать Equals(obj as Element). Это в стороне, я не уверен, что мне нравится этот подход Equals(Element other): использование other != null использует перегруженный оператор, а не встроенный оператор эталонного неравенства, и если вы собираетесь использовать перегруженный оператор уже, не можете ли вы просто использовать return this == other; там? – hvd 21 October 2014 в 08:17

Метод Contains не использует оператор ==. В чем проблема?

Правильно.

Этот метод [Содержит] определяет равенство с помощью сопоставления равенства по умолчанию, как определено реализацией объекта метода IEquatable.Equals для T (тип значений в списке).

http://msdn.microsoft.com/en-us/library/bhkz42b3 ( v = vs.110) .aspx

Вы также должны переопределить Equals (). Обратите внимание, когда вы перегружаете Equals (), почти всегда правильно также отменять GetHashCode ().

12
ответ дан Eric J. 15 August 2018 в 18:37
поделиться

Переопределить Equals и GetHashCode как:

class Element
{
    public int id;

    protected bool Equals(Element other)
    {
        return id == other.id;
    }

    public override bool Equals(object obj)
    {
        if (ReferenceEquals(null, obj)) return false;
        if (ReferenceEquals(this, obj)) return true;
        if (obj.GetType() != this.GetType()) return false;
        return Equals((Element) obj);
    }

    public override int GetHashCode()
    {
        return id; //or id.GetHashCode();
    }
 //..... rest of the class

См.: List<T>.Contains Method

Этот метод определяет равенство по используя сопоставитель равенства по умолчанию, как определено реализацией объектом метода IEquatable<T>.Equals для T (тип значений в списке).

8
ответ дан user2711965 15 August 2018 в 18:37
поделиться
  • 1
    Спасибо. Ваш код упростил мою работу. Если бы это было возможно, я бы тоже принял ваш ответ. – user2029077 20 October 2014 в 21:05
  • 2
    @MinimusHeximus, вы приняли правильный ответ. Не думайте о том, чтобы принять мой ответ против Джона Скита, или я буду распылен: P – user2711965 20 October 2014 в 21:52
Другие вопросы по тегам:

Похожие вопросы: