Navigation
Links

Powered by Squarespace
« IPAddress class serializable? | Main | XML/object libraries are deprecated »
Thursday
Aug262004

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,
        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);
    }
}

Reader Comments (3)

I am sure this will be helpful for more than a handful of people. Nicely done.

September 4, 2004 | Unregistered CommenterDavid Collantes

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!

November 17, 2004 | Unregistered CommenterEddy Recio

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.

December 2, 2004 | Unregistered CommenterGeorge Tsiokos

PostPost a New Comment

Enter your information below to add a new comment.

My response is on my own website »
Author Email (optional):
Author URL (optional):
Post:
 
Some HTML allowed: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <code> <em> <i> <strike> <strong>