2008-11-14 13 views
8

Dlaczego wykroczenie w usłudze EAccess jest zgłaszane podczas wykonywania kodu poniżej?Dlaczego funkcja TList.Remove() generuje błąd naruszenia uprawnień?

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; 

Odpowiedz

0

powyższy kod jest używany w 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; 
+0

Hmm, to nie jest odpowiedź na twoje pytanie. Myślę, że powinieneś połączyć to z kodem w twoim pytaniu (które, tak jak jest teraz, jest nieważne, ponieważ 'myNotifyEvent' jak pokazano w pytaniu nie pasuje do sygnatury' TNotifyEvent' (nie jest to metoda tam) –

5

Wygląda jak robaka.

Jeśli kompilujesz z debugowaniem dcu (zwykle nie rób tego, chyba że chcesz stracić swoje zdrowie psychiczne!), Widzisz, że połączenie z porównywarką poszło nie tak. (Nieobowiązkowo) trzecia wartość funkcji porównania nie jest ustawiona i powoduje naruszenie dostępu.

Tak więc nie można umieścić wskaźników metod na ogólnej liście.

Ok następujące prace:

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; 

Trzeba zdefiniować własną comparer z possiby trochę więcej inteligencji ;-).

+0

Wygląda podobnie jak błąd dla mnie –

1

Czy można przekazać niestandardowego porównywalnika do TList<T>? Nie mam przed sobą D2009, więc nie mogę tego wypróbować.

+0

Tak, możesz przekazać jeden przy przeciążonym konstruktorze –

3

Naruszenie dostępu jest spowodowane brakującym porównawcą. I podejrzewam, że została ustalona w plastrze, ale problem nadal występuje (przynajmniej w Delphi 2009), jeśli używasz TObjectList więc ja tylko aktualizację z najprostszego rozwiązania:

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

lub w moim przypadku

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

ten błąd nadal istnieje z xe4: / –

Powiązane problemy