Data Types
PPJ types preserve SAL behavior that ordinary .NET values do not express by themselves: numeric nulls, numeric Boolean values, SAL-specific conversions, and handles tied to runtime resources. Replacing a type because it appears to contain a string or number can change those behaviors even when the code still compiles.
The generator uses native .NET types where the target declaration permits them, such as many constants and interop signatures. Keep PPJ types at compatibility-sensitive boundaries until tests show an equivalent native representation.
Data Type Equivalence
| SAL data type | PPJ type | Representation / responsibility |
|---|---|---|
| String | SalString | Wraps string data and SAL string operations. |
| Number | SalNumber | Decimal-based numeric value with a separate null state. |
| Date/Time | SalDateTime | DateTime-based value with SAL null and conversion behavior. |
| Boolean | SalBoolean | Numeric SAL-compatible Boolean behavior; not simply C# bool. |
| Window Handle | SalWindowHandle | Refers to a target-specific UI object; Desktop uses Windows Forms controls. |
| File Handle | SalFileHandle | Represents an open file resource and its operations. |
| Sql Handle | SalSqlHandle | Owns or references SQL command/reader state under PPJ's connection policy. |
| Sql Session Handle | SalSqlSessionHandle | Represents a SQL session under the selected provider's behavior. |
SalString, SalNumber, SalBoolean, and SalDateTime expose interfaces such as INullable, IComparable, IConvertible, and IFormattable. Do not assume every handle type implements that same set of interfaces.
Null Is a State, Not a Display Value
SalNumber missing = SalNumber.Null;
SalNumber zero = 0;
bool missingIsNull = missing.IsNull; // true
bool zeroIsNull = zero.IsNull; // false
A numeric field can display blank for a null value. That presentation is not a reason to convert the value to zero. Similarly, a formatted value such as "0.00" is text, not the original number and not its null state.
PPJ value + null state
│
├─ calculation / database binding → preserve numeric meaning and nulls
│
└─ display formatting → text using a culture and format
At a boundary that requires a native nullable number, make the policy explicit:
SalNumber amount = SalNumber.Null;
decimal? apiAmount = amount.IsNull ? (decimal?)null : amount.ToDecimal();
The null check happens before conversion. This preserves the difference between “not supplied” and an actual zero. Do not infer that all PPJ comparisons behave like nullable C# operators or SQL three-valued logic; use the documented PPJ operation for the intended test.
Values, References, and Handles
The reviewed desktop scalar types do not all have the same C# storage semantics: SalNumber, SalBoolean, and SalDateTime are structs, while SalString is a class. An assignment of a struct copies its value; assignment of a class reference copies a reference. A PPJ conversion operator can add another step. Check the actual type and operation before assuming an assignment is a deep copy.
A handle identifies a live resource in its target runtime. It is not a durable record key and should not be serialized for use after a form, connection, process, or session ends. A file handle and a window handle are not interchangeable merely because older code stored both in numeric-looking variables.
Converting Safely
Define the receiving API's expected type, null representation, precision, encoding, and ownership. Check the result on the way back as well. A successful implicit conversion for an ordinary argument does not allow mismatched ref arguments.
See Automatic Casts for conversions and receive parameters, Dynamic Arrays for element references, and Object Oriented Types for instance-method equivalents of SAL functions.
For executable examples, add RuntimeConceptChecks.cs to a test project referencing the desktop PPJ runtime and call RuntimeConceptChecks.RunChecks(). It checks null conversion, array receive values, context restoration, and action return flags without opening a database or UI. Use the installed release's references; these checks were verified with PPJ desktop 5.0.4.1.