Pregunta

Este código en una aplicación GUI compila y ejecuta:

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

(probado con Delphi 6 y 2009)

  • ¿por qué es Auto escribible y no de solo lectura?
  • ¿en qué situaciones podría ser útil?

Editar:

  • ¿esto también es posible en Delphi Prism? (Creo que sí, consulte aquí )

Actualización: Aplicaciones / bibliotecas de Delphi que hacen uso de Autoasignación:

¿Fue útil?

Solución

Eso no es tan malo como podría ser. Acabo de probarlo en Delphi 2009, y parece que, si bien el parámetro Self no usa la semántica const , lo que parece implicar que debería, tampoco usa var semántica, para que pueda cambiar todo lo que quiera dentro de su método sin perder realmente la referencia que la persona que llama tiene a su objeto. Eso sería algo muy malo.

En cuanto a la razón por la cual, una de dos respuestas. Ya sea un simple descuido o lo que Marco sugirió: para permitirle pasar Self a un parámetro var .

Otros consejos

¿Tal vez permitir pasar a parámetros const o var?

Podría ser un artefacto, ya que el sistema no tiene uno mismo en ningún lado a la izquierda de: = signo.

Asignarse a uno mismo es tan ilógico e inútil que esta 'característica' probablemente sea un descuido. Y al igual que con las constantes asignables, no siempre es fácil corregir tales problemas.

El consejo simple aquí es: no lo hagas.

En realidad, " Self " es solo una referencia de nombre a un lugar en la pila que almacena la dirección que apunta a un objeto en el montón. Es posible forzar solo lectura en esta variable, aparentemente el diseñador decidió no hacerlo. Creo que la decisión es arbitraria.

No puedo ver ningún caso en el que esto sea útil, eso simplemente cambiaría un valor en la pila. Además, cambiar este valor puede ser peligroso ya que no hay garantía de que el comportamiento del código del miembro de la instancia de referencia sea consistente en las versiones del compilador.

Actualizado: en respuesta al comentario de PatrickvL

  

La 'variable' " Self " no está en el   apilar (que yo sepa, nunca lo es);   En cambio, su valor se pone en un   registrarse (EAX para ser exactos) justo antes   Se realiza una llamada a cualquier método de objeto. & # 8211;

No, Self tiene una dirección real en la memoria. Prueba este código para verlo por ti mismo.

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 veces, cuando desea optimizar un método lo más lejos que puede llevarlo (sin recurrir al ensamblaje), 'Self' se puede (ab) usar como una variable 'libre'; esto podría significar la diferencia entre usando stack y usando registros.

Claro, el contenido de la pila probablemente ya esté presente en la memoria caché de la CPU, por lo que debería ser rápido de acceder, pero los registros son aún más rápidos.

Como nota al margen: todavía me faltan los días en que estaba programando en el Motorola 68000 de Amiga y tenía el lujo de 16 datos y 16 registros de direcciones ... No puedo creer que el mundo eligió ir con el ¡4 registros limitados de la línea de procesadores 80x86!

Y como nota final, elijo usar Self a veces, ya que el optimizador de Delphi es, bueno, no optimizando tan bien, en realidad. (Al menos, palidece en comparación con el truco que uno puede encontrar en los diversos optimizadores de LLVM, por ejemplo). En mi humilde opinión y YMMV, por supuesto.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top