85

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?

14
  • 4
    @JMK, maybe because you didn't override it... :) Commented Mar 4, 2013 at 10:13
  • 6
    if (obj == null || GetType() != obj.GetType()) is a very strange way to write if(!(obj is CisSettings)). Commented Mar 4, 2013 at 16:09
  • 4
    Also, the logic is in the wrong place: put the type-specific logic in Equals(CisSettings) and have Equals(object) call it, rather than the other way around. Commented Mar 4, 2013 at 16:12
  • 4
    Also, calling GetHashCode on a 32 bit integer is unnecessary; a 32 bit integer is its own hash code. Commented Mar 4, 2013 at 16:13
  • 5
    Also, your hash code has bad distribution if the four numbers tend to be similar values. Commented Mar 4, 2013 at 16:14

8 Answers 8

126

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); } 
Sign up to request clarification or add additional context in comments.

3 Comments

don't forget to overload "!=" operator also ;)
"Probably" has nothing to do with it; it is illegal to override == without overriding !=.
if you care about parformance you should consider implementing the == operator yourself. The above implementaiton causes boxing, which as described by Microsoft is "computationally expensive". Especially since you could just compare the 4 ints that your struct consists of.
11

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.

2 Comments

Just out of curiosity, is there a circumstance in which you'd want Equals() and == to return different values? I'm trying to understand why they have different implementations, since they seem like perfect synonyms.
@Nerrolken .Equals() is often used for value-equality while == is left to remain as reference-equality
5

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 } } 

Comments

3

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.

Comments

2

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

Comments

2

You should overload your operator is some way like this:

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

Comments

1

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

For overloading operator, see this page

Comments

0

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; } 

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.