Domanda

Questo codice in un'applicazione GUI viene compilato ed eseguito:

procedure TForm1.Button1Click(Sender: TObject);
begin
  Self := TForm1.Create(Owner);
end;

(testato con Delphi 6 e 2009)

  • perché è auto-scrivibile e non di sola lettura?
  • in quali situazioni potrebbe essere utile?

Modifica:

  • è possibile anche in Prisma di Delfi? (Penso di si, vedi qui )

Aggiornamento: Applicazioni / librerie Delphi che fanno uso di Auto-assegnazione:

È stato utile?

Soluzione

Non è così male come potrebbe essere. L'ho appena testato in Delphi 2009 e sembrerebbe che, sebbene il parametro Self non usi la semantica const , che sembra implicare che dovrebbe, non usa anche var , quindi puoi cambiarlo tutto ciò che desideri nel tuo metodo senza perdere effettivamente il riferimento che il chiamante detiene sul tuo oggetto. Sarebbe una cosa molto brutta.

Per quanto riguarda il motivo, una delle due risposte. O una semplice svista, o ciò che Marco ha suggerito: per permetterti di passare il Sé a un parametro var .

Altri suggerimenti

Forse per consentire il passaggio ai parametri const o var?

Potrebbe essere un artefatto, dal momento che il sistema non ha un sé da nessuna parte a sinistra di: = segno.

Assegnare al Sé è così illogico e inutile che questa "caratteristica" è probabilmente una svista. E come per le costanti assegnabili, non è sempre facile correggere tali problemi.

Il semplice consiglio qui è: non farlo.

In realtà, " Self " è solo un riferimento al nome di un posto nello stack che memorizza l'indirizzo che punta all'oggetto nell'heap. È possibile forzare la sola lettura su questa variabile, a quanto pare il progettista ha deciso di non farlo. Credo che la decisione sia arbitraria.

Non riesco a vedere nessun caso in cui ciò sia utile, ciò cambierebbe semplicemente un valore nello stack. Inoltre, modificare questo valore può essere pericoloso in quanto non vi è alcuna garanzia che il comportamento del codice che fa riferimento al membro dell'istanza di riferimento sarà coerente tra le versioni del compilatore.

Aggiornato: in risposta a PatrickvL comment

  

La 'variabile' " Self " non è sul   stack (per quanto ne sappia, non lo è mai);   Invece il suo valore è messo in a   registrati (EAX per l'esattezza) poco prima   viene effettuata una chiamata a qualsiasi metodo oggetto. -

No, il Sé ha l'indirizzo reale in memoria. Prova questo codice per vedere di persona.

procedure TForm1.Button1Click(Sender: TObject);
begin
  ShowMessage(IntToStr(Integer(@Self)));
end;

procedure TForm1.Button2Click(Sender: TObject);
var
  newform: TForm;
  p: ^Integer;
begin
  Self.Caption := 'TheOriginal';
  newform := TForm.Create(nil);
  try
    newform.Caption := 'TheNewOne';
    // The following two lines is, technically, the same as
    //   Self := newform;
    p := Pointer(@Self);
    p^ := Integer(newform);
    ShowMessage(Self.Caption);  // This will show 'TheNewOne' instead of 'TheOriginal'
  finally
    Self.Free; // Relax, this will free TheNewOne rather than TheOriginal
  end;
end;

A volte, quando si desidera ottimizzare un metodo per quanto possibile (senza ricorrere all'assemblaggio), 'Sé' può essere (ab) usato come una variabile 'libera' - potrebbe significare solo la differenza tra usando stack e usando i registri.

Certo, molto probabilmente i contenuti dello stack sono già presenti nella cache della CPU, quindi dovrebbe essere veloce accedervi, ma i registri sono ancora più veloci.

Come sidenote: mi mancano ancora i giorni in cui stavo programmando sul Motorola 68000 dell'Amiga e avevo il lusso di 16 dati e 16 registri di indirizzi .... Non posso credere che il mondo abbia scelto di andare con 4 registri limitati della linea di processori 80x86!

E come nota finale, ho scelto di usare il Sé a volte, dato che l'ottimizzatore di Delphi non sta, in realtà, ottimizzando . (Almeno, impallidisce rispetto a quale inganno si può trovare nei vari ottimizzatori LLVM per esempio.) IMHO e YMMV ovviamente.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top