2008-11-14 30 views
8

¿Por qué se plantea EAccessViolation al ejecutar el código siguiente?¿Por qué TList.Remove() produce un error 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; 

Respuesta

0

el código anterior se utiliza en 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, esto no es realmente una respuesta a su pregunta. Creo que debería fusionar esto con el código en su pregunta (que, tal como está ahora, no es válido porque el 'myNotifyEvent' como se muestra en la pregunta no coincide con la firma' TNotifyEvent' (no es un método allí). –

5

se ve como un error.

Si compila con depuración de dcu (normalmente no lo hace a menos que quiera perder la cordura), verá que una llamada al comparador salió mal. Un tercer valor (posiblemente opcional) de una función de comparación no se establece y causa la violación de acceso.

Así que posiblemente no pueda poner punteros a los métodos en una lista genérica.

Ok las siguientes obras:

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; 

Usted tiene que definir su propio comparador, con un poco más de inteligencia possiby ;-).

+0

como un error para mí también. –

1

¿Es posible pasar un comparador personalizado al TList<T>? No tengo D2009 delante de mí, así que no puedo intentarlo.

+0

Sí, puede pasar uno en el constructor sobrecargado. –

3

La infracción de acceso es causada por la falta del comparador. Sospecho que esto fue fijada en un parche, pero el problema aún persiste (al menos en Delphi 2009) si se utiliza un TObjectList así que estoy actualizando con la solución más simple:

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

o en mi caso

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

este error todavía existe con xe4: / –

Cuestiones relacionadas