Почему TList.Remove () выдает ошибку EAccessViolation? - PullRequest
8 голосов
/ 14 ноября 2008

Почему EAccessViolation вызывается при выполнении кода ниже?

uses
  Generics.Collections;
  ...

var
  list: TList<TNotifyEvent>;
  ...

begin
  list := TList<TNotifyEvent>.Create();
  try
    list.Add(myNotifyEvent);
    list.Remove(myNotifyEvent);  // EAccessViolation at address...
  finally
    FreeAndNil(list);
  end;
end;

procedure myNotifyEvent(Sender: TObject);
begin
  OutputDebugString('event');  // nebo cokoliv jineho
end;

Ответы [ 4 ]

5 голосов
/ 14 ноября 2008

Похоже, ошибка.

Если вы скомпилируете с отладочными dcu (обычно не делайте этого, если вы не хотите потерять здравомыслие!), Вы увидите, что вызов компаратору пошел не так. (Возможно, необязательное) третье значение функции сравнения не установлено и вызывает нарушение прав доступа.

Так что, возможно, вы не можете поместить указатели методов в общий список.

Хорошо, следующие работы:

uses
  Generics.Defaults;

type
  TForm4 = class(TForm)
    ...
  private
    procedure myNotifyEvent(Sender: TObject);
  end;

TComparer<T> = class (TInterfacedObject, IComparer<T>)
public
  function Compare(const Left, Right: T): Integer;
end;

implementation

uses
  Generics.Collections;

var
  list: TList<TNotifyEvent>;
begin
  list := TList<TNotifyEvent>.Create(TComparer<TNotifyEvent>.Create);
  try
    list.Add(myNotifyEvent);
    list.Remove(myNotifyEvent);
  finally
    FreeAndNil(list);
  end;
end;

procedure TForm4.myNotifyEvent(Sender: TObject);
begin
  ShowMessage('event');
end;

{ TComparer<T> }

function TComparer<T>.Compare(const Left, Right: T): Integer;
begin
  Result := 0;
end;

Вы должны определить свой собственный компаратор, возможно, с большим интеллектом; -).

3 голосов
/ 14 января 2010

Нарушение прав доступа вызвано отсутствием компаратора. Я подозреваю, что это было исправлено в патче, но проблема все еще сохраняется (по крайней мере, в Delphi 2009), если вы используете TObjectList, поэтому я просто обновляюсь с помощью самого простого решения:

TList<TNotifyEvent>.Create(TComparer<TNotifyEvent>.Default);

или в моем случае

TObjectList<TNotifyEvent>.Create(TComparer<TNotifyEvent>.Default);
1 голос
/ 14 ноября 2008

Можно ли передать пользовательский компаратор на TList<T>? У меня нет D2009 передо мной, поэтому не могу попробовать.

0 голосов
/ 14 ноября 2008

вышеуказанный код используется в TForm1 ...

uses 
  Generics.Collections;

procedure TForm1.Button1Click(Sender: TObject);
var
  list: TList<TNotifyEvent>;
begin
  list := TList<TNotifyEvent>.Create();
  try
    list.Add(myNotifyEvent);
    list.Remove(myNotifyEvent);  // EAccessViolation at address...
  finally
    FreeAndNil(list);
  end;
end;
procedure TForm1.myNotifyEvent(Sender: TObject);
begin
  OutputDebugString('event');  // nebo cokoliv jineho
end;
...