Introduction
Type casting in Type-C allows for the conversion of values between different data types. This feature is particularly useful when you need to operate on a value with a type that is different from its current type or when passing values to functions that require a specific type.
There are three types of type casting in Type-C:
- Regular casting: When the conversion is straight forward, saying casting a signed integer to an unsigned integer.
- Forced casting: To override the compiler checks and force a conversion, such as a nullable type to a non-nullable type.
- Safe casting: To safely convert a type, returning null if the conversion is not possible.
Each approach has its own usage and usage policies, and the choice of which to use depends on the specific requirements of the situation.
Regular Casting
Regular casting is applicable when the conversion safety is guarenteed.
But before we talk about regular casting we have to talk about type checking a bit.
Consider the following example:
obj in the previous example is create as an interface type, and it is assigned a string value. This will tell the compiler to cast "hello, world!" to the interface type. So essentially it can be written as:
Both are valid because casting is straight forward. Regular casting can be used in cases where the conversion is straightforward but not acceptable by the compiler for additional safety, such as number conversion.
For example:
This would fail as the casting is not safe but also not necessarily unsafe. Hence the as operator would be used to cast the value.
In summary, regular casting inherits the compiler's basic type safety but with additional special cases for basic types
Forced Type Casting
Forced casting, done using the as! operator, bypasses compiler checks. This type of casting is powerful but should be used with caution, as it can lead to undefined behavior if used improperly. It is most appropriate in situations where the developer has complete certainty about the underlying type and structure of the data, often following an explicit type check.
It is important to note that forced casting does not change the view of its parameter. It merely overrides the compiler's type checking. So force casting i32 to i64 would result in corruption of the data (no actual casting will be done).
Safe Casting
Safe casting employs the as? operator and is the most cautious approach. If the cast is possible, it returns the value in the casted type; otherwise, it yields null. This method returns a nullable type, providing an additional safety layer by avoiding potential runtime errors from unsuccessful casts. Also, this casting works only data types which can be Nullable.
When it comes to converting between instances of classes/interface, where the casting is uncertain, using the safe casting as? is the best approach since it handles the check and the casting at the same time in the virtual machine, hence improving performance.
Type casting rules:
For forced casting, no rule is applied. It is a used it at your own risk feature. For regular casting, the following rules are applied:
- t1 as t2, as an expression is allowed if t1 and t2, are of the same base type (both interfaces, or both primitives, etc).
- t1 as t2, as a type is allowed if t1 and t2 are classes/interfaces or mixed.
- t1 as t2, as a type is allowed if t1 and t2 are variants or variant constructors.