Объект C # не равен нулю, но (MyObject != null) все равно возвращает false

StackOverflow https://stackoverflow.com/questions/155458

  •  03-07-2019
  •  | 
  •  

Вопрос

Мне нужно провести сравнение между object и NULL.Когда объект не равен НУЛЮ, я заполняю его некоторыми данными.

Вот этот код :

 if (region != null)
 {
  ....
 }

Это работает, но при повторном цикле объект region НЕ равен нулю (я могу видеть данные внутри него в режиме отладки).При пошаговой отладке это не входит в инструкцию IF...Когда я делаю быстрый Просмотр со следующим выражением :Я вижу, что (region == null) возвращает false, И (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);
    }
Это было полезно?

Решение

Перегружен ли оператор == и / или != для класса объекта region?

Теперь, когда вы опубликовали код для перегрузок:

Перегрузки, вероятно, должны выглядеть следующим образом (код взят из записей, сделанных Джон Скит и Филип Рик):

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);
}

Другие советы

Эти перегрузки оператора нарушены.

Во-первых, это намного упрощает жизнь, если != реализуется простым вызовом == и инвертированием результата.

Во-вторых, перед проверкой на недействительность в == должно быть:

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;
        }

        return (r1.Cmr.CompareTo(r2.Cmr) == 0 && r1.Id == r2.Id);
    }

если r1 и r2 равны нулю, то первый тест (объект.Ссылочные значения (r1, null)) вернет false, даже если r2 также равен null.

попробуй

//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);
    }

Иногда это может произойти, когда у вас есть несколько потоков, работающих с одними и теми же данными.Если это так, вы можете использовать блокировку, чтобы они не мешали друг другу.

Для сравнения равенства типа "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) и избегайте дополнительного вызова метода.Сравнение с самим собой исключено из оператора equals и IEquatable<T> реализации, потому что это может ввести 1.ненужные накладные расходы в некоторых случаях и/или 2.непоследовательная производительность зависит от того, как часто экземпляр сравнивается сам с собой по сравнению с другими экземплярами.

Альтернатива, которая мне не нравится, но о которой следует упомянуть, заключается в том, чтобы отменить эту настройку, централизуя вместо этого код равенства для конкретного типа в операторе равенства, и чтобы методы Equals зависели от этого.Затем можно было бы использовать кратчайший путь из ReferenceEquals(obj1,obj2) проверять равенство ссылок и нулевое равенство одновременно, как упоминал Филип в предыдущем посте, но эта идея вводит в заблуждение.Кажется, что вы убиваете двух зайцев одним выстрелом, но на самом деле вы создаете больше работы - после определения, что объекты не являются ни нулевыми, ни одним и тем же экземпляром, вам, кроме того, ВСЕ равно придется проверять, является ли каждый экземпляр нулевым.В моей реализации вы проверяете, является ли любой отдельный экземпляр null ровно один раз.К моменту вызова метода экземпляра Equals уже исключено, что первый сравниваемый объект равен null, поэтому все, что осталось сделать, это проверить, равен ли другой null.Таким образом, не более чем после двух сравнений мы переходим непосредственно к проверке поля, независимо от того, какой метод мы используем (Equals(object),Equals(T),==,!=).Кроме того, как я уже упоминал, если вы действительно сравниваете и возражаете самому себе большую часть времени, то вы могли бы добавить эту проверку в метод Equals непосредственно перед переходом к сравнениям полей.Смысл в добавлении его последним заключается в том, что вы все еще можете поддерживать иерархию потоков / зависимостей, не вводя избыточную / бесполезную проверку на каждом уровне.

Так значит ли это, что эти проверки здесь неверны:

public static bool operator !=(Region r1, Region r2)
{
    if (object.ReferenceEquals(r1, null))
    {
        return false;
    }
    if (object.ReferenceEquals(r2, null))
    {
        return false;
    }
...

Существует еще одна возможность, когда вам нужно нажать на значок обновления рядом с параметром, который вы просматриваете.VS пытается идти в ногу с производительностью, не оценивая при этом каждый оператор / параметр.Взгляните, чтобы убедиться, прежде чем начинать вносить изменения в места, которые не имеют отношения к делу.

bool comp;
if (object.IsNullOrEmpty(r1))
{
    comp = false;
}

if (object.IsNullOrEmpty(r2))
{
    comp = false;
}
return comp;
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top