tags:

views:

100

answers:

3

This is VB.NET.

Does anyone have any idea what might cause the expression mentioned in the title to return False?

Things I am certain of:

  1. There are keys in the dictionary.
  2. The equality comparer returns a different hashcode for each key and that hashcode is always the same for the same input.
  3. Comparing someDictionary.Keys.First to a newly constructed object equivalent to the key returns True.
  4. someDictionary.Comparer.Equals(someDictionary.Keys.First, newObjectThatIsEquivalentToFirstKey) returns True.
  5. While someDictionary.Keys.First.GetHashCode always returns the same value (even across multiple program executions), calling GetHashCode on repeatedly recreated equivalent objects does not. The object in question is essentially just a 4-tuple of bools and the hashcode is New BitArray(New Boolean{} (obj.First, obj.Second, obj.Third, obj.Fourth}).GetHashCode
  6. UPDATE: Only one thread.

Update: Apparently, that hash code implementation does NOT always return the same value. I will attempt to diagnose if this is the problem.

A: 

What about a race condition?

Since the time Keys.First is retrieved, another thread changes the dictionary, then evaluation happens against a dictionary without that key?

Ariel
Only one thread. Added to certainties.
Daniel Straight
What you can do is to debug first into comparer and then in the dictionary, you can add breakpoints manually to ContainsKey() and see what's going on.(You may already know this, but in VS, you can do Breakpoints, New, Break at Function, then write your function's full name manually; that's a pretty useful feature.)
Ariel
A: 

So changing the hashcode to the hashcode of a concatenation of the string values of the booleans fixed the problem.

Oddly enough, when I ran the program, the hashcodes were always the same, but if I used the Immediate window in the debugger to query the hashcode, it was always different.

Daniel Straight
+2  A: 

Doing a dict.ContainsKey(dict.Keys.First) won't return true if the hash code of the Keys.First has changed since it was placed into the hash table.

The reason is that the two methods use separate lookups. dict.Keys.First does not depend on the hash code, and probably was just a pointer to an arbitrary "hash bucket", of which this item happens to be on top.

dict.ContainsKey(), however, uses the hash code to pick the bucket to look in. If the hash code of dict.Keys.First has changed since it was added, it may belong in a different hash bucket, but this isn't reflected or updated in the hash table; the object gets "lost" in the dictionary.

(In C#, but translatable to VB.NET, and un-tested)

class Foo { 
  public int i;

  public override int GetHashCode() {
    return i.GetHashCode();
  }
}

var dictionary = new Dictionary<Foo,string> ();
var foo = new Foo { i = 1; }
dictionary.Add (foo, "I was wrong.");
foo.i = 2;
if (dictionary.ContainsKey (dictionary.Keys.First)) {
  System.Console.WriteLine (dictionary[dictionary.Keys.First]);
} else {
  System.Console.WriteLine ("I was right.");
}
Marcus Griep
Well, in my case nothing was changing... well apparently SOMETHING was, but it wasn't in my code. It was in BitArray. Thanks for the info anyway. It's useful for reference.
Daniel Straight