How to implement IEquatable<Container<T>> in C# for all types T?

66 Views Asked by At

I have a simple, generic container class in C# that looks something like this -

public class Point<T>
{
    public T Data { get; }
    public string ID { get; }

    public Point(T x, string id)
    {
        this.Data = x;
        this.ID = id;
    }
}

I would like all Point objects to be compared solely based on the ID property. My question is - how can I implement IEquatable<Point> such that any Point objects can be compared to each other? For example, Point<int> could be compared to Point<decimal>, and the objects would be considered equal if their ID properties were identical.

1

There are 1 best solutions below

2
Sweeper On BEST ANSWER

A simple way is to extract a non-generic interface. Though it is not required for IEquatable, you can even include the Data property in this interface.

public interface IPoint {
    object? Data { get; }
    string ID { get; }
}

public class Point<T>: IPoint, IEquatable<IPoint> {
    public T Data { get; }
    
    object? IPoint.Data => Data;
    
    public string ID { get; }

    public Point(T x, string id) {
        this.Data = x;
        this.ID = id;
    }
    
    public bool Equals(IPoint? other) => ID == other?.ID;
    
    public override bool Equals(object? obj) {
        return Equals(obj as IPoint);
    }

    public override int GetHashCode() {
        return ID.GetHashCode();
    }
}

Though a caveat is that other code now can provide their own implementation of IPoint and their own implementation of IEquatable<IPoint>, that isn't consistent with your Point<T>. This could cause confusing behaviours such as implA.Equals(implB) not agreeing with implB.Equals(implA).