Reputation:
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.
Upvotes: 8
Views: 7601
Reputation: 5668
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.
Upvotes: 17
Reputation: 11
The best aproach in Delphi is use a variable to handle that instance.
Upvotes: 0
Reputation: 1
for FMX, you should use GetObject example:
with TLabel.Create(box1) do
begin
Font.Size := 34;
Font.Style := [TFontStyle.fsBold];
TextAlign := TTextAlign.taCenter;
box1.AddObject(GetObject);
end;;
Upvotes: 0
Reputation: 81
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;
Upvotes: 0
Reputation: 5
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:
Upvotes: -1
Reputation: 5975
An addition to Brian's example on a Notify handler is to use an absolute variable (win32 only):
procedure Notify( Sender : TObject );
var
Something : TSomeThing absolute Sender;
begin
if Sender is TSomething then
begin
VerySimpleProperty := Something.Something;
OtherProperty := Something.SomethingElse;
end;
end;
It basically avoids having to assign a local variable or have a lot of type casts.
Upvotes: 2
Reputation: 7062
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?
Upvotes: 4
Reputation: 13454
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
Upvotes: 1
Reputation: 391306
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;
Upvotes: 12