德尔福TPair异常 [英] Delphi TPair Exception

查看:320
本文介绍了德尔福TPair异常的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有这个峰值来测试TPair。您可以在新的Delphi XE控制台应用程序上复制+粘贴。我已经标记了这个例外:


项目Project1.exe引发异常
类EAccessViolation消息
'访问冲突在模块'Project1.exe'中的地址0045042D
。阅读
地址A9032D0C。


任何想法?



谢谢。

 程序Project1; 

{$ APPTYPE CONSOLE}

使用
SysUtils,
Genericics.Defaults,
泛型。

type
TProduct = class
private
FName:string;
procedure SetName(const Value:string);
发布
public
属性名称:string read FName write SetName;
结束

type
TListOfProducts = TObjectDictionary< TProduct,Integer> ;;

{TProduct}

程序TProduct.SetName(const Value:string);
begin
FName:= Value;
结束


var
MyDict:TListOfProducts;
MyProduct1:TProduct;
MyProduct2:TProduct;
MyProduct3:TProduct;
APair:TPair 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); //< ---错误在这里。
Writeln(IntToStr(APair.Value));

Readln(aKey);
除了
在E:Exception do
Writeln(E.ClassName,':',E.Message);
结束
结束。


解决方案

这是一个Delphi错误。 TDictionary< TKey,TValue> .ExtractPair 不分配结果



RRUZ位于 QC中的错误



代码如下:

  function TDictionary< TKey,TValue> .ExtractPair(const关键:TKey):TPair  var 
hc,index:Integer;
begin
hc:=哈希(键);
index:= GetBucketIndex(Key,hc);
如果index< 0然后
退出(TPair< TKey,TValue>。创建(键,默认(TValue)));

DoRemove(Key,hc,cnExtracted);
结束

结果 DoRemove



很难解决这个错误。 ExtractPair 是将项目从字典中取出而不会破坏该键的唯一方式,因此您必须调用它。但是由于它不会返回提取的项目,您需要先阅读该项目,记住该值,然后调用 ExtractPair


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: Exception 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.

这篇关于德尔福TPair异常的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆