Geeks With Blogs
New Things I Learned

Recently we have to create methods that will manually compare 2 objects and see if they are equal – essentially check if all their properties / fields are equal.  Some of the fields are Nullable Types, which have been available since .NET 2.0 (VS2005).  It is a nice construct to have, especially to represent database fields that can also be null – this makes coding simpler because a nullable type can also contain null as a valid value.  Interestingly, talking some some people that have done .NET for awhile, very few actually ever uses it.  It’s pretty nifty actually.

For typical primitive types, we just call the Equals method – as an added bonus, most primitive types implement IEquatable<T> which means it won’t do boxing/unboxing for value types.  So when we get to these nullable types, of course there’s some wonder as to whether the Equals method will work or not.  Well, first off, there’s actually some wonderment if the code will actually crash or not.  Consider the following code:

Nullable<int> first = 5;
Nullable<int> second = 7;
bool b = first.Equals(second);

Now, the above code looks fairly benign, the code creates 2 Nullable integers and then compare the values.  Nullable Types constructs are not special – it is implemented using generics, using the Nullable<T> construct.  What happens is that in C#, there’s a shortcut to create these nullable types; the above code can also be written as follows:

int? first = 5;
int? second = 7;
bool b = first.Equals(second);

Other than the declaration, nothing is different.  It’s essentially just shorthand for C# (same shorthand for VB.NET as well) – however some developers are so used to this construct that they may have forgotten that behind the scenes it is translated as creating an instance of the Nullable<T> construct and may actually consider these declarations as native types themselves.  As such, the following code looks a bit… concerning:

int? first = null;
int? second = 7;
bool b = first.Equals(second);

At a glance, it looks like it’s a guaranteed crash – first is assigned to null, so it definitely will crash when you try to access its instance method, right?  But the above code actually works – it will return false & assign it to b.  But how?  Well, that’s because the declaration int? is just a shorthand for Nullable<int> and Nullable<T> is a value-type.  A value type cannot be null – it’ll always have an instance to it.  As such, calling the instance method doesn’t crash the program.  With nullable types, regardless of the value of the first or second variable being compared, the call to the Equals method will always be successful.

However, the Equals method that is called accepts an object as its first parameter – which meant that there will be boxing/unboxing of the values as they’re being passed into the method.  I’m actually surprised that there is no overload within the Nullable<T> construct itself that will compare against another Nullable<T> instance.  .NET provides this through the Nullable class, but it just seems weird that they didn’t implement it inside the object model itself.  So, with the advent of Extension Methods in .NET 3.0, we try to make this to be friendlier.

public static class NullableExtensionMethods
{
   public static bool IsEqualTo<T>(this Nullable<T> first, Nullable<T> second)
      where T : struct, IEquatable<T>
   {
      // if one is null, the other is not, then obviously it's not equal
      if (first.HasValue != second.HasValue) 
         return false;

      // Both either null or not null - if one is null, then they're equal
      if (first.HasValue == false)
         return true;

      // Compare by calling the IEquatable implementation
      return first.Value.Equals(second);
   }

   public static bool IsEqualTo<T>(this Nullable<T> first, T second)
      where T : struct, IEquatable<T>
   {
      // If first is null, then obviously not equal
      return first.HasValue ? first.Value.Equals(second) : false;
   }
}

The preceeding code will basically allow any nullable types variables to call the IsEqualTo method and compare it against the supplied parameter, assuming they’re the same type.  The biggest drawback to these extension methods is that they have to be named differently; per the method invocation on extension methods, the instance method implementation will always be called first as long as the parameter supplied fulfills the instance method signature.  And since the parameter of the Equals method is an object, that particular implementation will always be the one that gets called – thus the extension methods have to use a different name.

On a microscopic level, this implementation is also faster – about 2.5 times faster.  But we’re at the splitting microseconds here – on my test PC, which is not very powerful, the instance implementation takes about 2-3 microseconds each, while the above extension method implementation is about a microsecond.  We’re still talking about 1 second can call millions of times to these methods, but it was interesting to note that boxing/unboxing have a measurable cost compared to extension methods.

Posted on Friday, July 31, 2009 5:59 AM | Back to top


Comments on this post: Comparing Nullable Values

# re: Comparing Nullable Values
Requesting Gravatar...
You have celebrated my joy. You have shared your wisdom and your love with me. I am truly blessed to have this in my life
Left by casino on Apr 25, 2011 5:14 PM

# re: Comparing Nullable Values
Requesting Gravatar...
singleton patter xD
Left by deiMudda on Jan 31, 2012 1:47 AM

Your comment:
 (will show your gravatar)


Copyright © Muljadi Budiman | Powered by: GeeksWithBlogs.net