[c#] Operator overloading ==, !=, Equals

I've already gone through question

I understand that, it is necessary to implement ==, != and Equals().

public class BOX
{
    double height, length, breadth;

    // this is first one '=='
    public static bool operator== (BOX obj1, BOX obj2)
    {
        return (obj1.length == obj2.length 
                    && obj1.breadth == obj2.breadth 
                    && obj1.height == obj2.height);
    }

    // this is second one '!='
    public static bool operator!= (BOX obj1, BOX obj2)
    {
        return !(obj1.length == obj2.length 
                    && obj1.breadth == obj2.breadth 
                    && obj1.height == obj2.height);
    }

    // this is third one 'Equals'
    public override bool Equals(BOX obj)
    {
        return (length == obj.length 
                    && breadth == obj.breadth 
                    && height == obj.height);
    }
}

I assume, I've written code properly to override ==,!=,Equals operators. Though, I get compilation errors as follows.

'myNameSpace.BOX.Equals(myNameSpace.BOX)' is marked as an override 
but no suitable method found to override.

So, question is - How to override above operators & get rid of this error?

This question is related to c# .net compiler-errors operator-overloading

The answer is


public class BOX
{
    double height, length, breadth;

    public static bool operator == (BOX b1, BOX b2)
    {
        if (b1 is null)
            return b2 is null;

        return b1.Equals(b2);
    }

    public static bool operator != (BOX b1, BOX b2)
    {
        return !(b1 == b2);
    }

    public override bool Equals(object obj)
    {
        if (obj == null)
            return false;

        return obj is BOX b2? (length == b2.length && 
                               breadth == b2.breadth && 
                               height == b2.height): false;

    }

    public override int GetHashCode()
    {
        return (height,length,breadth).GetHashCode();
    }
}

In fact, this is a "how to" subject. So, here is the reference implementation:

    public class BOX
    {
        double height, length, breadth;

        public static bool operator == (BOX b1, BOX b2)
        {
            if ((object)b1 == null)
                return (object)b2 == null;

            return b1.Equals(b2);
        }

        public static bool operator != (BOX b1, BOX b2)
        {
            return !(b1 == b2);
        }

        public override bool Equals(object obj)
        {
            if (obj == null || GetType() != obj.GetType())
                return false;

            var b2 = (BOX)obj;
            return (length == b2.length && breadth == b2.breadth && height == b2.height);
        }

        public override int GetHashCode()
        {
            return height.GetHashCode() ^ length.GetHashCode() ^ breadth.GetHashCode();
        }
    }

REF: https://msdn.microsoft.com/en-us/library/336aedhh(v=vs.100).aspx#Examples

UPDATE: the cast to (object) in the operator == implementation is important, otherwise, it would re-execute the operator == overload, leading to a stackoverflow. Credits to @grek40.

This (object) cast trick is from Microsoft String == implementaiton. SRC: https://github.com/Microsoft/referencesource/blob/master/mscorlib/system/string.cs#L643


As Selman22 said, you are overriding the default object.Equals method, which accepts an object obj and not a safe compile time type.

In order for that to happen, make your type implement IEquatable<Box>:

public class Box : IEquatable<Box>
{
    double height, length, breadth;

    public static bool operator ==(Box obj1, Box obj2)
    {
        if (ReferenceEquals(obj1, obj2))
        {
            return true;
        }
        if (ReferenceEquals(obj1, null))
        {
            return false;
        }
        if (ReferenceEquals(obj2, null))
        {
            return false;
        }

        return obj1.Equals(obj2);
    }

    public static bool operator !=(Box obj1, Box obj2)
    {
        return !(obj1 == obj2);
    }

    public bool Equals(Box other)
    {
        if (ReferenceEquals(other, null))
        {
            return false;
        }
        if (ReferenceEquals(this, other))
        {
            return true;
        }

        return height.Equals(other.height) 
               && length.Equals(other.length) 
               && breadth.Equals(other.breadth);
    }

    public override bool Equals(object obj)
    {
        return Equals(obj as Box);
    }

    public override int GetHashCode()
    {
        unchecked
        {
            int hashCode = height.GetHashCode();
            hashCode = (hashCode * 397) ^ length.GetHashCode();
            hashCode = (hashCode * 397) ^ breadth.GetHashCode();
            return hashCode;
        }
    }
}

Another thing to note is that you are making a floating point comparison using the equality operator and you might experience a loss of precision.


Examples related to c#

How can I convert this one line of ActionScript to C#? Microsoft Advertising SDK doesn't deliverer ads How to use a global array in C#? How to correctly write async method? C# - insert values from file into two arrays Uploading into folder in FTP? Are these methods thread safe? dotnet ef not found in .NET Core 3 HTTP Error 500.30 - ANCM In-Process Start Failure Best way to "push" into C# array

Examples related to .net

You must add a reference to assembly 'netstandard, Version=2.0.0.0 How to use Bootstrap 4 in ASP.NET Core No authenticationScheme was specified, and there was no DefaultChallengeScheme found with default authentification and custom authorization .net Core 2.0 - Package was restored using .NetFramework 4.6.1 instead of target framework .netCore 2.0. The package may not be fully compatible Update .NET web service to use TLS 1.2 EF Core add-migration Build Failed What is the difference between .NET Core and .NET Standard Class Library project types? Visual Studio 2017 - Could not load file or assembly 'System.Runtime, Version=4.1.0.0' or one of its dependencies Nuget connection attempt failed "Unable to load the service index for source" Token based authentication in Web API without any user interface

Examples related to compiler-errors

intellij idea - Error: java: invalid source release 1.9 Error:Execution failed for task ':app:transformClassesWithJarMergingForDebug' Deserialize JSON with Jackson into Polymorphic Types - A Complete Example is giving me a compile error Android java.exe finished with non-zero exit value 1 error: expected primary-expression before ')' token (C) What does "collect2: error: ld returned 1 exit status" mean? Python3: ImportError: No module named '_ctypes' when using Value from module multiprocessing Maven error :Perhaps you are running on a JRE rather than a JDK? What does a "Cannot find symbol" or "Cannot resolve symbol" error mean? Operator overloading ==, !=, Equals

Examples related to operator-overloading

Operator overloading ==, !=, Equals operator << must take exactly one argument assignment operator overloading in c++ What are the basic rules and idioms for operator overloading? Operator overloading on class templates How to code a modulo (%) operator in C/C++/Obj-C that handles negative numbers How to override the [] operator in Python? Operator overloading in Java How to properly overload the << operator for an ostream? How do I overload the [] operator in C#