我看到很多关于 C# 中的相等性以及如何实现它的帖子和问题。我想尝试收集最佳实践,并提供一个或多或少没有样板代码、不重复代码的解决方案。
从这样一个简单的类开始:
public class Foo
{
public int Bar { get; set; }
}
我现在想向此类添加 Equals
的所有可能性调用首先使用 ReSharper 建议覆盖它:
public override bool Equals(object obj)
{
if (ReferenceEquals(null, obj)) return false;
if (ReferenceEquals(this, obj)) return true;
if (obj.GetType() != GetType()) return false;
if(obj is Foo foo)
{
// here all the values should be checked
return Bar == foo.Bar;
}
return false;
}
现在我已经覆盖了 Equals 调用,但留下了 ==
和!=
具有该建议的运营商 https://www.loganfranken.com/blog/698/overriding-equals-in-c-part-3/
public static bool operator ==(Foo a,
Foo b)
{
if(ReferenceEquals(null, a)) return false;
return a.Equals(b);
}
public static bool operator !=(Foo a,
Foo b)
{
return !(a == b);
}
现在的最后一步是实现 IEquatable<>
像这样的界面并调整覆盖Equals
像这样离开类:
public class Foo : IEquatable<Foo>
{
public int Bar { get; set; }
public bool Equals(Foo other)
{
if (ReferenceEquals(null, other)) return false;
if (ReferenceEquals(this, other)) return true;
// here all the values should be checked
return Bar == other.Bar;
}
public override bool Equals(object obj)
{
if (ReferenceEquals(null, obj)) return false;
if (obj.GetType() != GetType()) return false;
return Equals(obj as Foo);
}
public static bool operator ==(Foo a,
Foo b)
{
if(ReferenceEquals(null, a)) return false;
return a.Equals(b);
}
public static bool operator !=(Foo a,
Foo b)
{
return !(a == b);
}
}
现在,在我看来,我已经或多或少地删除了所有重复代码(不幸的是,我想不出一种方法来消除空检查)。我将在 Equals(Foo other)
中实现“核心逻辑”方法和其他方法可以复制到任何其他类。
这里有我遗漏的陷阱或问题吗?或者有什么关于获得更少代码的建议吗?我并不是想获得最佳性能,干净的代码应该是此实现和其他类的可重用性的主要标准。那么是否可以将最后 3 个方法毫无问题地复制到任何其他类并且仅实现 IEquatable<>
当然,还要更改调用?
另请注意,我没有实现 GetHashCode()
现在。
最佳答案
您不应该重复自己:实现 public bool Equals(Foo other)
就足够了;
所有其他:Equals
、==
、!=
可以从 Equals(Foo other)
派生:
public class Foo : IEquatable<Foo>
{
public int Bar { get; set; }
public bool Equals(Foo other)
{
if (ReferenceEquals(this, other)) return true;
if (other is null) return false;
// here all the values should be checked
return Bar == other.Bar;
}
// Here we can put it short
public override bool Equals(object obj) => obj is Foo other && Equals(other);
//TODO: Don't forget about hash
// Here I put the easiest approach which exploits the fact we
// have just one property of type int.
public override int GetHashCode() => Bar;
// Note ReferenceEquals(a, b): we want null == null be true
public static bool operator == (Foo a, Foo b) =>
ReferenceEquals(a, b) || (a is not null && a.Equals(b));
public static bool operator !=(Foo a, Foo b) => !(a == b);
}
关于c# - 等于实现并覆盖 Equals、IEquatable、== 和 !=,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/67805459/