5

Possible Duplicate:
Reference object instance created using “with” in Delphi

One method that I use to create query objects in Delphi follows the first code sample. It gives me a reference to the object and I can then pass the object to a function.

procedure SomeProcedure;
var
  qry: TQuery;
begin
  qry := TQuery.Create(nil);

  with qry do
  begin
    Connection := MyConn;
    SQL.Text := 'SELECT * FROM PEOPLE';
    Open;

    funcDisplayDataSet(qry);
    Free;
  end;

end;

Is it also possible to do this in a WITH statement where your Create object in contained in the WITH statement?

procedure SomeProcedure;
begin
  with TQuery.Create(nil) do
  begin
    Connection := MyConn;
    SQL.Text := 'SELECT * FROM PEOPLE';
    Open;

    funcDisplayDataSet( ??? );  // Here I'm unsure how to pass the object created...
    Free;
  end;
end;

Can I pass this dynamic object to a function like `funcDisplayDataSet(TQuery)?

I just would like to know if this is possible. I'm not looking for a summary on why the WITH statement is bad or good. There are other posts on StackOver flow with that discussion.*

Community
  • 1
  • 1
KodeTitan
  • 903
  • 1
  • 9
  • 23
  • 1
    +1 for the interesting question, although I suspect that there isn't a way to do it cleanly/clearly, if at all. If the solution turns out to be some voodoo that would make the next guy have to go and look up how you did it, then you shouldn't do it. – Chris Thornton Jan 18 '12 at 15:14
  • Same question here [reference-object-instance-created-using-with-in-delphi](http://stackoverflow.com/questions/791181/reference-object-instance-created-using-with-in-delphi), with a solution provided by Alexander. – LU RD Jan 18 '12 at 15:32
  • 4
    Just use a local variable and take the WITH out. If you go do some evil hack, just to keep the WITH in there, then I'll have to track you down, and pants you. – Warren P Jan 18 '12 at 17:28

3 Answers3

6

That's not possible, in general, in a clean manner. Your options:

  1. Add a method to the class that returns Self.
  2. Stop using with and create a local variable for the instance.

Option 1 is viable if you have control over the class. But it leaves the class looking rather odd. Why would a class need an instance method that returned the instance? If you don't have control over the class then you could use a class helper as RRUZ suggests but I regard the use of class helpers as a last resort. I've never solved a problem with a class helper.

That leaves option 2. This would be how I would solve the problem.

David Heffernan
  • 601,492
  • 42
  • 1,072
  • 1,490
  • 1
    +1 "I've never solved a problem with a class helper" – PA. Jan 18 '12 at 17:15
  • I had solved an problem with a class helper... It transformed an 50 hour work in a 6 hours fix... In a emergency, such was the case, they are really handy. – Fabricio Araujo Jan 18 '12 at 17:20
5

What about using a class helper ?

type
  TQueryHelper = class helper for TQuery
  public
    function Instance: TQuery;
  end;


function TQueryHelper.Instance: TQuery;
begin
  Result := Self;
end;

And use like this

   With TQuery.Create(nil) do
   begin
     SQL.Text:='Select * from OTGH';
     ShowMessage(Instance.SQL.Text);
   end;
RRUZ
  • 134,889
  • 20
  • 356
  • 483
  • 3
    Well this does the job but fails my test of being "clean". +1 – David Heffernan Jan 18 '12 at 15:31
  • David, I'm against the `with` statement too, this is just an answer to the questiom `...I just would like to know if this is possible`. – RRUZ Jan 18 '12 at 15:33
  • Almost the same as the solution (by Alexander) in my link above. Without class helper, but still not "clean" by David's measure. – LU RD Jan 18 '12 at 15:35
  • @RRUZ I up-voted you but I wanted to add some commentary to indicate that class helpers are usually considered to be *bad thing*. – David Heffernan Jan 18 '12 at 15:38
  • @LURD good catch (I don't see that question before) I will vote to close the question. – RRUZ Jan 18 '12 at 15:38
  • @DavidHeffernan `..class helpers are usually considered to be bad thing?` really ? – RRUZ Jan 18 '12 at 15:41
  • 1
    @RRUZ Absolutely. Even the documentation recommends that you do not use them. Now, if they worked like C# extension methods that would be altogether different. – David Heffernan Jan 18 '12 at 15:45
  • @DavidHeffernan, I use class helpers in very specific scenarios, can you provide me a link to the documentation which you mention? because I only now [this](http://docwiki.embarcadero.com/RADStudio/en/Class_and_Record_Helpers) – RRUZ Jan 18 '12 at 15:55
  • That's the doc that I mean. I'm sure it was sterner in previous versions. But all the same the advice applies. Use a derived class to add new methods. – David Heffernan Jan 18 '12 at 16:02
  • The Delphi 2007 Documentation on Class Helpers (which is the first version they were available in) states: `Class helpers provide a way to extend a class, but they should not be viewed as a design tool to be used when developing new code. They should be used solely for their intended purpose, which is language and platform RTL binding.` – afrazier Jan 18 '12 at 16:17
  • 4
    This is just a dumb idea. Take the with out. – Warren P Jan 18 '12 at 17:29
4

The with statement doesn't provide a reference that you can use to pass outside of the statement.

With a TQuery, you could get around it by using a property that has a reference to the parent:

begin
  with TQuery.Create(nil) do
  begin
    Connection := MyConn;
    SQL.Text := 'SELECT * FROM PEOPLE';
    Open;
    // Fields have reference to parent component, but your implementation may vary
    funcDisplayDataSet(TQuery(Fields.Fields[0].GetParentComponent));
    Free;
  end;
end;
Marcus Adams
  • 53,009
  • 9
  • 91
  • 143