为什么在执行下面的代码时会引发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;
答案 0 :(得分:5)
它看起来像一个bug。
如果使用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;
你必须定义自己的比较器,可能需要更多智能; - )。
答案 1 :(得分:3)
访问冲突是由缺少比较器引起的。我怀疑这是在一个补丁中修复但问题仍然存在(至少在Delphi 2009中),如果你使用TObjectList,所以我只是用最简单的解决方案进行更新:
TList<TNotifyEvent>.Create(TComparer<TNotifyEvent>.Default);
或在我的情况下
TObjectList<TNotifyEvent>.Create(TComparer<TNotifyEvent>.Default);
答案 2 :(得分:1)
是否可以将自定义比较器传递给TList<T>
?我没有D2009在我面前,所以无法尝试。
答案 3 :(得分:0)
以上代码用于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;