Подтвердить что ты не робот

Объект С# не равен null, но (myObject!= Null) все равно возвращает false

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

Вот код:

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

Это работает, но когда цикл и цикл когда-то объект области не равен null (я могу видеть данные внутри него в режиме отладки). Поэтапно при отладке он не входит в оператор IF... Когда я делаю Quick Watch с помощью следующего выражения: Я вижу, что (region == null) возвращает false, AND (region!= Null ) return false too... почему и как?

Обновление

Кто-то указывает, что объект был == и!= перегружен:

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

Ответ 1

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

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

Перегрузки должны выглядеть следующим образом (код, сделанный из сообщений, сделанных Jon Skeet и Philip Rieck):

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

Ответ 2

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

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

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

if (object.ReferenceEquals(r1, r2))
{
    return true;
}

Ответ 3

Обе перегрузки неверны

 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 равны null, первый тест (object.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);
    }

Ответ 4

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

Ответ 5

Для сравнения сравнений типа "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 другой), так что сохраняется иерархия иждивенцев, и на каждом уровне внедряются более строгие гарантии для устранения избыточности и несущественной сложности.

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 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. непоследовательность в зависимости от того, как часто экземпляр сравнивается с самим собой vs другие экземпляры.

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

Ответ 6

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

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

Ответ 7

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

Ответ 8

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

if (object.IsNullOrEmpty(r2))
{
    comp = false;
}
return comp;