2008-11-14 3 views
8

아래 코드를 실행할 때 EAccessViolation이 발생하는 이유는 무엇입니까? 위의 코드가 된 TForm1에 사용되는TList.Remove()가 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

...

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; 
+0

음,이 질문에 대한 답변이 아닙니다. 질문에 표시된 'myNotifyEvent'가'TNotifyEvent' 시그니처와 일치하지 않기 때문에 현재의 코드는 무효입니다 (이 메서드는 메서드가 아닙니다). –

5

그것은 벌레처럼 보인다.

디버그 dcu로 컴파일하는 경우 (일반적으로 그렇게하지 않는 것이 좋습니다!) 비교 자의 호출이 잘못되었다는 것을 알 수 있습니다. 비교 함수의 (선택 사항 인) 세 번째 값이 설정되지 않고 액세스 위반이 발생합니다.

그래서 메소드 포인터를 일반 목록에 넣을 수 없습니다.

좋아 다음 작품 :

당신은 possiby 좀 더 많은 정보 ;-)로, 자신의 비교자를 정의해야
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; 

.

+0

Looks –

1

사용자 지정 비교자를 TList<T>으로 전달할 수 있습니까? 나는 내 앞에 D2009가 없으므로 그것을 시도 할 수 없다.

+0

예, 오버로드 된 생성자에서 하나를 전달할 수 있습니다. –

3

액세스 위반은 비교 자 누락으로 인해 발생합니다. 나는이 패치에서 수정 된 것으로 의심하지만, 당신이 TObjectList와를 사용하는 경우 문제가 계속 난 그냥 간단한 솔루션을 통해 업데이트 있도록 (적어도 2009 델파이에서) 지속 :

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

또는 제 경우

을에
TObjectList<TNotifyEvent>.Create(TComparer<TNotifyEvent>.Default); 
+0

이 버그는 여전히 xe4 : /와 함께 존재합니다. –

관련 문제