Почему TList.Remove() выдает ошибку EAccessViolation?
Почему 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 ответа
Это похоже на ошибку.
Если вы скомпилируете с помощью команды debug 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;
Вы должны определить свой собственный компаратор, возможно, немного больше интеллекта;-).
Нарушение прав доступа вызвано отсутствием компаратора. Я подозреваю, что это было исправлено в патче, но проблема все еще сохраняется (по крайней мере, в Delphi 2009), если вы используете TObjectList, поэтому я просто обновляюсь с помощью самого простого решения:
TList<TNotifyEvent>.Create(TComparer<TNotifyEvent>.Default);
или в моем случае
TObjectList<TNotifyEvent>.Create(TComparer<TNotifyEvent>.Default);
Можно ли передать пользовательский компаратор в TList<T>
? У меня нет D2009 передо мной, поэтому не могу попробовать.
Приведенный выше код используется в 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;