为什么 ReferenceEquals 仍然与值类型一起使用?
Why is ReferenceEquals still used with value types?
有一个很好的 explanation 为什么 object.ReferenceEquals(this, obj)
不能用于值类型:
When comparing values using ReferenceEquals, if objA and objB are
value types, they are boxed before they are passed to the
ReferenceEquals method. This means that even if both objA and objB
represent the same instance of a value type, the ReferenceEquals
method nevertheless returns false
但是,我发现了类似于以下片段的代码:
internal readonly struct Foo
{
public override bool Equals(object obj)
{
if (object.ReferenceEquals(this, obj))
{
return true;
}
if (obj is Foo other)
{
return this.Equals(other);
}
return false;
}
public bool Equals(Foo other)
{
// ..
return true;
}
}
这是错误的还是存在 ReferenceEquals
可能对值类型(尤其是结构)有用(即求值为真)的边缘情况?
不应该。编写的代码很糟糕,因为它不必要地为测试装箱了一些 永远不会 工作的东西。为了完整起见,在这种情况下更有用和惯用的模式是:
// custom Foo equality implementation
public bool Equals(Foo other)
{
// ...
}
// default object implemenentation
public override int GetHashCode() {...} // must match Equals(Foo) logic
public override bool Equals(object obj) => obj is Foo other && Equals(other);
有一个很好的 explanation 为什么 object.ReferenceEquals(this, obj)
不能用于值类型:
When comparing values using ReferenceEquals, if objA and objB are value types, they are boxed before they are passed to the ReferenceEquals method. This means that even if both objA and objB represent the same instance of a value type, the ReferenceEquals method nevertheless returns false
但是,我发现了类似于以下片段的代码:
internal readonly struct Foo
{
public override bool Equals(object obj)
{
if (object.ReferenceEquals(this, obj))
{
return true;
}
if (obj is Foo other)
{
return this.Equals(other);
}
return false;
}
public bool Equals(Foo other)
{
// ..
return true;
}
}
这是错误的还是存在 ReferenceEquals
可能对值类型(尤其是结构)有用(即求值为真)的边缘情况?
不应该。编写的代码很糟糕,因为它不必要地为测试装箱了一些 永远不会 工作的东西。为了完整起见,在这种情况下更有用和惯用的模式是:
// custom Foo equality implementation
public bool Equals(Foo other)
{
// ...
}
// default object implemenentation
public override int GetHashCode() {...} // must match Equals(Foo) logic
public override bool Equals(object obj) => obj is Foo other && Equals(other);