This chapter is from the book

This chapter is from the book

The C# Predefined Types

The C# language predefines a set of types that map to types in the common type system. If you are familiar with another programming language, the names of these types might be different, but you can easily see the correlation. All the predefined types are value types except for object and string. The predefined types are shown in Table 3.1.

Table 3.1. Predefined C# Types

Keyword

Aliased Type

Description

Range

bool

Boolean

Logical Boolean

true or false

byte

Byte

Unsigned 8-bit integer

0 to 255

char

Char

A single 16-bit Unicode character

U+0000 to U+FFFF

decimal

Decimal

A 128-bit data type with 28–29 significant digits

(–7.9 × 1028 to 7.9 × 1028) / (100 to 28)

double

Double

Double-precision 64-bit floating point up to 15–16 digits

±5.0 × 10–324 to ±1.7 × 10308

float

Single

Single-precision 32-bit floating point up to 7 digits

±1.5 × 10–45 to ±3.4 × 1038

int

Int32

Signed 32-bit integer

–231 to 231 – 1

long

Int64

Signed 64-bit integer

–263 to 263 – 1

sbyte

SByte

Signed 8-bit integer

–128 to 127

short

Int16

Signed 16-bit integer

–32,768 to 32,767

uint

UInt32

Unsigned 32-bit integer

0 to 4,294,967,295

ulong

UInt64

Unsigned 64-bit integer

0 to 18,446,744,073,709,551,615

ushort

UInt16

Unsigned 16-bit integer

0 to 65,535

object

Object

Base type of all other value and reference types, except interfaces

N/A

string

String

A sequence of Unicode characters

N/A

By including a type to directly represent Boolean values (values that are either true or false), there is no ambiguity that the value is intended to be a Boolean value as opposed to an integer value. This helps eliminate several common programming errors, making it easier to write self-documenting code.

Tip: Boolean Values

In C, Boolean values are represented as an integer value, and it is left up to the programmer to decide if 0 means true or false. Typically, C programs define named constants representing the integer values of 0 and 1 to help eliminate this ambiguity, but this still allows any integer value to be used.

The decimal type provides at least 28 significant digits and is designed to have no representation error over a wide range of values frequently used in financial calculations. The range of values the double type can represent with no representation error is a set used primarily in physical calculations.

The object type is the underlying base type for all the other reference and value types. The string type represents a sequence of Unicode code units and cannot be changed once given a value. As a result, values of type string are immutable.

C# also has some special types, the most common being the void type. The void type indicates the absence of a type. The dynamic type is similar to object, with the primary difference being all operations on that type will be resolved at runtime rather than compile time.

Note: System.Object

All the value types and the class, array, and delegate reference types derive from object. Interface types can derive only from other interface types, but they are convertible to object.

Type parameter types actually do not derive from anything, but they are still convertible to object.

Unsafe pointer types neither derive from nor are convertible to object because they are outside the normal type rules for C#.

All this actually means that every nonpointer type in C# is convertible to, but might not derive from, object.

Note: Predefined Types and CLS Compliance

All the predefined types are CLS-compliant except the unsigned integer types and the sbyte type. You can use these types and still be CLS-compliant as long as they are not publicly accessible. If you do need to make one of these types publicly accessible, they can safely map to a CLS-compliant type:

sbyte maps to short.

uint normally maps to long but can be mapped to int when the original value is less than 2,147,483,647.5.

ulong normally maps to decimal but can be mapped to long when the original value is less than 9,223,372,036,854,775,807.5.

ushort normally maps to int but can be mapped to short when the original value is less than 32,767.5.

Although void and dynamic are types, var represents an implicitly typed variable and tells the compiler to determine the real type based on the assigned data.

Caution: Var Is Not Short for Variant

When the var type was first introduced, many people thought it was equivalent to the Visual Basic Variant type. A Variant is a type that can be used to represent any other data type and is not strongly typed. A var type is still strongly typed because it is replaced with a real data type during compilation. Even so, overusing it can decrease the understandability of your code, so use it carefully.

Try It Yourself: Working with the Predefined Types

Now that you are familiar with the predefined types, let’s see how to use them. By following these steps, you write an application that creates some local variables and displays their values. Then you create an implicitly typed variable and verify that it actually creates a strongly typed variable:

Hover the mouse cursor over the var keyword until the ToolTip is displayed, which confirms that v is actually an int, as shown in Figure 3.2.

Figure 3.2. ToolTip showing a var as an int.

Press Ctrl+F5 again to run the application, and you should now see an additional line appear:

This is also an Int32 value: 20

Press any key to close the console and return to Visual Studio.

Enter the following line in the Main method:

v = "hello";

You should immediately notice a red “squiggly” line under the statement you just entered and an error message stating that you Cannot implicitly convert type 'string' to 'int'. This error occurs because the compiler has already assigned v to be of type int and the strong-typing capabilities of C# prevent you from assigning a string value to the same variable, which is an incompatible type.

Remove the line you entered from step 9 so your program compiles again.