delphi – 在TObjectDictionary中使用对象作为键
发布时间:2020-12-15 04:35:07 所属栏目:大数据 来源:网络整理
导读:当我使用TObjectDictionary时,TKey是对象,我的应用程序工作不正确. 我有两个单元,它包含两个类.第一单元: unit RubTerm;interfacetype TRubTerm = Class(TObject) private FRubricName: String; FTermName: String; public property RubricName: String rea
当我使用TObjectDictionary时,TKey是对象,我的应用程序工作不正确.
我有两个单元,它包含两个类.第一单元: unit RubTerm; interface type TRubTerm = Class(TObject) private FRubricName: String; FTermName: String; public property RubricName: String read FRubricName; property TermName: String read FTermName; constructor Create(ARubricName,ATermName: String); end; implementation constructor TRubTerm.Create(ARubricName,ATermName: String); begin Self.FRubricName := ARubricName; Self.FTermName := ATermName; end; end; 第二单元: unit ClassificationMatrix; interface uses System.Generics.Collections,System.Generics.Defaults,System.SysUtils,RubTerm; type TClassificationMatrix = class(TObject) private FTable: TObjectDictionary<TRubTerm,Integer>; public constructor Create; procedure TClassificationMatrix.AddCount(ADocsCount: Integer; ARubName,ATermName: String); function TClassificationMatrix.GetCount(ARubName,ATermName: String): Integer; end; implementation constructor TClassificationMatrix.Create; begin FTable := TObjectDictionary<TRubTerm,Integer>.Create; end; procedure TClassificationMatrix.AddCount(ADocsCount: Integer; ARubName,ATermName: String); var ARubTerm: TRubTerm; begin ARubTerm := TRubTerm.Create(ARubName,ATermName); FTable.Add(ARubTerm,ADocsCount); end; function TClassificationMatrix.GetCount(ARubName,ATermName: String): Integer; var ARubTerm: TRubTerm; begin ARubTerm := TRubTerm.Create(ARubName,ATermName); FTable.TryGetValue(ARubTerm,Result); end; end; 但是这段代码工作不正常: procedure TestTClassificationMatrix.TestGetCount; var DocsCountTest: Integer; begin FClassificationMatrix.AddCount(10,'R','T'); DocsCountTest := FClassificationMatrix.GetCount('R','T'); end; // DocsCountTest = 0! Why not 10? Where is problem? 谢谢! 解决方法
字典取决于键值.您正在存储对键中对象的引用.如果您创建两个设置相同的对象,则具有不同的值,因此具有不同的键.
var ARubTerm1: TRubTerm; ARubTerm2: TRubTerm; begin ARubTerm1 := TRubTerm.Create('1','1'); ARubTerm2 := TRubTerm.Create('1','1'); // ARubTerm1 = ARubTerm2 is not possible here as ARubTerm1 points to a different address than ARubTerm2 end; 相反,您可以使用String作为TObjectDictonary中的第一个类型参数,该参数基于RubricName和TermName.有了这个,你就可以得到相同的价值. 还应该注意,XE2中的上述代码会产生两个内存泄漏.必须释放创建的每个对象.因此这部分代码也是泄漏内存 function TClassificationMatrix.GetCount(ARubName,Result); end; 鉴于所有这些.如果要将Object用作Key,可以使用Custom Equality Comparer执行此操作.以下是您的示例已更改为实现IEqualityComparer< T>,并修复了一些内存泄漏. unit ClassificationMatrix; interface uses Generics.Collections,Generics.Defaults,SysUtils,Integer>; public constructor Create; procedure AddCount(ADocsCount: Integer; ARubName,ATermName: String); function GetCount(ARubName,ATermName: String): Integer; end; implementation constructor TClassificationMatrix.Create; var Comparer : IEqualityComparer<RubTerm.TRubTerm>; begin Comparer := TRubTermComparer.Create; FTable := TObjectDictionary<TRubTerm,Integer>.Create([doOwnsKeys],TRubTermComparer.Create); end; procedure TClassificationMatrix.AddCount(ADocsCount: Integer; ARubName,ATermName); try if Not FTable.TryGetValue(ARubTerm,Result) then result := 0; finally ARubTerm.Free; end; end; end. 还有RubTerm.pas单元 unit RubTerm; interface uses Generics.Defaults; type TRubTerm = Class(TObject) private FRubricName: String; FTermName: String; public property RubricName: String read FRubricName; property TermName: String read FTermName; constructor Create(ARubricName,ATermName: String); function GetHashCode: Integer; override; end; TRubTermComparer = class(TInterfacedObject,IEqualityComparer<TRubTerm>) public function Equals(const Left,Right: TRubTerm): Boolean; function GetHashCode(const Value: TRubTerm): Integer; end; implementation constructor TRubTerm.Create(ARubricName,ATermName: String); begin Self.FRubricName := ARubricName; Self.FTermName := ATermName; end; { TRubTermComparer } function TRubTermComparer.Equals(const Left,Right: TRubTerm): Boolean; begin result := (Left.RubricName = Right.RubricName) and (Left.TermName = Right.TermName); end; function TRubTermComparer.GetHashCode(const Value: TRubTerm): Integer; begin result := Value.GetHashCode; end; //The Hashing code was taken from David's Answer to make this a complete answer. {$IFOPT Q+} {$DEFINE OverflowChecksEnabled} {$Q-} {$ENDIF} function CombinedHash(const Values: array of Integer): Integer; var Value: Integer; begin Result := 17; for Value in Values do begin Result := Result*37 + Value; end; end; {$IFDEF OverflowChecksEnabled} {$Q+} {$ENDIF} function GetHashCodeString(const Value: string): Integer; begin Result := BobJenkinsHash(PChar(Value)^,SizeOf(Char) * Length(Value),0); end; function TRubTerm.GetHashCode: Integer; begin Result := CombinedHash([GetHashCodeString(Value.RubricName),GetHashCodeString(Value.TermName)]); end; end. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |