class MyClass : IEquatable<MyClass> {
public MyClass(int x = 0, int y = 0) { X = x; Y = y; }
public override bool Equals(object obj) {
var other = obj as MyClass;
return other is null ? false : X == other.X && Y == other.Y;
public bool Equals(MyClass o) => Equals((object)o);
public static bool operator ==(MyClass o1, MyClass o2) => object.Equals(o1, o2);
public static bool operator !=(MyClass o1, MyClass o2) => !(o1 == o2);
public override int GetHashCode() => X ^ Y;
class MyDerived : MyClass, IEquatable<MyDerived> {
public MyDerived(int x = 0, int y = 0, int z=0, int k=0) : base(x, y) { Z = z; K = k; }
public override bool Equals(object obj) {
var other = obj as MyDerived;
return other is null ? false : base.Equals((object)other) && Z == other.Z && K == other.K;
public bool Equals(MyDerived other) => Equals((object)other);
public static bool operator ==(MyDerived o1, MyDerived o2) => object.Equals(o1, o2);
public static bool operator !=(MyDerived o1, MyDerived o2) => !(o1 == o2);
public override int GetHashCode() => base.GetHashCode() ^ Z ^ K;
public static void Main()
MyDerived d1 = new MyDerived(0, 1, 2, 3), d2 = new MyDerived(0, 1, 4, 5), d3 = new MyDerived(0, 1, 2, 3), d4 = null;
MyClass b1 = d1, b2 = d2, b3 = d3, b4 = d4;
Console.WriteLine(" d1==d2 => "+ (d1==d2));
Console.WriteLine(" d1.Equals(d2) => " + (d1.Equals(d2)));
Console.WriteLine(" d1==d3 => " + (d1==d3));
Console.WriteLine(" d1.Equals(d3) => " + (d1.Equals(d3)));
Console.WriteLine(" d1==d4 => " + (d1 == d4));
Console.WriteLine(" d1.Equals(d4) => " + (d1.Equals(d4)));
Console.WriteLine(" b1==b2 => "+ (b1==b2));
Console.WriteLine(" b1.Equals(b2) => " + (b1.Equals(b2)));
Console.WriteLine(" b1==b3 => " + (b1==b3));
Console.WriteLine(" b1.Equals(b3) => " + (b1.Equals(b3)));
Console.WriteLine(" b1==b4 => " + (b1 == b4));
Console.WriteLine(" b1.Equals(b4) => " + (b1.Equals(b4)));