2014-05-04 11 views
6

Sul blog di Chris: http://delphihaven.wordpress.com/2011/07/14/weird-in-more-ways-than-one/Quale questione fa "riferimento a" risolvere

ho trovato il seguente codice

type 
    TLinkVisitor<T> = reference to procedure(const Item: T); 

    TDoubleLinked<T> = record 
    Prev: ^TDoubleLinked<T>; 
    Next: ^TDoubleLinked<T>; 
    Value: T; 
    class function Create(const aValue: T): Pointer; static; 
    function Add(const aValue: T): Pointer; 
    procedure Delete; 
    procedure DeleteAll; 
    function First: Pointer; 
    function Last: Pointer; 
    procedure ForEach(const Proc: TLinkVisitor<T>); 
    end; 

Che problema non il 'riferimento alla' parola chiave risolvere che non può essere fatto con una normale procedura genere?

risposta

11

Con una procedura reference è possibile utilizzare:

  • Una procedura tradizionale, o
  • Un metodo di un oggetto, di classe o di registrare o
  • un metodo anonimo.

È la capacità di utilizzare metodi anonimi che imposta le procedure reference oltre a tutti gli altri tipi procedurali. E ciò che distingue metodi anonimi oltre ad altri tipi procedurali o di metodo è l'acquisizione variabile.

Per una discussione più dettagliata, fare riferimento a questa risposta: What is the difference between of object and reference to?. Vale anche la pena leggere la documentazione ufficiale per i metodi anonimi.

4

Secondo la documentazione ufficiale il problema (da risolvere) è che i metodi anonimi sono tipi gestiti, mentre le variabili procedurali non lo sono.
La parola chiave 'reference to' è più generale rispetto agli altri tipi procedurali.

Ecco come il doc dice: metodi http://docs.embarcadero.com/products/rad_studio/delphiAndcpp2009/HelpUpdate2/EN/html/devcommon/anonymousmethods_xml.html

anonimi sono tipicamente assegnati a qualcosa, come in questi esempi:

myFunc := function(x: Integer): string 
begin 
    Result := IntToStr(x); 
end; 

myProc := procedure(x: Integer) 
begin 
    Writeln(x); 
end; 

metodi anonimi possono anche essere restituiti da funzioni o passati come valori per i parametri quando si chiamano i metodi. Ad esempio, utilizzando il metodo anonimo myFunc variabile definita sopra:

type 
    TFuncOfIntToString = reference to function(x: Integer): string; 

procedure AnalyzeFunction(proc: TFuncOfIntToString); 
begin 
    { some code } 
end; 

// Call procedure with anonymous method as parameter 
// Using variable: 
AnalyzeFunction(myFunc); 

// Use anonymous method directly: 
AnalyzeFunction(function(x: Integer): string 
begin 
    Result := IntToStr(x); 
end;) 

riferimenti metodo possono anche essere assegnati ai metodi e metodi anonimi. Per esempio:

type 
    TMethRef = reference to procedure(x: Integer); 
TMyClass = class 
    procedure Method(x: Integer); 
end; 

var 
    m: TMethRef; 
    i: TMyClass; 
begin 
    // ... 
    m := i.Method; //assigning to method reference 
end; 

Tuttavia, il contrario è non vero: non è possibile assegnare un metodo anonimo a un puntatore metodo regolare. I riferimenti al metodo sono tipi gestiti, ma i puntatori del metodo sono tipi non gestiti. Pertanto, per motivi di sicurezza del tipo, l'assegnazione dei riferimenti al metodo ai puntatori del metodo non è supportata. Ad esempio, gli eventi sono proprietà del valore del puntatore del metodo, quindi non è possibile utilizzare un metodo anonimo per un evento. Vedere la sezione sul binding delle variabili per ulteriori informazioni su questa restrizione.

+1

Ti manca una delle più importanti funzionalità chiave dei metodi anonimi che è la cattura variabile. Altre cose come passare o restituirle possono essere fatte con normali puntatori di funzione, ma la cattura variabile non può. –

+0

Grazie a @StefanGlienke per averlo indicato. Mi ero completamente dimenticato di questo. Naturalmente tutto questo fanciness che si verifica sullo heap esclude questa roba per il codice ad alta velocità. – Johan

Problemi correlati