|
Initialization/Finalization |
Top Previous Next |
|
What is translated > Statements > Initialization/Finalization There is no direct counterpart for the initialization and finalization sections of a unit in C#. These sections are therefore translated as two functions containing the corresponding instructions.
Delphi2C# offers two methods to generate automatic calls to these functions. Sometimes the initialization of a unit requires that the initialization of another unit has already been done. In this case, the option to create a special file that will reproduce the Delphi initialization order must be selected. If there are no such dependencies, you can choose the option that initialization and finalization takes place automatically in each file.
1. Calling the initialzation procedures automatically per file and call the Finalization method manually
If this option is chosen, a global variable of a class is written. The initialization routine is called in the constructor of this class. The call of the finalization routine has to be inserted manually . When the program starts, the global variables are first created and the units are also initialized:
initialization GlobalResourceA := TResourceA.Create; GlobalEnumValue := eOption1;
finalization FreeResource;
->
public class UnitaInterface : IDisposable { ... static UnitaInterface() { AssertSystemInitialization(); GlobalResourceA = TResourceA.Create; GlobalEnumValue = eOption1; }
void Dispose() { { FreeResource(); } GC.SuppressFinalize(this); }
~UnitaInterface() { Dispose(); }
In C#, unlike in C++, it is not guaranteed that the destructor ~UnitaInterface() will be automatically called. Therefore, it is the developer's responsibility to ensure that the Dispose method is explicitly invoked. The destructor is not strictly necessary; it merely serves as a fallback mechanism to ensure that resources are released in cases where the developer forgets to include an explicit call to the Dispose method in the code. When Dispose is called, GC.SuppressFinalize(this) suppresses the execution of the destructor to avoid unnecessary work for the garbage collector, as the resources have already been manually released.
2. Using a Lifecycle Manager class
Alternatively, there is the option to have the order of the initialization-finalization calls controlled by an external Lifecycle Manager class. This is a class in an additional file whose constructor calls all initialization procedures of the various units in the correct order and whose Dispose method ensures that the units are finalized accordingly.
The name of the control file is generated by appending "LCM" to the name of the Delphi2C# project option used for translation. For example, if the Test.prj project options are used, the resulting control file name would be:
TestLCM.cpp / TestLCM.h
and the generated class is:
public class TestLifecycleManager : IDisposable { public TestLifecycleManager() { // calling the Init procedures in correct order }
public void Dispose() { // calling the Finalization procedures in correct order } };
This class can be used the following way:
static void Main(string[] args) { using (var TestLifecycleManager = new TestLifecycleManager()) { ... processing the main code } // TestLifecycleManager }
All initializations are executed within the constructor of the TestLifecycleManager class when the main function starts, and the finalization methods are invoked after the main function has completed.
A disadvantage of using Lifecycle Manager class files is that a separate initialization and finalization file must be created for each project.
|
|
This page belongs to the Delphi2C# Documentation |
Delphi2C# home Content |