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.

Free Resource

SignalFx is the only real-time cloud monitoring platform for infrastructure, microservices, and applications. The platform collects metrics and traces across every component in your cloud environment, replacing traditional point tools with a single integrated solution that works across the stack.

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.

SignalFx is built on a massively scalable streaming architecture that applies advanced predictive analytics for real-time problem detection. With its NoSample™ distributed tracing capabilities, SignalFx reliably monitors all transactions across microservices, accurately identifying all anomalies. And through data-science-powered directed troubleshooting SignalFx guides the operator to find the root cause of issues in seconds.

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

Published at DZone with permission of

Opinions expressed by DZone contributors are their own.

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

{{ parent.tldr }}

{{ parent.urlSource.name }}