Basic Datatypes
Both JScript .NET and the CLR provide many basic datatypes for nearly any operation. This section examines the primitive types available in JScript .NET, as well as their CLR counterparts. This section also discusses some of the complex datatypes, String and Array, and a few of the CLR types that aren't available in the JScript language but are available through the platform.
Primitive Types
Historically, the primitive datatypes of a language have been defined as datatypes that are directly supported by the language through built-in keywords. In addition to having direct language support, primitive types are generally very compact or well defined. (Complex objects and datatypes that take substantial amounts of initialization code don't fit into the category of primitive datatypes.)
The primitive datatypes available in JScript .NET include the numeric datatypes that support integers and floating-pointer numbers, the Boolean datatype that represents a true/false condition, and several special types, null and undefined, that can be used to test whether variables have been initialized.
Integer Numeric Types
JScript has several built-in keywords for describing various integer number types. Each of these types in turn relates to a type in the CLR. All the methods of the JScript types come from the functionality provided by the CLR. JScript supports the byte, short, int, and long keywords. Of these types, the byte type is unsigned, and the short, int, and long types are all signed. JScript doesn't have any additional keywords to specify the sign of a variable. Table 3.1 lists each of the JScript types, along with the corresponding CLR type. You'll notice some CLR types without JScript mappings that might come in handy when writing programs.
Table 3.1 JScript-to-CLR Type Mapping
JScript .NET Type |
CLR Type |
Signed |
---|---|---|
byte |
System.Byte |
No |
|
System.SByte |
Yes |
short |
System.Int16 |
Yes |
|
System.UInt16 |
No |
int |
System.Int32 |
Yes |
|
System.UInt32 |
No |
long |
System.Int64 |
Yes |
|
System.UInt64 |
No |
You can use the JScript .NET type names and the CLR-type names interchangeably. The CLR has many additional types that aren't available in JScript. Both the UInt32 and UInt64 can come in extremely handy for large number calculations or long-running loops.
Listing 3.1 is a small program that prints out the lower and upper bounds of each of the CLR types. These types have static member variables for their bounds, so a simple call to MinValue and MaxValue can get you exactly what you need.
Listing 3.1 CLR Integer Type Bounds
import System; // We have to use the actual type names because we are trying to // make use of the static field members. Console.WriteLine("{0,-15}{1,-25}{2,-25}", "Type Name", "MinValue", "MaxValue"); Console.WriteLine("{0,-15}{1,-25}{2,-25}", "Byte", Byte.MinValue, Byte.MaxValue); Console.WriteLine("{0,-15}{1,-25}{2,-25}", "SByte", SByte.MinValue, SByte.MaxValue); Console.WriteLine("{0,-15}{1,-25}{2,-25}", "Int16", Int16.MinValue, Int16.MaxValue); Console.WriteLine("{0,-15}{1,-25}{2,-25}", "UInt16", UInt16.MinValue, UInt16.MaxValue); Console.WriteLine("{0,-15}{1,-25}{2,-25}", "Int32", Int32.MinValue, Int32.MaxValue); Console.WriteLine("{0,-15}{1,-25}{2,-25}", "UInt32", UInt32.MinValue, UInt32.MaxValue); Console.WriteLine("{0,-15}{1,-25}{2,-25}", "Int64", Int64.MinValue, Int64.MaxValue); Console.WriteLine("{0,-15}{1,-25}{2,-25}", "UInt64", UInt64.MinValue, UInt64.MaxValue);
NOTE
Listing 3.1 takes advantage of some pretty neat features of the Console object. So far, the only code you have seen that uses Console object output has been extremely simple. Listing 3.1 uses a format string that is similar to that used with the C function printf. Each of the items is then displayed as a parameter. Although we pass three parameters in Listing 3.1, the function can normally handle up to four, and beyond four requires that you pass in a special array of parameters rather than pass each parameter individually.
The format string consists of a parameter format specifier in between each pair of braces. Each format specifier has the offset to the parameter it should use, and then some additional formatting rules are applied (for example, each item take up a certain amount of spaces [either 15 or 25] and each item should be left aligned [by using the minus symbol]). Other formatting rules are available, and you'll see them in notes throughout the book. For more information, examine the Software Development Kit (SDK) documentation because these formatting rules tend to be different in the various types and objects.
Float Numeric Types
For floating-point numbers, JScript supports both the float and the double keywords. These types map to the CLR types Single and Double, respectively. The Single type represents a 32-bit floating-point number, and the Double type represents a 64-bit floating-point number. You can assign values to floating-point numbers by using the decimal representation, or you can use scientific notation. The syntax for scientific notation in JScript .NET is numberEmantissa, where mantissa is the power of 10 to multiply by the number number. Listing 3.2 shows the upper and lower bounds of both the float and double datatypes, using the static fields.
Listing 3.2 CLR Float Type Bounds
import System; // JScript assignments var _float:float = 7.333E4; var _double:double = 1.2E10; // We have to use the actual type names because we are trying to // make use of the static field members. Console.WriteLine("{0,-15}{1,-15}{2,-15}", "Type Name", "MinValue", "MaxValue"); Console.WriteLine("{0,-15}{1,-15}{2,-15}", "Single", Single.MinValue, Single.MaxValue); Console.WriteLine("{0,-15}{1,-15}{2,-15}", "Double", Double.MinValue, Double.MaxValue);
The Boolean Type
JScript represents a Boolean typed variable with the keyword Boolean. This object directly converts to the CLR Type System.Boolean and takes up 2 bytes worth of space (the same as an Int16). Along with supporting a variable datatype, JScript .NET can also coerce nearly any expression to return a Boolean result. This allows for very compact code when you're trying to compare types against what their basic values should be.
For numeric datatypes, both floats and integers, any 0 value returns false. Any nonzero value returns true. This means that when checking against 0 in a conditional statement, you can leave out the comparison operator altogether, as in the following example:
var _int:int = 0; function DoLoops(_int:int) { // Check to make sure we are doing at least one loop. // If not. Set the value to one. if ( !_int ) { _int = 1; } // do something }
You can also check objects to see whether they have been initialized, by using the Boolean type. Any variable that is still null and has not been initialized returns false. Any variable that contains an object reference returns true. The following is the best way to check any objects before using them:
var _obj:Object; if ( _obj ) { // Do something with the object } else { // We have a bad object. Decide what to tell the user. }
CAUTION
Be sure you test the preceding example with each of the types that you expect to be used. Depending on the object type, JScript has specific ways of deciding whether to return true or false in the conditional statement. The generic method is to test the object reference against null, but some of the primitive datatypes aren't objects and behave differently, depending on the default value for the datatype. So, keep in mind that testing for null is valid only on objects, and not on primitive datatypes.
Special Types: null and undefined
null and undefined are actually not special types as much as they are special values of types. null and undefined behave identically to one another because the JScript compiler handles the appropriate conversion between null and undefined as necessary. For the most part, you use both null and undefined to determine whether a variable contains a null pointer or a pointer to an object. For this reason, you can't use this method to compare objects that extend System.ValueType, such as the integer types and the Boolean type. Listing 3.3 demonstrates the use of null and undefined.
Listing 3.3 Using null and undefined
import System; var MyInt:Int32; var MyString:String; var MyBoolean:Boolean; var MyObject = undefined; if ( MyInt == null ) { Console.WriteLine("MyInt == null"); } if ( MyInt == undefined ) { Console.WriteLine("MyInt == undefined"); } if ( MyString == null ) { Console.WriteLine("MyString == null"); } if ( MyString == undefined ) { Console.WriteLine("MyString == undefined"); } if ( MyBoolean == null ) { Console.WriteLine("MyBoolean == null"); } if ( MyBoolean == undefined ) { Console.WriteLine("MyBoolean == undefined"); } if ( MyObject == null ) { Console.WriteLine("MyObject == null"); } if ( MyObject == undefined ) { Console.WriteLine("MyObject == undefined"); }
MyString == null MyString == undefined MyObject == null MyObject == undefined
Notice in Listing 3.3 that even though the Int32 and Boolean variables are not given values, they naturally assume default values. Int32 variables are always 0 and Boolean variables are always false. Because the use of null and undefined is so interchangeable, we will be using null throughout the rest of the book when performing checks on whether variables contain real pointers.