Delphi TPair Exception - PullRequest
       41

Delphi TPair Exception

5 голосов
/ 02 мая 2011

У меня есть этот шип для тестирования TPair. Вы можете скопировать + вставить новое консольное приложение Delphi XE. Я пометил строку с исключением:

Project Project1.exe поднял исключение Класс EAccessViolation с сообщением Нарушение доступа по адресу 0045042D в модуле «Project1.exe». Читать о адрес A9032D0C.

Есть идеи?

Спасибо.

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.

1 Ответ

11 голосов
/ 03 мая 2011

Это ошибка Delphi.TDictionary<TKey,TValue>.ExtractPair не присваивает Result.

RRUZ обнаружил ошибку в КК .

Код гласит:

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 следует назначить при вызове DoRemove.

Обойти эту ошибку довольно сложно.ExtractPair - это единственный способ вывести элемент из словаря, не уничтожая ключ, и поэтому вы должны вызвать его.Но так как он не вернет извлеченный элемент, вам необходимо сначала прочитать элемент, запомнить значение и затем вызвать ExtractPair.

...