Экземпляр ссылочного объекта, созданный с помощью «with» в Delphi - PullRequest
8 голосов
/ 26 апреля 2009

Есть ли способ ссылки на экземпляр объекта, который создается с помощью оператора "с"?

Пример:

with TAnObject.Create do
begin
  DoSomething(instance);
end;

Где DoSomething будет использовать ссылку на экземпляр, как если бы вы передавали экземпляр из переменной, объявленной ссылкой на созданный объект.

Пример:

AnObject := TAnObject.Create;

Спасибо.

Ответы [ 9 ]

14 голосов
/ 26 апреля 2009

Ну, вы можете использовать такой подход:

// implement:

type
  TSimpleMethod = procedure of object;

function GetThis(const pr: TSimpleMethod): TObject;
begin
  Result := TMethod(pr).Data;
end;

// usage:

  with TStringList.Create do
  try
    CommaText := '1,2,3,4,5,6,7,8,9,0';
    ShowText(TStringList(GetThis(Free)));
  finally
    Free;
  end;

или класс помощников:

type 
  TObjectHelper = class helper For TObject
  private
    function GetThis: TObject; Inline;
  public
    property This: TObject read GetThis;
  end;

...

function TObjectHelper.GetThis: TObject;
begin
  Result := Self;
end;

Но, на самом деле, предыдущие ответы верны: вам лучше забыть про «с».

12 голосов
/ 26 апреля 2009

Вы также никогда не должны использовать with, потому что будущие изменения могут внести в эту область больше, чем вы предполагали.

Возьмите это, например:

procedure Test;
var
    x: Integer;
begin
    with TSomeObject.Create do
    begin
        DoSomethingWithX(x);
        Free;
    end;
end;

, а затем вы добавите свойство X в класс TSomeObject. Теперь, какой X вы думаете, он будет использовать? Локальная переменная или свойство X объекта?

Лучшим решением всегда является создание локальной переменной с коротким именем и псевдоним объекта для этой переменной.

procedure Test;
var
    x: Integer;
    o: TSomeObject;
begin
    o := TSomeObject.Create;
    o.DoSomethingWithX(x);
    o.Free;
end;
3 голосов
/ 27 апреля 2009

Вы сами дали ответ: объявите локальную переменную. Если хотите, вы можете использовать ключевое слово с для этого.

var
  MyInstance: TMyObject;
begin
  MyInstance := TMyObject.Create;
  with MyInstance do
  try
    Foo;
    Bar;
    DoSomething(MyInstance);
  finally
    Free;
  end;
end;

В приведенном выше примере единственной причиной использования с является читаемость кода, что очень субъективно, вы также можете отказаться от ключевого слова с и использовать MyInstance напрямую. Это просто вопрос личного вкуса. Я не согласен с ответами «никогда не использовать с», но вы должны знать о его недостатках.

См. Также этот вопрос: Является ли ключевое слово delphi "with" плохой практикой?

2 голосов
/ 28 апреля 2009

В дополнение к примеру Брайана с обработчиком уведомлений используется абсолютная переменная (только для win32):

procedure Notify( Sender : TObject ); 
var 
  Something : TSomeThing absolute Sender;
begin 
  if Sender is TSomething then 
  begin
    VerySimpleProperty := Something.Something;
    OtherProperty := Something.SomethingElse;
  end;
end;

Это в основном избавляет от необходимости присваивать локальную переменную или использовать много типов типов.

1 голос
/ 27 апреля 2009

Я выучил трудный путь - используйте «С» только в следующих сценариях:

With TMyForm.Create( Owner ) do
  try
    ShowModal
  finally
    Free;
  end;


procedure Notify( Sender : TObject );
begin
  With Sender as TSomething do
    VerySimpleProperty := Something      
end;

Т.е. сделать видимость С максимально простой. Если принять во внимание тот факт, что отладчик не может разрешить «С», на самом деле лучше и понятнее использовать простую локальную переменную или полностью объявить цель, т.е. MyRecord.Something

0 голосов
/ 17 января 2019

для FMX, вы должны использовать GetObject Пример:

with TLabel.Create(box1) do
begin
    Font.Size := 34;
    Font.Style := [TFontStyle.fsBold];
    TextAlign := TTextAlign.taCenter;
    box1.AddObject(GetObject);
end;;
0 голосов
/ 03 июля 2018

Лучший подход в Delphi - использовать переменную для обработки этого экземпляра.

0 голосов
/ 25 мая 2016

Для этого есть хороший хак. Определите эту обходную функцию где-нибудь в модуле проекта.

// use variable inside 'with ... do'
// WSelf function returns TObject associated with its method.
//   I would recommend to use the method 'Free'
// WSelf(Free) as <TObjectN>
type TObjectMethod = procedure of object;
function WSelf(const MethodPointer: TObjectMethod): TObject;
begin
  Result := TMethod(MethodPointer).Data;
end;

Пример использования.

var
    SL: TStringList;
begin
    SL := TStringList.Create;
    try
        with TStringList.Create do
        try
            Add('1');
            Add('2');
            Add('3');
            // (WSelf(Free) as TStringList) references to the object
            //   created by TStringList.Create
            SL.Assign(WSelf(Free) as TStringList);
        finally
            Free;
        end;
    finally
        ShowMessage(SL.Text);
        SL.Free;
    end;
end;
0 голосов
/ 15 марта 2014

Сейчас это невозможно, но мы можем сделать это реальностью, убедив создателей компилятора:

  With TForm1.Create (Nil) Do  // New TForm1 instance
    Try
      LogForm (");  // That same instance as parameter to an outer method (solution)
      "ShowModal;  // Instance.ShowModal
    Finally
      "Free;  // Instance.Free
    End;

Мое предложение:

  1. Не более одного объекта / записи в заголовке With.
  2. Вложенные блоки не допускаются.
  3. Использование "для обозначения объекта / записи (двойные кавычки похожи до такой же отметки: http://en.wikipedia.org/wiki/Ditto_mark).
...