Force Dictionary to use Identity versus Equality

J

jehugaleahsa

Hello:

Is there a way to force a Dictionary to determine equivilence by
memory location?

I have a generic class where I don't want to treat equal items as
identical items. Only when two references point to the same instance
do I want to treat them as the same dictionary key.

Any help?

Thanks,
Travis
 
J

jehugaleahsa

I created an IdentityComparer like this:

public class IdentityComparer : IEqualityComparer<TDataRecord>
{
public bool Equals(TDataRecord x, TDataRecord y)
{
return Object.ReferenceEquals(x, y);
}

public int GetHashCode(TDataRecord obj)
{
return obj.GetHashCode();
}
}

I pass this to the constructor of the Dictionary. Is there a way to
improve the GetHashCode, however?
 
B

Ben Voigt [C++ MVP]

Hello:

Is there a way to force a Dictionary to determine equivilence by
memory location?

I have a generic class where I don't want to treat equal items as
identical items. Only when two references point to the same instance
do I want to treat them as the same dictionary key.

Any help?

Dictionary accepts an EqualityComparer delegate in the constructor, use
object.ReferenceEquals as the EqualityComparer.
 
J

jehugaleahsa

Thanks. Any ideas about improving the GetHashCode?

I'm assuming there isn't anything I can do about the GetHashCode. I
can't use memory addresses since they are volitile because of the
memory management.

Thanks again,
Travis
 
B

Ben Voigt [C++ MVP]

Thanks. Any ideas about improving the GetHashCode?

I'm assuming there isn't anything I can do about the GetHashCode. I
can't use memory addresses since they are volitile because of the
memory management.

Sorry, I don't know of any particular solution for that. But hash code
collisions should be pretty minimal unless the number of objects which are
equal-in-value-but-not-reference is a lot higher than you suggested.
 
P

Pavel Minaev

Thanks. Any ideas about improving the GetHashCode?

I'm assuming there isn't anything I can do about the GetHashCode. I
can't use memory addresses since they are volitile because of the
memory management.

There isn't anything that can be done in pure C#. However, it is
possible in IL to make non-virtual method calls even for virtual
methods, explicitly specifying the type that should provide the
implementation that is called. In your case, what you need is to make
a non-virtual call to Object.GetHashCode() on your objects - that
would be the default implementation that provides identity-based hash.
So, you take the C# code written along these lines:

using System;
using System.Collections.Generic;

public class IdentityComparer<T> : IEqualityComparer<T>
where T : class
{
public bool Equals(T x, T y)
{
return x == y;
}

public int GetHashCode(T x)
{
return x.GetHashCode();
}
}

Compile it, then ildasm it. In the resulting .il file, find this
instruction:

callvirt instance int32 [mscorlib]System.Object::GetHashCode()

replace "callvirt" with "call", and use ilasm to recompile the
assembly. Now you've got your identity comparer with proper
GetHashCode().
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top