Reference object instance created using “with” in

2019-01-12 03:57发布

is there a way to reference an object instance that is created using the "with" statement?

Example:

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

Where DoSomething would use the instance reference as if you were passing an instance from a variable declared reference to the object created.

Example:

AnObject := TAnObject.Create;

Thanks.

8条回答
迷人小祖宗
2楼-- · 2019-01-12 04:10

You should never use with either because future changes might introduce more into that scope than you intended.

Take this for instance:

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

and then later on you tuck on a X property on the TSomeObject class. Now, which X do you think it's going to use? The local variable or the X property of the object?

The best solution is always to just create a local variable with a short name, and alias the object to that variable.

procedure Test;
var
    x: Integer;
    o: TSomeObject;
begin
    o := TSomeObject.Create;
    o.DoSomethingWithX(x);
    o.Free;
end;
查看更多
3楼-- · 2019-01-12 04:10

You gave the answer yourself: declare local variable. If you want you can use the with keyword on that.

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

In above example the only reason to use with is code readability, which is very subjective, you could also ditch the with keyword and use MyInstance directly. It's just a matter of personal taste. I don't agree on the "never use with" answers, but you should be aware of it's drawbacks.

See also this question: Is delphi "with" keyword a bad practice?

查看更多
Ridiculous、
4楼-- · 2019-01-12 04:10

You should use Self.

Example:

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

In that context Self is the object created by with clause.

查看更多
\"骚年 ilove
5楼-- · 2019-01-12 04:13

Well, you can use such approach:

// 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;

or class helpers:

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;

But, actually, previous replies are correct: you should better forget about "with" statement.

查看更多
贪生不怕死
6楼-- · 2019-01-12 04:15

I've learnt the hard way - only use 'With' in the following scenarios:

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


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

i.e keep the visibility of With as simple as possible. When you take into account the fact that the debugger cant resolve 'With', it's actually better and clearer to use a simple local variable or to fully declare the target i.e MyRecord.Something

查看更多
ら.Afraid
7楼-- · 2019-01-12 04:18

This is not possible now, but we can make it a reality by persuading the compiler creators:

  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;

My proposal is:

  1. No more than one object/record per With header.
  2. Nested Withs not allowed.
  3. Usage of " to indicate the object/record (double quotes are similar to the ditto mark: http://en.wikipedia.org/wiki/Ditto_mark).
查看更多
登录 后发表回答