перегружен == оператор, выбрасывающий исключение NullReferenceException с ненулевыми операндами - PullRequest
0 голосов
/ 22 сентября 2018

Я пытаюсь реализовать интерфейс IEquatable<T> и оператор ==.Приведенная ниже реализация вызывает NullReferenceException, когда я пытаюсь использовать оператор ==, несмотря на тот факт, что оба операнда не являются нулевыми.Я добавил комментарии к минимальному коду примера, чтобы точно показать, где происходит исключение.Что я делаю не так?

using System;

namespace scratchpad
{
    class TestClass : IEquatable<TestClass>
    {
        public int data;
        public TestClass(int d)
        {
            this.data = d;
        }
        public bool Equals(TestClass other)
        {
            if (other == null)
                return false;
            else
                return this.data == other.data;
        }

        public override bool Equals(object other)
        {
            if (other is TestClass)
                return this.Equals((TestClass)other);
            else //Includes null
                return false;
        }

        public override int GetHashCode()
        {
            return this.data;
        }

        public static bool operator ==(TestClass left, TestClass right)
        {
            return left.Equals(right); //This line triggers the NullReferenceException
        }

        public static bool operator !=(TestClass left, TestClass right)
        {
            return !left.Equals(right);
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            TestClass tc1 = new TestClass(10);
            TestClass tc2 = new TestClass(10);
            Console.WriteLine("tc1="+tc1.data); //Prints "tc1.data=10" fine
            Console.WriteLine("tc1="+tc1.data); //Prints "tc2.data=10" fine
            bool isEqual = tc1 == tc2; //NullReferenceException occur here
            Console.WriteLine("isEqual="+isEqual); //Never gets to here
        }
    }
}

Редактировать (чтобы уточнить вопрос в ответ на дубликаты флажков вопроса): Я не спрашиваю, что такое NullReferenceException (я так понимаю), и меня не интересует ReferenceEquals так как мне нужно приравнять значения объекта.

Ответы [ 2 ]

0 голосов
/ 22 сентября 2018

На самом деле ваш перегруженный оператор равенства получает три раза:

Первый , когда вызывается из Program.Main(string[]) со строкой tc1 == tc2, где left = tc1 и right = tc2, который затем вызывает TestClass.Equals(TestClass), где other = tc2.

Оттуда other == null теперь вызывает ваш перегруженный оператор равенства a секунда время, где left = tc2 и right = null.Теперь TestClass.Equals(TestClass) также называется временем секунды , где other = null.

И, наконец, other == null вызывает ваш перегруженный оператор равенства в течение третьего времени, где оба left = null и right = null.Это теперь в конечном итоге вызывает System.NullReferenceException , поскольку left было нулевым.

Чтобы исправить эту ошибку кодирования, замените other == null на other is null в TestClass.Equals(TestClass):

public bool Equals(TestClass other)
{
    if (other is null)
        return false;
    else
        return data == other.data;
}

Альтернативно, в качестве условного выражения (используя тело выражения):

public bool Equals(TestClass other) => !(other is null) && data == other.data;
0 голосов
/ 22 сентября 2018

Строка other == null в Equals(TestClass) вызывает оператор равенства, который вызывает Equals(TestClass) - бесконечный цикл.Во втором раунде other равен нулю, что приводит к NullReferenceException, когда вы передаете его оператору равенства в качестве параметра left.

Вместо этого следует использовать ReferenceEquals(other, null) или other is null.

...