I have some simple struct, which overrides the Equals()
method:
public struct Pair<T> {
public Pair(T x, T y) {
X = x; Y = y;
}
public T X { get; }
public T Y { get; }
public override bool Equals(object obj) {
var otherPair = (Pair<T>) obj;
return X.Equals(otherPair.X);
}
}
According to MSDN, value types without an Equals()
method are compared as follows:
If none of the fields of the current instance and obj are reference types, the Equals method performs a byte-by-byte comparison of the two objects in memory. Otherwise, it uses reflection to compare the corresponding fields of obj and this instance.
I wish to compare Pair
s using the quoted approach instead of using Pair
's own Equals()
method, so that the following test passes:
[Test]
public void PairsEqual()
{
var p1a = new Pair<int>(10, 1);
var p1b = new Pair<int>(10, 1);
var p2 = new Pair<int>(10, 2);
Assert.That(p1a, Is.Not.EqualTo(p2));
Assert.That(p1a, Is.EqualTo(p1a));
Assert.That(p1a, Is.EqualTo(p1b));
}
This should ultimately work like a ReferenceEqual
for structs. Is this possible? Ideally, I would like to replace the comparison with the original ValueType.Equals()
method.
Edit:
My real wish is to be able to add a code contract to a class like this:
public class Holder<T> {
private T _item;
public Holder(T item) {
_item = item;
}
public T Item {
get { return _item; }
set {
Contract.Ensures(_item.Equals(value));
_item = value; // <-- imagine this like contained a bug
}
}
}
Imagine I use the holder object like this:
var holder = new Holder<Pair<int>>(p1a);
holder.Item = p2;
If set
wasn't _item = value;
but rather _item = _item;
, the contract wouldn't complain, since the example would use Pair<T>
's Equals()
method, which says that p1a and p2 are equal. If it instead use the original ValueType.Equals()
method using byte comparison/reflection, the contract would have been violated correctly and the mistake would have been caugt.
Using objects, the contract would instead have been something like Contract.Ensures(ReferenceEqual(_item, value)
but that doesn't work for value types (structs).
The point is that I don't know the type of T
in Holder<T>
, so I cannot introduce my own custom equality comparer, even if I wanted.