I have this spike to test TPair. You can copy+paste on a new Delphi XE Console-app. I have marked the line with the exception:
Project Project1.exe raised exception class EAccessViolation with message 'Access violation at address 0045042D in module 'Project1.exe'. Read of address A9032D0C.
Any Idea ?
Thanks.
program Project1;
{$APPTYPE CONSOLE}
uses
SysUtils,
Generics.Defaults,
Generics.Collections;
type
TProduct = class
private
FName: string;
procedure SetName(const Value: string);
published
public
property Name: string read FName write SetName;
end;
type
TListOfProducts = TObjectDictionary<TProduct, Integer>;
{ TProduct }
procedure TProduct.SetName(const Value: string);
begin
FName := Value;
end;
var
MyDict: TListOfProducts;
MyProduct1: TProduct;
MyProduct2: TProduct;
MyProduct3: TProduct;
APair: TPair<TProduct, Integer>;
aKey: string;
begin
try
MyDict := TListOfProducts.Create([doOwnsKeys]);
MyProduct1 := TProduct.Create;
MyProduct1.Name := 'P1';
MyProduct2 := TProduct.Create;
MyProduct2.Name := 'P2';
MyProduct3 := TProduct.Create;
MyProduct3.Name := 'P3';
MyDict.Add(MyProduct1, 1);
MyDict.Add(MyProduct2, 2);
MyDict.Add(MyProduct3, 3);
APair := MyDict.ExtractPair(MyProduct1);
Writeln(APair.Key.Name); // <--- Error is Here.
Writeln(IntToStr(APair.Value));
Readln(aKey);
except
on E: Exc开发者_如何学Pythoneption do
Writeln(E.ClassName, ': ', E.Message);
end;
end.
This is a Delphi bug. TDictionary<TKey,TValue>.ExtractPair
does not assign Result
.
RRUZ located the bug in QC.
The code reads:
function TDictionary<TKey,TValue>.ExtractPair(const Key: TKey): TPair<TKey,TValue>;
var
hc, index: Integer;
begin
hc := Hash(Key);
index := GetBucketIndex(Key, hc);
if index < 0 then
Exit(TPair<TKey,TValue>.Create(Key, Default(TValue)));
DoRemove(Key, hc, cnExtracted);
end;
Result
should be assigned when the call to DoRemove
is made.
It's quite hard to work around this bug. ExtractPair
is the only way to get an item out of the dictionary without destroying the key and so you have to call it. But since it won't return the extracted item, you need to first read the item, remember the value, and then call ExtractPair
.
精彩评论