在Delphi中使用“with”创建的引用对象实例

时间:2009-04-26 16:53:15

标签: delphi with-statement

有没有办法引用使用“with”语句创建的对象实例?

示例:

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

DoSomething将使用实例引用,就像您将实例从变量声明引用传递给创建的对象一样。

示例:

AnObject := TAnObject.Create;

感谢。

9 个答案:

答案 0 :(得分:14)

嗯,你可以使用这种方法:

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

但实际上,之前的回复是正确的:你最好忘记“with”声明。

答案 1 :(得分:12)

您永远不应该使用with,因为未来的更改可能会比您预期的更多地引入该范围。

以此为例:

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

然后在tomeObject类上的X属性上。现在,您认为它将使用哪个X?对象的局部变量或X属性?

最好的解决方案始终是创建一个短名称的局部变量,并将该对象别名为该变量。

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

答案 2 :(得分:3)

你自己给出了答案:声明局部变量。如果您愿意,可以使用 with 关键字。

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

在上面的示例中,使用的唯一原因是代码可读性,这是非常主观的,您也可以抛弃关键字并直接使用MyInstance。这只是个人品味的问题。我不同意“永不使用”的答案,但你应该意识到它的缺点。

另请参阅此问题:Is delphi "with" keyword a bad practice?

答案 3 :(得分:2)

在Notify处理程序上添加Brian的示例是使用绝对变量(仅限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;

它基本上避免了必须分配局部变量或者有很多类型转换。

答案 4 :(得分:1)

我学到了很多方法 - 在以下场景中只使用'With':

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


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

即保持尽可能简单的可见性。当你考虑到调试器无法解析'With'这一事实时,使用一个简单的局部变量或完全声明目标,即MyRecord.Something

实际上更好更清晰。

答案 5 :(得分:0)

现在这是不可能的,但我们可以通过说服编译器创建者来实现它:

  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)。

答案 6 :(得分:0)

这样做有一个很好的工作。 在项目单元中定义此变通办法功能。

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

答案 7 :(得分:0)

对于FMX,您应该使用GetObject 例如:

with TLabel.Create(box1) do
begin
    Font.Size := 34;
    Font.Style := [TFontStyle.fsBold];
    TextAlign := TTextAlign.taCenter;
    box1.AddObject(GetObject);
end;;

答案 8 :(得分:-1)

Delphi中最好的方法是使用变量来处理该实例。