Question regarding declaration of equality operators in C# - c#

This seems incredibly basic, but I couldn't find any other answers on this particular note. In declaring a == operator in C#, you must also declare the != operator. Obviously every case may vary based on type, but if a type has explicit equality or does not, is it reasonable to declare != as simply !(a == b)? Is there a reason NOT to do this? For example:
public static bool operator ==(Point p1, Point p2)
{
return ((p1.X == p2.x) && (p1.Y == p2.Y));
}
public static bool operator !=(Point p1, Point p2)
{
return !(p1 == p2);
}

There is a good example from Microsoft Docs: How to: Define Value Equality for a Type covering important aspects of defining equality for types.
In the following example, for x!=y you see it's simply returning !(x==y):
using System;
class TwoDPoint : IEquatable<TwoDPoint>
{
// Readonly auto-implemented properties.
public int X { get; private set; }
public int Y { get; private set; }
// Set the properties in the constructor.
public TwoDPoint(int x, int y)
{
if ((x < 1) || (x > 2000) || (y < 1) || (y > 2000))
{
throw new System.ArgumentException("Point must be in range 1 - 2000");
}
this.X = x;
this.Y = y;
}
public override bool Equals(object obj)
{
return this.Equals(obj as TwoDPoint);
}
public bool Equals(TwoDPoint p)
{
// If parameter is null, return false.
if (Object.ReferenceEquals(p, null))
{
return false;
}
// Optimization for a common success case.
if (Object.ReferenceEquals(this, p))
{
return true;
}
// If run-time types are not exactly the same, return false.
if (this.GetType() != p.GetType())
{
return false;
}
// Return true if the fields match.
// Note that the base class is not invoked because it is
// System.Object, which defines Equals as reference equality.
return (X == p.X) && (Y == p.Y);
}
public override int GetHashCode()
{
return X * 0x00010000 + Y;
}
public static bool operator ==(TwoDPoint lhs, TwoDPoint rhs)
{
// Check for null on left side.
if (Object.ReferenceEquals(lhs, null))
{
if (Object.ReferenceEquals(rhs, null))
{
// null == null = true.
return true;
}
// Only the left side is null.
return false;
}
// Equals handles case of null on right side.
return lhs.Equals(rhs);
}
public static bool operator !=(TwoDPoint lhs, TwoDPoint rhs)
{
return !(lhs == rhs);
}
}

Related

C# Dictionary that uses an Unordered Pair as its Key?

I'm trying to create a Dictionary is C# that takes an Unordered Pair of Indices as its Key.
For example:
exampleDictionary[new UnorderedPair(x,y)] and exampleDictionary[new UnorderedPair(y,x)] should both return the same value.
Is there a way to create a custom unordered collection other than using a HashSet? Or some way to create an unordered Tuple?
This question is similar to what I'm trying to accomplish, except in C# rather than python.
If the type is not your own or you can't or don't want to modify refer to Theodor Zoulias's answer
Otherwise, assuming that UnorderedPair is your own class you can modify what you could do is e.g.
[Serializable]
public class UnorderedPair<T> : IEquatable<UnorderedPair<T>>
{
public T X;
public T Y;
public UnorderedPair()
{
}
public UnorderedPair(T x, T y)
{
X = x;
Y = y;
}
public bool Equals(UnorderedPair<T> other)
{
if (ReferenceEquals(null, other))
{
return false;
}
if (ReferenceEquals(this, other))
{
return true;
}
// For equality simply include the swapped check
return X.Equals(other.X) && Y.Equals(other.Y) || X.Equals(other.Y) && Y.Equals(other.X);
}
public override bool Equals(object obj)
{
if (ReferenceEquals(null, obj))
{
return false;
}
if (ReferenceEquals(this, obj))
{
return true;
}
if (obj.GetType() != GetType())
{
return false;
}
return Equals((UnorderedPair<T>)obj);
}
public override int GetHashCode()
{
// and for the HashCode (used as key in HashSet and Dictionary) simply order them by size an hash them again ^^
var hashX = X == null ? 0 : X.GetHashCode();
var hashY = Y == null ? 0 : Y.GetHashCode();
return HashCode.Combine(Math.Min(hashX,hashY), Math.Max(hashX,hashY));
}
public static bool operator ==(UnorderedPair<T> left, UnorderedPair<T> right)
{
return Equals(left, right);
}
public static bool operator !=(UnorderedPair<T> left, UnorderedPair<T> right)
{
return !Equals(left, right);
}
}
and then e.g.
var testDict = new Dictionary<UnorderedPair<int>, string>();
testDict.Add(new UnorderedPair<int>(1,2), "Hello World!");
Console.WriteLine(testDict[new UnorderedPair<int>(2,1)]);
As per suggestion by Jodrell in the comments you could even make the types swappable - not sure this would be ever needed - but this way you could even have a pair of different types:
[Serializable]
public class UnorderedPair<TX, TY> : IEquatable<UnorderedPair<TX, TY>>
{
public TX X;
public TY Y;
public UnorderedPair()
{
}
public UnorderedPair(TX x, TY y)
{
X = x;
Y = y;
}
public UnorderedPair(TY y, TX x)
{
X = x;
Y = y;
}
public override int GetHashCode()
{
// and for the HashCode (used as key in HashSet and Dictionary) simply order them by size an hash them again ^^
var hashX = X == null ? 0 : X.GetHashCode();
var hashY = Y == null ? 0 : Y.GetHashCode();
var combine = HashCode.Combine(Math.Min(hashX, hashY), Math.Max(hashX, hashY));
return combine;
}
public bool Equals(UnorderedPair<TX, TY> other)
{
if (ReferenceEquals(null, other))
{
return false;
}
if (ReferenceEquals(this, other))
{
return true;
}
if (typeof(TX) != typeof(TY))
{
return EqualityComparer<TX>.Default.Equals(X, other.X) && EqualityComparer<TY>.Default.Equals(Y, other.Y);
}
return EqualityComparer<TX>.Default.Equals(X, other.X) && EqualityComparer<TY>.Default.Equals(Y, other.Y)
|| X.Equals(other.Y) && Y.Equals(other.X);
}
public override bool Equals(object obj)
{
if (ReferenceEquals(null, obj))
{
return false;
}
if (ReferenceEquals(this, obj))
{
return true;
}
return obj switch
{
UnorderedPair<TX, TY> other => Equals(other),
UnorderedPair<TY, TX> otherSwapped => Equals(otherSwapped),
_ => false
};
}
public static bool operator ==(UnorderedPair<TX, TY> left, UnorderedPair<TX, TY> right)
{
return Equals(left, right);
}
public static bool operator !=(UnorderedPair<TX, TY> left, UnorderedPair<TX, TY> right)
{
return !Equals(left, right);
}
public static implicit operator UnorderedPair<TX, TY>(UnorderedPair<TY, TX> pair)
{
return new UnorderedPair<TX, TY>(pair.Y, pair.X);
}
}
and
var testDict = new Dictionary<UnorderedPair<int, double>, string>();
testDict.Add(new UnorderedPair<int, double>(1,2.5), "Hello World!");
Console.WriteLine(testDict[new UnorderedPair<double,int>(2.5,1)]);
(.NET Fiddle for both)
You could write a custom IEqualityComparer<UnorderedPair<T>> implementation, and pass it as argument to the constructor of your Dictionary<UnorderedPair<TKey>, TValue>. This way you won't have to modify your UnorderedPair<T> type, by overriding its Equals and GetHashCode methods. Below is an example of such a comparer for the ValueTuple<T1, T2> struct, with both T1 and T2 being the same type:
class UnorderedValueTupleEqualityComparer<T> : IEqualityComparer<(T, T)>
{
private readonly IEqualityComparer<T> _comparer;
public UnorderedValueTupleEqualityComparer(IEqualityComparer<T> comparer = default)
{
_comparer = comparer ?? EqualityComparer<T>.Default;
}
public bool Equals((T, T) x, (T, T) y)
{
if (_comparer.Equals(x.Item1, y.Item1)
&& _comparer.Equals(x.Item2, y.Item2)) return true;
if (_comparer.Equals(x.Item1, y.Item2)
&& _comparer.Equals(x.Item2, y.Item1)) return true;
return false;
}
public int GetHashCode((T, T) obj)
{
int h1 = _comparer.GetHashCode(obj.Item1);
int h2 = _comparer.GetHashCode(obj.Item2);
if (h1 > h2) (h1, h2) = (h2, h1);
return HashCode.Combine(h1, h2);
}
}
Usage example:
Dictionary<(int, int), string> dictionary = new(
new UnorderedValueTupleEqualityComparer<int>());
Inspired by #derHugo's answer and my comments on it,
Fiddle here
A generic implementation,
#nullable enable
public class UnorderedPair<T> : IEquatable<UnorderedPair<T>>
{
private static IEqualityComparer<T> comparer = EqualityComparer<T>.Default;
public T X { get; }
public T Y { get; }
public UnorderedPair(T x, T y)
{
X = x;
Y = y;
}
public bool Equals(UnorderedPair<T>? other)
{
if(other is null)
{
return false;
}
if (ReferenceEquals(this, other))
{
return true;
}
// For equality simply include the swapped check
return
comparer.Equals(X, other.X) && comparer.Equals(Y, other.Y)
||
comparer.Equals(X, other.Y) && comparer.Equals(Y, other.X);
}
public override bool Equals(object? obj)
{
return Equals(obj as UnorderedPair<T>);
}
public override int GetHashCode()
{
unchecked
{
return
(X is null ? 0 : comparer.GetHashCode(X))
+
(Y is null ? 0 : comparer.GetHashCode(Y));
}
}
public static bool operator ==(UnorderedPair<T>? left, UnorderedPair<T>? right)
{
return Equals(left, right);
}
public static bool operator !=(UnorderedPair<T>? left, UnorderedPair<T>? right)
{
return !Equals(left, right);
}
}
#nullable disable

Checking against null in Equals()

How come if I comment out the second line when overriding Equals() like so:
public override bool Equals(object obj) {
if(object.ReferenceEquals(this, obj)) return true;
//if(obj == null) return false;
Person other = obj as Person;
if(other == null) return false;
return this.Name == other.Name;
}
I get a NullReferenceException? If I uncomment it, it'll work. Also I made sure that the obj argument wasn't a null, and it still does that.
Here is full code
namespace MyNameSpace{
class Person : IComparable<Person>{
public string Name { get; set; }
public Person(string name) {
Name = name;
}
public static bool operator <(Person x, Person y) {
return x.CompareTo(y) < 0;
}
public static bool operator >(Person x, Person y) {
return x.CompareTo(y) > 0;
}
public static bool operator ==(Person x, Person y) {
return x.Equals(y);
}
public static bool operator !=(Person x, Person y) {
return !x.Equals(y);
}
public override bool Equals(object obj) {
if(object.ReferenceEquals(this, obj)) return true;
//if(obj == null) return false;
Person other = obj as Person;
if(other == null) return false;
return this.Name == other.Name;
}
public int CompareTo(Person other) {
return this.Name.CompareTo(other.Name);
}
}
class Program {
static void Main(string[] args) {
Person one = new Person("one");
Person two = new Person("two");
Console.WriteLine(one == two);
}
}
}
I suspect you have a custom == operator on Person, which is being invoked by the line:
if(other == null) return false;
Which also hints that the operator is buggy and should be fixed.
Edit: and with your update: here is the buggy custom == operator:
public static bool operator ==(Person x, Person y) {
return x.Equals(y);
}
Using just:
public static bool operator ==(Person x, Person y) {
return Equals(x,y);
}
would solve that, along with:
public override bool Equals(object obj) {
if(obj == (object)this) return true; // ref equality, the cheap way
if(obj is Person) {
Person other = (Person)obj;
return this.Name == other.Name;
}
return false;
}
As a general rule for IComparable implementation, I would strongly recommend Eric Lippert's approach. It's very simple and helps a lot to not get NRE.
Basically, you don't call either Equals or == in any operator overload. You just call a unique static method that does all the job:
public int CompareTo(Natural x) { return CompareTo(this, x); }
public static bool operator <(Natural x, Natural y) { return CompareTo(x, y) < 0; }
public static bool operator >(Natural x, Natural y) { return CompareTo(x, y) > 0; }
public static bool operator <=(Natural x, Natural y) { return CompareTo(x, y) <= 0; }
public static bool operator >=(Natural x, Natural y) { return CompareTo(x, y) >= 0; }
public static bool operator ==(Natural x, Natural y) { return CompareTo(x, y) == 0; }
public static bool operator !=(Natural x, Natural y) { return CompareTo(x, y) != 0; }
public override bool Equals(object obj) { return CompareTo(this, obj as Natural) == 0; }
public bool Equals(Natural x) { return CompareTo(this, x) == 0; }
// negative means x < y
// positive means x > y
// zero means x == y
// two nulls are equal
// otherwise, null is always smaller
private static int CompareTo(Natural x, Natural y) {
if (ReferenceEquals(x, y))
return 0;
else if (ReferenceEquals(x, null))
return -1;
else if (ReferenceEquals(y, null))
return 1;
else if (ReferenceEquals(x, Zero))
return -1;
else if (ReferenceEquals(y, Zero))
return 1;
else if (x.head == y.head)
return CompareTo(x.tail, y.tail);
else if (x.head == ZeroBit)
return CompareTo(x.tail, y.tail) > 0 ? 1 : -1;
else
return CompareTo(x.tail, y.tail) < 0 ? -1 : 1;
}
I get it, I was recursively calling operator ==, and at some point i had operator == (x, y), where x and y were both null, and then I did x.Equals(), that's why it threw that exception.

Implementing == operator in C# on explicit-interface implementation

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.
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:
Cast the left-hand object to the type that defines the == operator.
return (Coords)coordsUser1 == userCoords2;
Use the normal Equals(object) method. However, this will box your struct.
return coordsUser1.Equals(userCoords2);
Force your interfaces to implement IEquatable<T>, and use the generic Equals(T) (which reduces boxing).
return coordsUser1.Equals(userCoords2);

What do I need to do for this line of code? (C#)

I'm trying to get an if statment that says if my Points Array at "i" (Initialized in a For Loop) is equal to the X and Y of a Circle (Which is set to smallcircle.X and smallcircle.Y). I know what I need to do in the if statment, but I can't get the if statment itself to work. What is the syntax for that?
Currently Have:
if (centerPoints[i] == smallcircle.X, smallcircle.Y)
It doesn't like that one bit.
Probably this:
if (centerPoints[i].X == smallcircle.X && centerPoints[i].Y == smallcircle.Y)
centerPoints[i] is an instance of Point, right?
In which case, this...
if (centerPoints[i] == new Point(smallcircle.X, smallcircle.Y))
... should do the trick
update
What type is your Circle? If it's yours then why doesn't it have a Centre property of type Point. This would make your life easier.
if ((centerPoints[i].X == smallcircle.X) && (centerPoints[i].Y == smallcircle.Y))
One more thing:
If this is the only thing your for loop is doing, you can write the whole loop like this:
foreach (Point point in centerPoints.Where(p => p.X == smallcircle.X && p.Y == smallcircle.Y) )
{
//
}
You're looking for the logical AND operator, which in C# is &&. It's used to check if both conditions are true.
So that:
if( pts[i] == smallcircle.X && pts[i] == smallcircle.Y ) {
// Both are true so do this...
}
If you want to check if EITHER condition is true, use the logial OR operator, ||:
if( pts[i] == smallcircle.X || pts[i] == smallcircle.Y ) {
// Either one or the other condition is true, so do this...
}
Another option is to override the Equals() method in your Point struct, here's an example of one that I've used:
struct Point
{
public int X;
public int Y;
public Point(int x, int y) { X = x; Y = y; }
public override bool Equals(object obj)
{
return obj is Point && Equals((Point)obj);
}
public bool Equals(Point other)
{
return (this.X == other.X && this.Y == other.Y);
}
public override int GetHashCode()
{
return X ^ Y;
}
public override string ToString()
{
return String.Format("({0}, {1})", X, Y);
}
public static bool operator ==(Point lhs, Point rhs)
{
return (lhs.Equals(rhs));
}
public static bool operator !=(Point lhs, Point rhs)
{
return !(lhs.Equals(rhs));
}
public static double Distance(Point p1, Point p2)
{
return Math.Sqrt((p1.X - p2.X) * (p1.X - p2.X) + (p1.Y - p2.Y) * (p1.Y - p2.Y));
}
}
So your code would become:
Point smallcircle = new Point(5, 5);
if (centerPoints[i] == smallcircle)
{
// Points are the same...
}

== operator overloading when object is boxed

The output of the below code is as following:
not equal
equal
Note the difference in type of x and xx and that == operator overload is only executed in the second case and not in the first.
Is there a way I can overload the == operator so that its always executed when a comparison is done on between MyDataObejct instances.
Edit 1:# here i want to override the == operator on MyDataClass , I am not sure how I can do it so that case1 also executes overloaded == implementation.
class Program {
static void Main(string[] args) {
// CASE 1
Object x = new MyDataClass();
Object y = new MyDataClass();
if ( x == y ) {
Console.WriteLine("equal");
} else {
Console.WriteLine("not equal");
}
// CASE 2
MyDataClass xx = new MyDataClass();
MyDataClass yy = new MyDataClass();
if (xx == yy) {
Console.WriteLine("equal");
} else {
Console.WriteLine("not equal");
}
}
}
public class MyDataClass {
private int x = 5;
public static bool operator ==(MyDataClass a, MyDataClass b) {
return a.x == b.x;
}
public static bool operator !=(MyDataClass a, MyDataClass b) {
return !(a == b);
}
}
No, basically. == uses static analysis, so will use the object ==. It sounds like you need to use object.Equals(x,y) instead (or x.Equals(y) if you know that neither is null), which uses polymorphism.
Here is a description on how to override Equals and the == operator:
http://msdn.microsoft.com/en-us/library/ms173147(VS.80).aspx
This is how it looks (provided that you have already made an overload of Equals()):
public static bool operator ==(MyDataClass a, MyDataClass b)
{
// If both are null, or both are same instance, return true.
if (System.Object.ReferenceEquals(a, b))
{
return true;
}
// If one is null, but not both, return false.
if (((object)a == null) || ((object)b == null))
{
return false;
}
// Otherwise use equals
return a.Equals(b);
}
public override bool Equals(System.Object obj)
{
// If parameter is null return false.
if (obj == null)
{
return false;
}
// If parameter cannot be cast to MyDataClass return false.
MyDataClass p = obj as MyDataClass;
if ((System.Object)p == null)
{
return false;
}
return (x == p.x);
}

Categories

Resources