Hello Bret~
I am using a hashtable that maps instances or Uri to objects. I cannot
derive the key's type from Uri because the object construction is outside my
code domain.
I also believe that there is a more general problem with using instances of
Uri as keys into hashtables. Look at the following code:
Uri u0 = new Uri("http://www.here.net/adoc?param=12a7665f334edd32");
Uri u1 = new Uri("http://www.here.net/adoc?param=1543ffefa23c34b5");
Uri u2 = new Uri("http://www.here.net/adoc?param=68e20c473edb271d");
Hashtable h = new Hashtable();
h[u0] = 1;
h[u1] = 2;
h[u2] = 3;
int a = (int)h[u0];
int b = (int)h[u1];
int c = (int)h[u2];
int count = h.Count;
Run the code and look at the values for a, b, c, and count. You will be more
than surprised!
BTW, the numbers I've chosen after param= are NOT random...
IMHO, people should be discouraged from using Uri as keys into hashtables
without explicitly specifying an IHashCodeProvider because the current
implementation of Uri breaks a vital rule: When o1.Equals(o2) is true, then
o1.GetHashCode() MUST be equal to o2.GetHashCode(). Everything else is a
bug.
"Bret Mulvey [MS]" <br***@online.microsoft.com> wrote in message
news:AC6tb.1328$Dw6.12421@attbi_s02...
"Michael Schollmeyer" <ms*****@web.de> wrote in message
news:bp**********@svr7.m-online.net... Hello,
The following code writes the text string:
Uri uri1 = new Uri("http://www.here.net/aplace?param=one");
Uri uri2 = new Uri("http://www.here.net/aplace?param=two");
int h1 = uri1.GetHashCode();
int h2 = uri2.GetHashCode();
bool e = uri1.Equals(uri2);
if (e == true && h1 != h2)
{
System.Console.WriteLine("Is is a bug or is it a feature?");
}
I thought the hash codes must be the same when two instances are equal. BTW, I found this because Uri's seem to be unusable as keys in a hashtable.
I am using the following versions:
Microsoft (R) Visual C# .NET Compiler version 7.10.3052.4
for Microsoft (R) .NET Framework version 1.1.4322
Cheers,
Michael
That's unexpected. The docs for Uri.Equals explain that it doesn't
consider fragments, but doesn't say anything about ignoring query strings. If you
rely on Equals to consider query data, you can certainly create a derived
class to provide the desired behavior:
class MyUri : Uri
{
public MyUri(string uri) : base(uri)
{
}
public override bool Equals(object comparand)
{
if (!base.Equals(comparand))
return false;
Uri uri = comparand as Uri;
if (uri == null)
return false;
return this.PathAndQuery == uri.PathAndQuery;
}
public override int GetHashCode()
{
return base.GetHashCode();
}
}
This doesn't work quite like Uri.Equals in the way it handles string
arguments, but you can extend it however you like.