Over a million developers have joined DZone.
{{announcement.body}}
{{announcement.title}}

The Innocuous Code That Tripped Me

DZone's Guide to

The Innocuous Code That Tripped Me

Sometimes the code that breaks on us when we believe it shouldn't breaks because of something we've long since stopped thinking about.

· Performance Zone
Free Resource

When building a cache, I need a way to generate a hash code from a query. A query is a complex object that has many properties. My first attempt to do so looked like this:

public int GetHashCode()
{
  int hashCode = QueryStr.GetHashCode();
  hashCode = (hashCode * 397) ^ WaitForNonStaleResultsTimeout?.GetHashCode() ?? 0;
  hashCode = (hashCode * 397) ^ AllowStale.GetHashCode();
  return hashCode;
}

And it failed, disastrously. All queries always had the same hash code, and I couldn’t figure out why until I actually debugged through the code.

Here is a hint: this only happened if WaitForNonStaleResultsTimeout is null. It might be better to also look at the way the compiler looks at this:

public unsafe override int GetHashCode()
{
    int num = this.QueryStr.GetHashCode() * 397;
    TimeSpan?* expr_18 = ref this.WaitForNonStaleResultsTimeout;
    return ((num ^ 
      (expr_18.HasValue ?
          new int?(expr_18.GetValueOrDefault().GetHashCode()) : null)) ?? 0
        ) * 397
        ^ this.AllowStale.GetHashCode();
}

Basically, if WaitForNonStaleResultsTimeout is null, the entire expression evaluated to null, so we return zero, losing all the previous hash values that we put in.

The solution was to parenthesis the expression, but this is something that passed a couple rounds of scrutiny and didn’t show up at all, because it looked fine, and I don’t keep the precedence rules for operators in C# in my head.

Topics:
c# ,ravendb ,performance ,query ,hash code

Published at DZone with permission of Oren Eini, DZone MVB. See the original article here.

Opinions expressed by DZone contributors are their own.

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}