Comparing two structs using ==

C#StructEquality

C# Problem Overview


I am trying to compare two structs using equals (==) in C#. My struct is below:

public struct CisSettings : IEquatable<CisSettings>
{
    public int Gain { get; private set; }
    public int Offset { get; private set; }
    public int Bright { get; private set; }
    public int Contrast { get; private set; }

    public CisSettings(int gain, int offset, int bright, int contrast) : this()
    {
        Gain = gain;
        Offset = offset;
        Bright = bright;
        Contrast = contrast;
    }

    public bool Equals(CisSettings other)
    {
        return Equals(other, this);
    }

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

        var objectToCompareWith = (CisSettings) obj;

        return objectToCompareWith.Bright == Bright && objectToCompareWith.Contrast == Contrast &&
               objectToCompareWith.Gain == Gain && objectToCompareWith.Offset == Offset;
        
    }

    public override int GetHashCode()
    {
        var calculation = Gain + Offset + Bright + Contrast;
        return calculation.GetHashCode();
    }
}

I am trying to have struct as a property in my class, and want to check to see if the struct is equal to the value I am trying to assign it to, before I go ahead and do so, so I am not indicating the property has changed when it hasn't, like so:

public CisSettings TopCisSettings
{
    get { return _topCisSettings; }
    set
    {
        if (_topCisSettings == value)
        {
            return;
        }
        _topCisSettings = value;
        OnPropertyChanged("TopCisSettings");
    }
}

However, on the line where I check for equality, I get this error:

> Operator '==' cannot be applied to operands of type 'CisSettings' and > 'CisSettings'

I can't figure out why this is happening, could somebody point me in the right direction?

C# Solutions


Solution 1 - C#

You need to overload the == and != operators. Add this to your struct:

public static bool operator ==(CisSettings c1, CisSettings c2) 
{
    return c1.Equals(c2);
}

public static bool operator !=(CisSettings c1, CisSettings c2) 
{
   return !c1.Equals(c2);
}

Solution 2 - C#

When you override the .Equals() method, the == operator is not automatically overloaded. You need to do that explicitly.

See also Guidelines for Overriding Equals() and Operator == or CA1815: Override equals and operator equals on value types.

Solution 3 - C#

You don't implement explicitly an equality operator, so == is not defined particularly for the type.

Solution 4 - C#

You should overload your operator is some way like this:

public static bool operator ==(CisSettings a, CisSettings b)
{
    return a.Equals(b);
}

Solution 5 - C#

You need to override operator == explicitly.

public static bool operator ==(CisSettings x, CisSettings y) 
{
   return x.Equals(y);
}

By the way, you'd better put the comparing code in public bool Equals(CisSettings other), and let bool Equals(object obj) call bool Equals(CisSettings other), so that you can gain some performance by avoiding unnecessary type check.

Solution 6 - C#

you must overload "==" operator, but also overload "!=" operator. (Look at this Note)

For overloading operator, see this page

Solution 7 - C#

You can also use Record types since C# v9 and [record struct] value types since C# v10 to avoid writing tremendous amount of writing repeated code without any point

For more details see Microsoft docs here:

Equality operators (C# reference)

> Available in C# 9.0 and later, record types support the == and != > operators that by default provide value equality semantics. That is, > two record operands are equal when both of them are null or > corresponding values of all fields and auto-implemented properties are > equal.

public class RecordTypesEquality
{
    public record Point(int X, int Y, string Name);
    public record TaggedNumber(int Number, List<string> Tags);

    public static void Main()
    {
        var p1 = new Point(2, 3, "A");
        var p2 = new Point(1, 3, "B");
        var p3 = new Point(2, 3, "A");

        Console.WriteLine(p1 == p2);  // output: False
        Console.WriteLine(p1 == p3);  // output: True

        var n1 = new TaggedNumber(2, new List<string>() { "A" });
        var n2 = new TaggedNumber(2, new List<string>() { "A" });
        Console.WriteLine(n1 == n2);  // output: False
    }
}

Solution 8 - C#

Make a method and pass both stuct obj as parameter do compariosn one by one

public Save ReturnGreater(Save online,Save local)
{
    Save DataToSave = new Save();
    DataToSave.Score = local.Score < online.Score ? online.Score : local.Score;
    DataToSave.UnlockGuns = local.UnlockGuns < online.UnlockGuns ? online.UnlockGuns : local.UnlockGuns;
    DataToSave.UnlockLevels = local.UnlockLevels < online.UnlockLevels ? online.UnlockLevels : local.UnlockLevels;
    DataToSave.TotalLevels = local.TotalLevels;
    DataToSave.RemoveAds = local.RemoveAds;
    return DataToSave;
}

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionJMKView Question on Stackoverflow
Solution 1 - C#Jens KlosterView Answer on Stackoverflow
Solution 2 - C#Hans KestingView Answer on Stackoverflow
Solution 3 - C#Grant ThomasView Answer on Stackoverflow
Solution 4 - C#Denys DenysenkoView Answer on Stackoverflow
Solution 5 - C#ChenView Answer on Stackoverflow
Solution 6 - C#XaruthView Answer on Stackoverflow
Solution 7 - C#BijanView Answer on Stackoverflow
Solution 8 - C#Aqib CyberyView Answer on Stackoverflow