Is it reference or value equality?

Probably reference. Checking for value equality is unintuitive – by default == is a reference equality check.

object a = 1;
object b = 1;
Assert.IsFalse (a == b);

Object a doesn’t equal object b since boxing a as object created once instance, and boxing b created another. Since == is a “reference type equality operator”, it will only compare the references.

Using any of these methods works fine:

Assert.IsTrue (a.Equals (b));
Assert.IsTrue (((int)a).Equals (b));
Assert.IsTrue (Object.Equals (a, b));
Assert.IsTrue ((int)a == (int)b);


When passing objects around, the simple solution is to use the Equals() method as it may perform value equality if the object overrides Equals(). So, value equality is somewhat easy to accomplish for individual objects, but you run into this problem again with collections:

Assert.IsFalse (
    new string[] { "abc", "def" }.Equals (
    new string[] { "abc", "def" }));
Assert.IsFalse (new int[] { 1, 2, 3 }.Equals (new int[] { 1, 2, 3 }));
Assert.IsFalse (
    new object[] { 4, "stuff", DateTime.Parse ("1/1/2004 1:00 AM") }.Equals (
    new object[] { 4, "stuff", DateTime.Parse ("January 1, 2004 01:00") }));


There is only reference equality with ArrayList since Object.Equals() is inherited not overridden.

Assert.IsFalse (
    new System.Collections.ArrayList (new int[] { 1, 2, 3 }) == 
    new System.Collections.ArrayList (new int[] { 1, 2, 3 }));
Assert.IsFalse (
    new System.Collections.ArrayList (new int[] { 1, 2, 3 }).Equals (
    new System.Collections.ArrayList (new int[] { 1, 2, 3 })));


Here’s my solution to perform value equality for collections. And now:

Assert.IsTrue (Collection.Equals (
    new System.Collections.ArrayList (new int[] { 1, 2, 3 }), 
    new System.Collections.ArrayList (new int[] { 1, 2, 3 }), true));
Assert.IsTrue (Collection.Equals (
    new int[] { 1, 2, 3 }, new System.Collections.ArrayList (
    new int[] { 1, 2, 3 }), true));
Assert.IsTrue (Collection.Equals (
    new object[] { 1, 2, 3 }, 
    new int[] { 1, 2, 3 }), true);
Assert.IsTrue (Collection.Equals (
    new object[] { 4, "stuff", DateTime.Parse ("1/1/2004 1:00 AM") }, 
    new object[] { 4, "stuff", DateTime.Parse ("January 1, 2004 01:00") }), true);


Here’s a real world example:

/// <summary>Always accepts the public key hardcoded in the byte array as a valid certificate.</summary>
public sealed class AcceptTrustedCertificate : ICertificatePolicy {
    public bool CheckValidationResult (
        ServicePoint srvPoint,
        X509Certificate certificate,
        WebRequest request,
     &nbs
p;  int certificateProblem) {
        //TODO: verify certificateProblem is an acceptable value
 
        // return true if certificate returned is equal to the certificate's public key
        return Collection.Equals (
            certificate.GetPublicKey (),
            new byte[] { 48, 130, 1, 10, 2, 130, 1, 1, 0, 206, 214, 212 }, true);
    }
}

4 comments on “Is it reference or value equality?

  1. Good job! Although isn’t it possible to do the same using IComparable? In fact in generics using the dictionary stack (I think) is able to the same thing. However, this is based on a Key value pair, this is a nice low level equality check. There might be other generic classes in .NET 2.0 that might address this short coming. Again good stuff!

  2. Both the IComparable.CompareTo and IComparer.Compare method return if x > y, x = y, or x < y. This function only checks value equality for collections. I\'ve posted a RelaxComparer class that Implements the IComparer interface in a more relaxed way than the default Comparer class, and have implemented a CollectionEquality method that tests collection equality based on the value and count of each item in the collection, regardless of position.

  3. These facts are really interesting. Few of them were well known for me but many of them were brand new for me too! I will print this one out and show to my friends because they will be definitely interested in that

Comments are closed.