what different between InstanceClass.NewInstance+Instance.Create and InstanceClass.Create;
Method1:
Instance := TComponent(InstanceClass.NewInstance);
Instance.Create(Self);
Method2:
Instance := InstanceClass.Create(Self);
Which is better?
I would always use InstanceClass.Create
if it is appropriate – and invariably it is.
There are plenty of reasons. A very good one is that the single line version is more concise. Another is that the single line version is the standard, commonly used approach.
Yet another reason is the handling of exceptions in the constructor which your method 1 does not manage correctly. In case of an exception, the new instance will be destroyed, but the instance variable has still been assigned to. That's an important difference from method 2 and goes against all the lifetime management conventions of Delphi.
You mention TApplication.CreateForm
. Let's take a look at it:
Instance := TComponent(InstanceClass.NewInstance);
TComponent(Reference) := Instance;
try
Instance.Create(Self);
except
TComponent(Reference) := nil;
raise;
end;
Remember that Reference
is the form variable that you pass as a var
parameter. The point about this is this code assigns that form variable before calling the constructor. Normally that assignment is only made after the constructor completes.
Presumably this is so that code which references the form variable (often a global variable) can work even if it is invoked from inside that form's constructor. This is a very special case and is overwhelmingly the exception rather than the rule. Don't let this special case drive your mainstream coding style.
(I added this answer, because IMHO others where not complete)
Method 2 is the correct one.
Method 1 if never to be called, since there is an hidden parameter to the constructor call, which may fail proper iniatialize: in fact, NewInstance
is a per-class pseudo virtual method!
In fact, there is an hidden boolean
parameter at constructor call (register EDX
, since EAX
=class). As stated by official documentation:
Constructors and destructors use the same calling conventions as other methods, except that an additional
Boolean
flag parameter is passed to indicate the context of the constructor or destructor call.A value of
False
in the flag parameter of a constructor call indicates that the constructor was invoked through an instance object or using the inherited keyword. In this case, the constructor behaves like an ordinary method. A value ofTrue
in the flag parameter of a constructor call indicates that the constructor was invoked through a class reference. In this case, the constructor creates an instance of theclass
given bySelf
, and returns a reference to the newly created object inEAX
.
In particular, when called that way, the class won't call the _ClassCreate
function. It may fail to initialize the class, if the class is not to be created with the default NewInstance
function. In fact, this function is inserted into the class VMT: in some rare cases, it may be overloaded (e.g. to provide another memory allocation pattern - may be a garbage collector or some speed-optimized allocator). So calling directly InstanceClass.NewInstance
can be buggy, in some border cases.
function _ClassCreate(AClass: TClass; Alloc: Boolean): TObject;
asm
...
TEST DL,DL
JL @@noAlloc
CALL dword ptr [EAX].vmtNewInstance
@@noAlloc:
...
Therefore, calling InstanceClass.NewInstance
directly is only to be done on purpose, only if you want to cancel two overridden vmtNewInstance / vmtFreeInstance
(and in this case, you may have to also NOT call .Free / .Destroy
, but you own memory free function). So: never call NewInstance
, but the constructor
, as designed and documented by Embarcadero (and FreePascal team by the way), unless you need to make some internal low-level tweak.
NEVER use method 1 to create an object! It may work 99.9 % of the time, but may fail some cases, or with a compiler/RTL enhancement in the future (like a garbage collector). Even if the VCL sometimes uses NewInstance
, you should not use it - I would rather prefer this method to be made protected.
Second is better because it is a standard method to create a class instance, while procedural form should be used within constructor to call inherited constructor.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With