Почему проверка на ноль не удалась, даже если объект явно инициализирован как ноль - PullRequest
0 голосов
/ 19 марта 2019

Я создал пользовательский класс abstract , который, в свою очередь, конечно же, также создал производные классы.

public abstract class AbstractBaseClass
...

public class ChildClass1 : AbstractBaseClass
...

Теперь, когда я объявляю, например, AbstractBaseClass baseClass = null, и там, где после этой инициализации следуют нулевые проверки, всегда происходит сбой.

if (baseClass == null)
{
    // this block is never reached - condition always evaluates to false
    // let's say AbstractBaseClass baseClass = null is at line 10
    // even if this condition is at line 11, condition still fails
}

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

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

Какие могут быть возможные причины, по которым это происходит (, чтобы я мог добавить больше примеров кода в зависимости от информации, поскольку весь соответствующий код довольно большой ), и как это исправить? Спасибо.

EDIT

Кроме того, значение отладчика равно нулю.

Да, как уже говорилось, @taffer == перегружен для AbstractBaseClass. Вот эта часть и другой соответствующий код:

    protected bool Equals(AbstractBaseClass other)
    {
        return Equals(this.SomeUniqueProperty, other.SomeUniqueProperty);
    }

    public override bool Equals(object obj)
    {
        if (ReferenceEquals(null, obj))
        {
            return false;
        }

        if (ReferenceEquals(this, obj))
        {
            return true;
        }

        return obj.GetType() == this.GetType() && this.Equals((AbstractBaseClass)obj);
    }

    public override int GetHashCode()
    {
        return (this.SomeUniqueProperty != null ? this.SomeUniqueProperty.GetHashCode() : 0);
    }

    public static bool operator ==(AbstractBaseClass a, AbstractBaseClass b)
    {
        if (ReferenceEquals(null, a))
        {
            return false;
        }

        return !ReferenceEquals(null, b) && a.Equals(b);
    }

    public static bool operator !=(AbstractBaseClass a, AbstractBaseClass b)
    {
        return !(a == b);
    }

1 Ответ

3 голосов
/ 19 марта 2019

Ваша перегрузка == неправильная, так как вы возвращаете false, если a равно нулю, игнорируя тот факт, что b также может быть null.

Что вам нужно сделать, это вернуть true, если оба значения null или a равно b:

public static bool operator ==(AbstractBaseClass a, AbstractBaseClass b)
{
    var isANull = ReferenceEquals(null, a);
    var isBNull = ReferenceEquals(null, b)
    return (isANull && isBNull) || a?.Equals(b) ?? false;
}

Примечание. В случае, если a равно нулю, а b - нет, оператор .? вернет ноль, а оператор ?? вернет false.

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

public static bool operator ==(AbstractBaseClass a, AbstractBaseClass b)
{
    return a?.Equals(b) ?? ReferenceEquals(null, b);
}

если a равно нулю, вернуть true, если b также равно нулю. если a не равно нулю, вернуть результат a.Equals(b).

В случае, если a не нуль, а b, ваш метод Equals должен возвращать false:

protected bool Equals(AbstractBaseClass other)
{
    return other != null 
        ? Equals(this.SomeUniqueProperty, other.SomeUniqueProperty) 
        : false;
}
...