重载==运算符使用非null操作数抛出NullReferenceException

时间:2018-09-22 15:05:44

标签: c# iequatable

我正在尝试实现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 :(得分:4)

other == null中的行Equals(TestClass)调用了相等运算符,该运算符调用了Equals(TestClass) –无限循环。在第二轮中,other为空,当您将其作为NullReferenceException参数传递给相等运算符时,将导致left

您应该改用ReferenceEquals(other, null)other is null

答案 1 :(得分:3)

实际上,您超载的equality operator被命中了 3 次:

第一,当从Program.Main(string[])用行tc1 == tc2调用时,其中left = tc1right = {{ 1}},然后调用tc2,其中TestClass.Equals(TestClass) = other

从那里,tc2现在将您的重载相等运算符调用 second 时间,其中other == null = left和{{ 1}} = tc2。 现在,right也称为时间,其中null = TestClass.Equals(TestClass)

最后,other调用重载的等式运算符三分之一时间,其中null = other == null和{ {1}} = left。现在,这最终会导致System.NullReferenceException,因为 left 为空。

要解决此编码错误,请将null中的right替换为null

other == null

或者,作为条件表达式(使用表达式主体):

other is null
相关问题