Мне нужно провести сравнение между объектом и NULL. Когда объект не равен NULL, я заполняю его некоторыми данными.
Вот код:
if (region != null)
{
....
}
Это работает, но иногда при зацикливании и зацикливании объект региона НЕ равен нулю (я вижу данные внутри него в режиме отладки). Пошагово при отладке он не входит в оператор IF ... Когда я провожу быстрое наблюдение со следующим выражением: я вижу, что (region == null) возвращает false, AND (region! = Null ) тоже верните false ... почему и как?
Обновлять
Кто-то указывает, что объект был == и! = Перегружен:
public static bool operator ==(Region r1, Region r2)
{
if (object.ReferenceEquals(r1, null))
{
return false;
}
if (object.ReferenceEquals(r2, null))
{
return false;
}
return (r1.Cmr.CompareTo(r2.Cmr) == 0 && r1.Id == r2.Id);
}
public static bool operator !=(Region r1, Region r2)
{
if (object.ReferenceEquals(r1, null))
{
return false;
}
if (object.ReferenceEquals(r2, null))
{
return false;
}
return (r1.Cmr.CompareTo(r2.Cmr) != 0 || r1.Id != r2.Id);
}





Иногда это может произойти, когда у вас есть несколько потоков, работающих с одними и теми же данными. В этом случае вы можете использовать блокировку, чтобы они не связывались друг с другом.
Перегружен ли оператор == и / или! = Для класса объекта региона?
Теперь, когда вы разместили код для перегрузок:
Перегрузки, вероятно, должны выглядеть следующим образом (код взят из сообщений, сделанных Джон Скит и Филип Рик):
public static bool operator ==(Region r1, Region r2)
{
if (object.ReferenceEquals( r1, r2)) {
// handles if both are null as well as object identity
return true;
}
if ((object)r1 == null || (object)r2 == null)
{
return false;
}
return (r1.Cmr.CompareTo(r2.Cmr) == 0 && r1.Id == r2.Id);
}
public static bool operator !=(Region r1, Region r2)
{
return !(r1 == r2);
}
Я только что понял, что у меня == и! = Перегружены!
Я думаю, что кто-то ошибся в части! =, Я это проверю! Спасибо за подсказку.
Правильно, перегрузки неправильные - если вы скопируете код или объяснение из моего сообщения ниже, я удалю свой пост
@Philip Rieck - Готово, хотя я не уверен, что вам нужно удалять свой пост (и я надеюсь, что не испортил логику кода).
Эти перегрузки оператора не работают.
Во-первых, это значительно упрощает жизнь, если! = Реализуется простым вызовом == и инвертированием результата.
Во-вторых, перед проверкой нулевого значения в == должно быть:
if (object.ReferenceEquals(r1, r2))
{
return true;
}
Хорошо, я сделаю модификацию через несколько минут.
Получается, что эти проверки здесь неправильные:
public static bool operator !=(Region r1, Region r2)
{
if (object.ReferenceEquals(r1, null))
{
return false;
}
if (object.ReferenceEquals(r2, null))
{
return false;
}
...
Да - вам нужна дополнительная проверка заранее, чтобы учесть случай, когда r1 и r2 оба равны нулю. Проверьте мой ответ. (Это также оптимизирует случай, когда r1 и r2 не равны нулю, но относятся к одному и тому же объекту.)
Обе перегрузки неверны
public static bool operator ==(Region r1, Region r2)
{
if (object.ReferenceEquals(r1, null))
{
return false;
}
if (object.ReferenceEquals(r2, null))
{
return false;
}
return (r1.Cmr.CompareTo(r2.Cmr) == 0 && r1.Id == r2.Id);
}
если r1 и r2 равны нулю, первый тест (объект.ReferenceEquals (r1, null)) вернет false, даже если r2 также равно нулю.
пытаться
//ifs expanded a bit for readability
public static bool operator ==(Region r1, Region r2)
{
if ( (object)r1 == null && (object)r2 == null)
{
return true;
}
if ( (object)r1 == null || (object)r2 == null)
{
return false;
}
//btw - a quick shortcut here is also object.ReferenceEquals(r1, r2)
return (r1.Cmr.CompareTo(r2.Cmr) == 0 && r1.Id == r2.Id);
}
Это работает !!!!!!!! Спасибо, что вы были бы моим "Принятым ответом", но кто-то другой сначала найдет причину, а вы поймете, как :)
Есть еще одна возможность, что вам нужно щелкнуть значок обновления рядом с параметром, который вы наблюдаете. VS пытается не отставать от производительности, не оценивая каждый оператор / параметр. Прежде чем начинать вносить изменения в нерелевантные места, убедитесь в этом.
Для сравнения на равенство типа "T" перегрузите эти методы:
int GetHashCode() //Overrides Object.GetHashCode
bool Equals(object other) //Overrides Object.Equals; would correspond to IEquatable, if such an interface existed
bool Equals(T other) //Implements IEquatable<T>; do this for each T you want to compare to
static bool operator ==(T x, T y)
static bool operator !=(T x, T y)
Ваш код сравнения для конкретного типа должен быть выполнен в одном месте: типобезопасный интерфейс IEquatable<T>, метод Equals(T other).
Если вы сравниваете с другим типом (T2), также реализуйте IEquatable<T2> и поместите код сравнения полей для этого типа в Equals (T2 other).
Все перегруженные методы и операторы должны перенаправлять задачу сравнения на равенство основному типобезопасному методу экземпляра Equals (T other), чтобы поддерживалась чистая иерархия зависимостей и вводились более строгие гарантии на каждом уровне для устранения избыточности и несущественной сложности.
bool Equals(object other)
{
if (other is T) //replicate this for each IEquatable<T2>, IEquatable<T3>, etc. you may implement
return Equals( (T)other) ); //forward to IEquatable<T> implementation
return false; //other is null or cannot be compared to this instance; therefore it is not equal
}
bool Equals(T other)
{
if ((object)other == null) //cast to object for reference equality comparison, or use object.ReferenceEquals
return false;
//if ((object)other == this) //possible performance boost, ONLY if object instance is frequently compared to itself! otherwise it's just an extra useless check
//return true;
return field1.Equals( other.field1 ) &&
field2.Equals( other.field2 ); //compare type fields to determine equality
}
public static bool operator ==( T x, T y )
{
if ((object)x != null) //cast to object for reference equality comparison, or use object.ReferenceEquals
return x.Equals( y ); //forward to type-safe Equals on non-null instance x
if ((object)y != null)
return false; //x was null, y is not null
return true; //both null
}
public static bool operator !=( T x, T y )
{
if ((object)x != null)
return !x.Equals( y ); //forward to type-safe Equals on non-null instance x
if ((object)y != null)
return true; //x was null, y is not null
return false; //both null
}
Обсуждение:
Предыдущая реализация централизует специфичное для типа (т. Е. Равенство полей) сравнение до конца реализации IEquatable<T> для этого типа.
Операторы == и != имеют параллельную, но противоположную реализацию. Я предпочитаю иметь одну ссылку на другую, так что есть дополнительный вызов метода для зависимого. Если оператор != просто будет вызывать оператора ==, а не предлагать оператора с такой же производительностью, то вы можете просто использовать !(obj1 == obj2) и избежать дополнительного вызова метода.
Сравнение с самим собой исключено из оператора равенства и реализаций IEquatable<T>, потому что оно может привести к 1. ненужным накладным расходам в некоторых случаях и / или 2. непоследовательной производительности в зависимости от того, как часто экземпляр сравнивается сам с собой по сравнению с другими экземплярами. .
Альтернатива, которую мне не нравится, но я должен упомянуть, - это отменить эту настройку, централизовав код равенства для конкретного типа в операторе равенства и от этого зависят методы Equals. Затем можно было бы использовать ярлык ReferenceEquals(obj1,obj2) для одновременной проверки ссылочного равенства и нулевого равенства, как Филип упоминал в более ранней публикации, но эта идея вводит в заблуждение. Кажется, что вы убиваете двух зайцев одним выстрелом, но на самом деле вы создаете больше работы - после определения, что объекты не являются ни нулевыми, ни одним и тем же экземпляром, вам, кроме того, ВСЕГДА придется проверять, каждый ли экземпляр нулевой. В моей реализации вы проверяете, является ли любой отдельный экземпляр нулевым ровно один раз. К моменту вызова метода экземпляра Equals уже исключено, что первый сравниваемый объект имеет значение NULL, поэтому все, что остается сделать, это проверить, является ли другой равным NULL. Таким образом, после максимум двух сравнений мы переходим непосредственно к проверке полей, независимо от того, какой метод мы используем (Equals(object),Equals(T),==,!=). Кроме того, как я уже упоминал, если вы действительно сравниваете и возражаете против себя большую часть времени, вы можете добавить эту проверку в метод Equals непосредственно перед тем, как погрузиться в сравнение полей. Смысл добавления последнего в том, что вы все еще можете поддерживать иерархию потоков / зависимостей, не вводя избыточную / бесполезную проверку на каждом уровне.
bool comp;
if (object.IsNullOrEmpty(r1))
{
comp = false;
}
if (object.IsNullOrEmpty(r2))
{
comp = false;
}
return comp;
// это может помочь вам или помочь любому, кто в этом нуждается
Спасибо, но причина в том, что == и! = Не были хорошо перегружены. Но ваш ответ мог быть правильным.