Friday, June 16, 2006

Change in v2.0 Delegate.GetHashCode()

There has been a subtle but interesting change to the implementation of Delegate.GetHashCode() in v2.0

Previously it was a function of the method pointer value in v1.x:
public override int GetHashCode() {
if (this.IsStatic()) {
return this._methodPtrAux.ToInt32();
}
return this._methodPtr.ToInt32();
}


This has totally changed with v2.0 - instead they now (scuse the pun) delegate the call to the System.Type for the delegate type:

public override int GetHashCode() {
return base.GetType().GetHashCode();
}

Of course, it's totally fine that two different objects produce the same hashcode when added into the same hashtable. It just means the lookup algorithm will take a little longer.

Compiling the code below [1] under v1.x and v2.0 will highlight the change. Under v1.x the code produces this output:
10244731 == 10244747
bob
steve

under v2.0 it produces this output:
2031146524 == 2031146524
bob
steve

[1]
using System;
using System.Collections;

class app {
static void Func1(object sender, EventArgs args) { Console.WriteLine("hi"); }
static void Func2(object sender, EventArgs args) { }

static void Main() {
EventHandler eh1 = new EventHandler(Func1);
EventHandler eh2 = new EventHandler(Func2);

//output is different on v1.x but same on v2.0
Console.WriteLine("{0} == {1}", eh1.GetHashCode(),
eh2.GetHashCode());

Hashtable dict = new Hashtable();
dict.Add(eh1, "bob");
dict.Add(eh2, "steve");

Console.WriteLine(dict[eh1]); //output is: bob
Console.WriteLine(dict[eh2]); //output is: steve
}
}

0 comments: