Как говорит Винай, есть некоторые части общих установок, которые нельзя просто скопировать. Кроме того, имейте в виду, что скрипты setup.py могут выполнять произвольную работу, например, они могут тестировать версию Python и изменять, как они устанавливают вещи, или могут записывать записи в реестре или создавать файлы .rc и т. Д. [ ! d0]
Я согласен: переустановите пакеты.
Кроме того, еще одно преимущество для повторной установки: если вы только что закончили, просто потеряете первый раз, когда что-то таинственным образом не сработает, и вы попытаетесь его отладить. сделайте это, когда вам нужен пакет, тогда вы не потрудитесь переустановить пакеты, которые вам больше не нужны.
Метод Contains не использует оператор ==
blockquote>Нет - он использует
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); } }
(Я не уверен в достоинствах неявное преобразование, кстати - я, как правило, держаться подальше от них.)
Метод Contains не использует оператор ==. В чем проблема?
Правильно.
Этот метод [Содержит] определяет равенство с помощью сопоставления равенства по умолчанию, как определено реализацией объекта метода IEquatable.Equals для T (тип значений в списке).
http://msdn.microsoft.com/en-us/library/bhkz42b3 ( v = vs.110) .aspx
Вы также должны переопределить Equals (). Обратите внимание, когда вы перегружаете Equals (), почти всегда правильно также отменять GetHashCode ().
Переопределить 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
Этот метод определяет равенство по используя сопоставитель равенства по умолчанию, как определено реализацией объектом метода
IEquatable<T>.Equals
для T (тип значений в списке).
id
однозначно идентифицирует объект. Это, безусловно, очень распространено, но есть ситуации (например, Entity Framework), где идентификатор может быть первоначально установлен на 0 до тех пор, пока идентификатор не будет назначен позже (например, когда объект будет сохранен). Я не уверен, что Equals будут иметь смысл в этом контексте, но если это возможность для OP, это нужно учитывать. – Eric J. 20 October 2014 в 19:52IEquatable<T>
для непечатаемых типов. Даже если один реализуетIEquatable<T>
, все равно нужно будет переопределитьEquals(Object)
для семантической корректности; еслиIEquatable<T>.Equals(T)
не будетEquals(Object)
[в этом случае интерфейс не будет служить никакой цели], для производных классов будет сложно определить любые новые критерии, связанные с равенством. Кстати, мне также не нравится перегрузка==
в ссылочных типах. – supercat 21 October 2014 в 00:14==
я нахожусь на заборе - я очень рад, что он is i> перегружен для==
, например , но это, безусловно, может быть преувеличено. – Jon Skeet 21 October 2014 в 06:54Equals(object obj)
должен возвращатьEquals(obj as Element)
. Это в стороне, я не уверен, что мне нравится этот подходEquals(Element other)
: использованиеother != null
использует перегруженный оператор, а не встроенный оператор эталонного неравенства, и если вы собираетесь использовать перегруженный оператор уже, не можете ли вы просто использоватьreturn this == other;
там? – hvd 21 October 2014 в 08:17