Skip to Content

Is it reference or value equality in c#?

Checking for value equality is unintuitive and inconsistent

Posted on 2 mins read

Probably reference equality - checking for value equality is unintuitive and inconsistent for objects. By default == is a reference equality check.

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

a doesn’t equal b because boxing creates one object instance for a, and another instance is created for b (two different locations in memory containing the same data). The double equals, ==, is a “reference type equality operator” and will only compare the object references.

Using any of these methods work as expected:

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 can be accomplished for individual objects, but you hit 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:

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,
        int certificateProblem) {
        // 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);
    }
}