Comparing two structs using ==
C#StructEqualityC# 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;
}