重载 == 运算符抛出带有非空操作数的 NullReferenceException
overloaded == operator throwing NullReferenceException with non-null operands
我正在尝试实现 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
不感兴趣,因为我需要等同于对象的值。
Equals(TestClass)
中的行 other == null
调用相等运算符,它调用 Equals(TestClass)
-- 无限循环。在第二轮中,other
为 null,当您将其作为 left
参数传递给相等运算符时会导致 NullReferenceException
。
您应该使用 ReferenceEquals(other, null)
或 other is null
。
实际上,您的超载 equality operator 被击中 三 次:
First,当从 Program.Main(string[])
调用行 tc1 == tc2
时,其中 left
=tc1
和 right
=tc2
,然后调用 TestClass.Equals(TestClass)
其中 other
=tc2
.
从那里,other == null
现在调用您的 重载相等运算符 秒 时间,其中 left
= tc2
和 right
=null
。
现在,TestClass.Equals(TestClass)
也被称为 秒 时间,其中 other
=null
.
最后,other == null
调用您的 重载相等运算符 第三次 次,其中两个 left
=null
和 right
=null
。现在这最终会导致 System.NullReferenceException 因为 left 为空。
要修复此编码错误,请将 TestClass.Equals(TestClass)
中的 other == null
替换为 other is null
:
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;
我正在尝试实现 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
不感兴趣,因为我需要等同于对象的值。
Equals(TestClass)
中的行 other == null
调用相等运算符,它调用 Equals(TestClass)
-- 无限循环。在第二轮中,other
为 null,当您将其作为 left
参数传递给相等运算符时会导致 NullReferenceException
。
您应该使用 ReferenceEquals(other, null)
或 other is null
。
实际上,您的超载 equality operator 被击中 三 次:
First,当从 Program.Main(string[])
调用行 tc1 == tc2
时,其中 left
=tc1
和 right
=tc2
,然后调用 TestClass.Equals(TestClass)
其中 other
=tc2
.
从那里,other == null
现在调用您的 重载相等运算符 秒 时间,其中 left
= tc2
和 right
=null
。
现在,TestClass.Equals(TestClass)
也被称为 秒 时间,其中 other
=null
.
最后,other == null
调用您的 重载相等运算符 第三次 次,其中两个 left
=null
和 right
=null
。现在这最终会导致 System.NullReferenceException 因为 left 为空。
要修复此编码错误,请将 TestClass.Equals(TestClass)
中的 other == null
替换为 other is null
:
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;