is there a way to reference an object instance that is created using the \"with\" statement?
Example:
with TAnObject.Create do
begin
DoSomething(in
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:
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.
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
There is a working fine hack to do so. Define this workaround function somwhere in project unit.
// 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;
Usage example.
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;
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?
The best aproach in Delphi is use a variable to handle that instance.