1

I have defined a struct Coords that explicitly implements three interfaces, each defined like this:

  public partial struct Coords
  {
    int           ICoordsUser.X          { get { return VectorUser.X; } }
    int           ICoordsUser.Y          { get { return VectorUser.Y; } }
    IntVector2D   ICoordsUser.Vector     { get { return VectorUser;   }
                                           set { VectorUser=value;    } }
    ICoordsCanon  ICoordsUser.Canon      { get { return this;         } } 
    ICoordsUser   ICoordsUser.Clone()    { return NewUserCoords(VectorUser);  }
    string        ICoordsUser.ToString() { return VectorUser.ToString(); }

    IEnumerable<NeighbourCoords> ICoordsUser.GetNeighbours(Hexside hexsides) { 
        return GetNeighbours(hexsides); 
    }
    int ICoordsUser.Range(ICoordsUser coords) { return Range(coords.Canon); }
  }

with the names ICoordsCanon, ICoordsUser, and ICoordsCustom. Then I have defined Value Equality on the struct like so:

#region Value Equality
bool IEquatable<Coords>.Equals(Coords rhs) { return this == rhs; }

public override bool Equals(object rhs) { 
  return (rhs is Coords) && this == (Coords)rhs; 
}

public static bool operator == (Coords lhs, Coords rhs) { 
  return lhs.VectorCanon == rhs.VectorCanon; 
}

public static bool operator != (Coords lhs, Coords rhs) { return ! (lhs == rhs); }
public override int GetHashCode() { return VectorUser.GetHashCode(); }

bool IEqualityComparer<Coords>.Equals(Coords lhs, Coords rhs) { return lhs == rhs; }
int  IEqualityComparer<Coords>.GetHashCode(Coords coords) {
    return coords.GetHashCode();
}
#endregion

However, when I perform an equality comparison with the == operator between values of one of the interface types, as

if (coordsUser1 == userCoords2) { /* whatever */ }

a reference comparison using object.== is always performed. Does anyone know how I can force value equality onto the == operator in such a circumstance, using C#?

Thank you in advance for any thoughts or suggestions.

[Edit] In the example above, both coordsUser1 and userCoords2 are instances of Coords stored in variables of type ICoordsUser, so it is not clear to me why the defined override of == is not being used.

0

1 Answer 1

5

Since you cannot define static members for an interface, you cannot define operators on an interface. Because operator overloading is resolved at compile-time, the compiler will not see any == operator that matches the signature given an interface type. Since Object defines the == operator for objects, and there is no better match at compile time, it will use that one.

There are three ways to solve this:

  1. Cast the left-hand object to the type that defines the == operator.

    return (Coords)coordsUser1 == userCoords2;
    
  2. Use the normal Equals(object) method. However, this will box your struct.

    return coordsUser1.Equals(userCoords2);
    
  3. Force your interfaces to implement IEquatable<T>, and use the generic Equals(T) (which reduces boxing).

    return coordsUser1.Equals(userCoords2);
    
Sign up to request clarification or add additional context in comments.

1 Comment

Method (3) is what I was using, when I wondered if there was an alternative.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.