tags:

views:

81

answers:

2

Hi,

I have a case using TDictionary:

var D: TDictionary<string, integer>;
begin
  D := TDictionary<string, integer>.Create(TCustomEqualityComparer.Create());
  try
    D.Add('One', 1);
    D.Add('Two', 2);
    D.Add('Three', 3);

    showmessage(inttostr(D.Items['One']));
    showmessage(inttostr(D.Items['TWO']));
  finally
    D.Free;
  end;
end;

Class TCustomEqualityComparer is copied from Generics Defaults TEqualityComparer (Delphi) with minor modification on GetHashCode method:

TCustomEqualityComparer = class(TEqualityComparer<string>)
public
  function Equals(const Left, Right: string): Boolean; override;
  function GetHashCode(const Value: string): Integer; override;
end;

function TCustomEqualityComparer.Equals(const Left, Right: string): Boolean;
begin
  Result := SameText(Left, Right);
end;

function TCustomEqualityComparer.GetHashCode(const Value: string): Integer;
begin
  Result := BobJenkinsHash(Value[1], Length(Value) * SizeOf(Value[1]), 0);
end;

I expect the TCustomEqualityComparer able to perform the case-insensitive matching for the key values. For example:

D.Items['TWO']

However, I get a "Item not found" exception. I am using Delphi 2010 Version 14.0.3513.24210.

Does anyone know how what's wrong with my code?

+1  A: 

The HashCode has to be the same for all values that return Equals = true! Try making Value uppercase in the GetHashCode before sending it to your HashFunction.

BTW, the original Equals is already case-insensitive.

Uwe Raabe
Are you sure the original Equals is already case-insensitive?This is the original Equals method defined in unit Generics.Defaults.pas: function Equals_UString(Inst: PSimpleInstance; const Left, Right: UnicodeString): Boolean; begin Result := Left = Right; end;
Chau Chee Yang
You are right! I mixed up the original implementation and an example.
Uwe Raabe
A: 

Thanks. I have changed TCustomEqualityComparer.GetHashCode and it works as you said:

function TCustomEqualityComparer.Equals(const Left, Right: string): Boolean;
begin
  Result := SameText(Left, Right);
end;

function TCustomEqualityComparer.GetHashCode(const Value: string): Integer;
var s: string;
begin
  s := UpperCase(Value);
  Result := BobJenkinsHash(s[1], Length(s) * SizeOf(s[1]), 0);
end;
Chau Chee Yang