Surprising Tuple (in)equality

aoven picture aoven · Feb 21, 2011 · Viewed 13.2k times · Source

Until today, my understanding of .NET Tuple classes had been that they delegate their implementation of Equals() to their contents, allowing me to equate and compare them "by value".

Then this test came along and made a fool out of me:

[TestMethod]
public void EquateTwoTuplesWithSameContent()
{
    var t1 = Tuple.Create("S");
    var t2 = Tuple.Create((object)t1.Item1);
    Assert.IsTrue(t1.Equals(t2)); // Boom!
}

Reading through MSDN documentation and various blogs has left me with more questions. From what I gather, it would seem that Tuple<object> and Tuple<TWhatever> are always considered not equal, regardless of the fact that both instances may wrap the same object (boxed or typecast - it's all the same).

Is this really how Tuples are supposed to behave? Is structural compatibility actually an additional constraint on equality as opposed to a relaxation, as I've been interpreting it until now?

If so, is there anything else in the BCL that I can use to meet the expectations of the above unit test?

Thank you in advance!

Answer

KeithS picture KeithS · Feb 21, 2011

Tuples require the following to be true for the objects to be considered "equal":

  • Must be a Tuple object with the same number of generic parameter(s) as the current object.
  • Each of those generic parameters must be of the same type as the other.
  • Each member of the tuple must have the same value as the corresponding member of the other.

So, because a Tuple<object> has a different generic parameter than a Tuple<string>, they are not equal even if the object is actually a reference to a string of the same value as the strongly-typed Tuple<string>.