我有一个使用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;
类TCustomEqualityComparer是从Generics Defaults TEqualityComparer (Delphi)复制而在GetHashCode方法上稍作修改:
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;
我希望TCustomEqualityComparer能够对键值执行不区分大小写的匹配。例如:
D.Items['TWO']
但是,我收到“找不到项目”的例外情况。我使用的是Delphi 2010版本14.0.3513.24210。
有谁知道我的代码出了什么问题?
答案 0 :(得分:14)
uses System.Generics.Collections, System.Generics.Defaults;
var
D: TDictionary<string, Integer>;
begin
D := TDictionary<string, Integer>.Create(TIStringComparer.Ordinal); // ‹- this is the trick
try
D.Add('One', 1);
.
.
finally
D.Free;
end;
end;
答案 1 :(得分:3)
对于返回Equals = true的所有值,HashCode必须相同!在将GetHashCode发送到HashFunction之前尝试在GetHashCode中使用Value大写。
答案 2 :(得分:2)
感谢。我已经改变了TCustomEqualityComparer.GetHashCode,它就像你说的那样工作:
function TCustomEqualityComparer.Equals(const Left, Right: string): Boolean;
begin
{$IFDEF UNICODE }
Result := (Left.ToUpper = Right.ToUpper);
{$ELSE }
Result := SameText(Left, Right);
{$ENDIF }
end;
function TCustomEqualityComparer.GetHashCode(const Value: string): Integer;
var s: string;
begin
s := {$IFDEF UNICODE } Value.ToUpper {$ELSE } UpperCase(Value) {$ENDIF };
Result := BobJenkinsHash(s[1], Length(s) * SizeOf(s[1]), 0);
end;