问题
Why EAccessViolation is raised when executing the code below?
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;
回答1:
It looks like a bug.
If you compile with debug dcu's (normally don't do that unless you want to loose your sanity!) you see that a call to the comparer went wrong. A (possibly optional) third value of a compare function is not set and causes the access violation.
So possibly you can't put method pointers in a generic list.
Ok the following works:
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;
You have to define your own comparer, with possiby some more intelligence ;-).
回答2:
Access Violation is caused by missing comparer. I suspect this was fixed in a patch but the problem still persists (at least in Delphi 2009) if you use a TObjectList so I'm just updating with the simplest solution:
TList<TNotifyEvent>.Create(TComparer<TNotifyEvent>.Default);
or in my case
TObjectList<TNotifyEvent>.Create(TComparer<TNotifyEvent>.Default);
回答3:
Is it possible to pass a custom comparer to TList<T>
? I don't have D2009 in front of me, so can't try it.
回答4:
the above code is used in 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;
来源:https://stackoverflow.com/questions/289825/why-is-tlist-remove-producing-an-eaccessviolation-error