8

I would like to clarify one doubt. In my current project I find that there are two TClientDataSet components. And one client dataset's properties and event handlers are assigned to another client dataset as below:

  cds2.AfterApplyUpdates := cds1.AfterApplyUpdates;
  cds2.AfterCancel       := cds1.AfterCancel;
  cds2.AfterClose        := cds1.AfterClose;

And

  cds2.CommandText       := cds1.CommandText;
  cds2.AutoCalcFields    := cds1.AutoCalcFields;
  cds2.DisableStringTrim := cds1.DisableStringTrim;

Is the above assignment of event handlers and properties required?

If we simply assign one client dataset to another as shown below, isn't it enough?

  cds2 := cds1;
Rob Kennedy
  • 161,384
  • 21
  • 275
  • 467
Vishal Tiwari
  • 739
  • 2
  • 12
  • 28
  • 1
    It's worth to mention that classes derived from `TPersistent` can implement the `Assign` method, where they can copy values of certain properties, implement deep copy of objects, or provide the ability to assign an object of a different class. Unfortunately, `TClientDataSet` doesn't implement it. – TLama Jul 22 '14 at 17:51

2 Answers2

15

Delphi classes are reference types. That means that when you define a variable whose type is a class, what you actually have is a reference, or pointer, to the object. And that makes the meaning of the assignment operator := be reference assignment rather than value assignment.

Suppose you have the following declarations:

var
  o1, o2: TObject;
....
o1 := TObject.Create;
o2 := o1;

At this point, you have created one object, and both o1 and o2 refer to, or point to, the same object. Any changes you make through the o1 reference are also visible through the o2 reference since there is only one object, or instance.

So, in your scenario, you have cds1 and cds2 that, presumably, refer to different instances. And that means that

cds2.CommandText := cds1.CommandText;

Copies the value of cds1.CommandText to cds2.CommandText.

That's totally different from

cds2 := cds1;

which copies references, and results in you losing track of the separate object that cds2 refers to.

Find more discussion of reference types and value types here: Why should we use classes rather than records, or vice versa?.

In summary, the two options that you present do very different things. The code that you currently use, which copies property values, presumably works. In which case, your suggested change to copy references will certainly not do what you want.

Community
  • 1
  • 1
David Heffernan
  • 601,492
  • 42
  • 1,072
  • 1,490
2

First of all: All components events are actually just properties which reference to event methods which are then used as event handlers. So when you assing one event as

cds2.AfterApplyUpdates := cds1.AfterApplyUpdates;

you are only assigning reference to the same method. With events this is quite commonly used in order to avoid writing same code multiple times.

Second of all: As David already sad when you are assigning one object variable to another using

cds2 := cds1;

you are only assigning same reference to object instance to another variable. You are not copying any actual data of the object.

Third of all: Even if what you are asking would work I doubt you would wannt to use it. Why? Becouse doing so you would get two TClientDataSets which will be accesing same database. And having tho of these is just pointelss.

SilverWarior
  • 7,372
  • 2
  • 16
  • 22
  • 1
    There are lots of reasons to have two TDataSets accessing the same database. So many, in fact, that they created a [method to do so](http://docwiki.embarcadero.com/Libraries/XE6/en/Datasnap.DBClient.TCustomClientDataSet.CloneCursor). I frequently have two instances of TClientDataSet that point to the same data (one for updating and one for doing lookups, for instance). – Ken White Jul 22 '14 at 16:07
  • Yes - I was tempted to suggest that after the OP had digested what David had said, he should have a look at CloneCursor() to see if there was a more elegant solution to his real requirement. – Hugh Jones Jul 22 '14 at 17:26
  • @SilverWarior: As you said, cds2.AfterApplyUpdates := cds1.AfterApplyUpdates; you are only assigning reference to the same method. With events this is quite commonly used in order to avoid writing same code multiple times. This means if there is a code change in event above handler of cds1, that would affect the cds2 evenhandler also, right? Since, cds2 event handler has reference of cds1 event handler. – Vishal Tiwari Jul 23 '14 at 04:33
  • Yes if you do change the code of the event handler method the code change will affect both components since in that case both of them use that same method. – SilverWarior Jul 23 '14 at 05:27
  • Thank You Dear All. It would help me a lot. I would come back if I come across any doubts, if it is related to the same topic. – Vishal Tiwari Jul 23 '14 at 05:30
  • 2
    Someone mentioned this earlier and it sounds like you'd benefit from learning about "deep copy" vs. "shallow copy" of objects. This is relevant to virtually any OOP language, but notably both Delphi and C++ where you can assign both by value (references in the case of objects) and by reference (by assigning pointers explicitly). To make matters even more confusing, C++ supports both "references" and "pointers". It also has a type of constructor often called a "copy constructor" that Delphi doesn't have. This ensures that when you "assign" one obj to another, you get the correct stuff copied. – David Schwartz Jul 23 '14 at 05:49