在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;
}现在,我已经覆盖了相等调用,但是留给==和!=运算符的是推荐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()。
发布于 2021-06-02 13:02:37
您不应该重复自己:实现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);
}https://stackoverflow.com/questions/67805459
复制相似问题