InstanceClass.NewInstance vs InstanceClass.Create

what is the difference between InstanceClass.NewInstance + Instance.Create and InstanceClass.Create;

Method1:

Instance := TComponent(InstanceClass.NewInstance); Instance.Create(Self); 

Method 2:

 Instance := InstanceClass.Create(Self); 

What's better?

+6
source share
3 answers

I would always use InstanceClass.Create , if appropriate - and this is always the case.

There are many reasons. It is good that the single-line version is shorter. Another is that the single-line version is the standard, commonly used approach.

Another reason is exception handling in the constructor, which your method 1 does not work correctly. In the event of an exception, the new instance will be destroyed, but the instance variable is still assigned. This is an important difference from method 2 and runs counter to all Delphi lifecycle management conventions.

You mentioned TApplication.CreateForm . Let's take a look at this:

 Instance := TComponent(InstanceClass.NewInstance); TComponent(Reference) := Instance; try Instance.Create(Self); except TComponent(Reference) := nil; raise; end; 

Remember that Reference is a form variable that you pass as a var parameter. The fact is that this code assigns this form variable before calling the constructor. Typically, this assignment is only performed after the constructor completes.

Presumably, this is so that code that references a form variable (often a global variable) can work even if it is called from within this form constructor. This is a very special case and the vast majority is an exception, not a rule. Do not let this special case control your basic coding style.

+10
source

(I added this answer because IMHO others where not completed)

Method 2 is correct.

Method 1, if you never call it, because there is a hidden parameter to invoke the constructor that may not match the iniatialize proper: in fact, NewInstance is a pseudo-virtual method for each class!

Actually there is a hidden boolean parameter when calling the constructor (register EDX , since EAX = class). As stated in the official documentation :

Constructors and destructors use the same calls as other methods, except that the optional flag parameter boolean is passed specify the context for calling the constructor or destructor.

A value of False in the constructor invocation flag parameter indicates that the constructor was called through an instance of the object or using an inherited keyword. In this case, the constructor behaves like a regular method. A value of True in the flag parameter of the constructor call indicates that the constructor was called through the reference class. In this case, the constructor creates an instance of the class specified by Self , and returns a reference to the newly created object in EAX .

In particular, when calling this class, the class will not call the _ClassCreate function. This may not initialize the class if the class is not created using the default NewInstance function. In fact, this function is inserted into the VMT class: in some rare cases, it can be overloaded (for example, to provide another memory allocation pattern - it can be a garbage collector or some optimizer with speed optimization). Therefore, calling InstanceClass.NewInstance directly may be erroneous, in some cases with borders.

 function _ClassCreate(AClass: TClass; Alloc: Boolean): TObject; asm ... TEST DL,DL JL @@noAlloc CALL dword ptr [EAX].vmtNewInstance @@noAlloc: ... 

Therefore, calling InstanceClass.NewInstance directly must be done on purpose only if you want to cancel two overridden vmtNewInstance / vmtFreeInstance (in which case you may also NOT call .Free / .Destroy , but you have a free function memory). So: never call NewInstance , but constructor , as it was developed and documented by Embarcadero (and the FreePascal team, by the way), if you do not need to make some internal low-level settings.

NEVER use method 1 to create an object! It may work 99.9% of the time, but it may crash in some cases or with the compiler / RTL extension in the future (e.g. garbage collector). Even if the VCL sometimes uses NewInstance , you should not use it - I would prefer this method to be protected.

+4
source

Secondly, it is better because this is the standard method for instantiating a class, while the procedural form should be used inside the constructor to invoke the inherited constructor.

+2
source

Source: https://habr.com/ru/post/914959/


All Articles