Unqualified References

Unqualified references are a big source of problems in CTD applications because it's not immediately clear where the variable is declared and they are evaluated dynamically at runtime. The result may be unpredictable. C# and VB.NET do not support any ambiguous reference (being strongly typed and compiled languages), therefore during porting we have to clearly and fully qualify all the unqualified references.

Fully Unqualified

Fully unqualified references are very hard to translate because in CTD they are resolved at runtime and can address just about anything. For example, the statement "Set nValue = 10" may be written in a global function, or in a class, or in any other place where nValue is nowhere to be seen. It's enough that the symbol is either a control or a variable on any top level form and CTD will find it dynamically at runtime. When porting, Ice Porter looks for the unqualified symbol in all top level forms and if it finds it in only one place, it fully qualifies the expression by using the templates static instance declared in the Application class.

For example:

Set dfAge = 20

If dfAge is declared in frmPatient, the code ports to:

App.frmPatient.dfAge.Number = 20;

It's exactly the same as if the assignment was qualified in SAL as

Set frmPatient.dfAge = 20

However, if the same symbol is present in more than one top level form, Ice Porter cannot generate any expression that makes sense and will log an error.

Class Qualified

Class qualified expressions include a window handle and a class or form template name. When the window handle is hWndItem or hWndForm or hWndMDI and the expression is within the current form or control, Ice Porter is capable of optimizing the expression and generates a direct expression using the this keyword. When a class is specified and the handle is not the current form, the generated code converts the window handle to the specified class either using a custom cast, or using a custom FromHandle static method, depending on the options that were selected in the Ice Porter project.

For example:

Set hWnd.CDfNumber.dfAge = 20

Is ported to:

((CDfNumber)hWnd).Number = 20;

Or to:

CDfNumber.FromHandle(hWnd).Number = 20;

The end result is exactly the same. The FromHandle syntax may be considered by some C# developers to be more consistent with the .NET Framework way of converting handles to controls. Other developers may prefer the cast expression because it may be more similar to original SAL code. It's just a matter of taste.

CTD does not check that the specified control derives from the specified class and simply casts the control to the class. This is a common problem in SAL applications and the source of many random crashes in CTD. Ice Porter may be able to identify these mistakes while porting, but in some cases you may end up with an InvalidCastException at runtime.

Handle Semi-qualified

Handle semi-qualified expressions are similar to the Class qualified but without the class name. CTD looks for the specified symbol at runtime within the control identified by the window handle. Ice Porter may be able to optimize these expressions if the symbol is declared in only one top level form. When the expression cannot be optimized, the generated code looks like this:

SalWindow.Findmember(hWnd, "dfAge").Number = 20;

The code above looks for the dfAge member within the control identified by hWnd at runtime.

Ambiguous Unqualified References

When Ice Porter cannot qualify an unqualified expression because the symbol is present in multiple locations, it resorts to using a special runtime evaluation function that is capable of looking up the symbol at runtime.

For example:

Set hWnd.sName = "PPJ"

When sName is present in more than one top level form, therefore it's impossible to generate a qualified expression, we generate the following expression:

SalWindow.FindMember(hWnd, "sName").String = "PPJ";

At runtime, the method SalWindow.FindMember() uses a particularly fast reflection code to read/write the member dynamically. However, we strongly suggest to remove all the ambiguous unqualified expressions when possible.

Last updated