C Type System

for RuBoard

C# Type System

In C# there is a fundamental distinction between value types and reference types. Value types have storage allocated immediately on the stack when the variable is declared. Reference types have storage allocated on the heap, and the variable is only a reference to the actual data, which can be allocated later.

We have been looking at classes in some detail. A class defines a reference type. In this section we survey the entire C# type system, including simple types such as int and decimal . In C# a struct has many similarities to a class but is a value type. Another important kind of value type in C# is an enum .

We examine later several other important types, including string, array, interface, and delegate. We will discuss the default values that get assigned to variables when there is not an explicit initialization. We will see that all types in C# are rooted in a fundamental base class called object . In C# "everything is an object," and value types are transparently converted to object references as needed through a process known as boxing . The inverse process, unboxing , returns an object to the value type from which it came.

Overview of Types in C#

In C# there are three kinds of types:

  • Value types

  • Reference types

  • Pointer types

Value Types

Value types directly contain their data. Each variable of a value type has its own copy of the data. Value types typically are allocated on the stack and are automatically destroyed when the variable goes out of scope. Value types include the simple types like int and decimal , structures, and enumeration types.

Reference Types

Reference types do not contain data directly but only refer to data. Variables of reference types store references to data, called objects. Two different variables can reference the same object. Reference types are allocated on the managed heap and eventually get destroyed through a process known as garbage collection .

Reference types include string , object , class types, array types, interfaces, and delegates.

Pointer Types

Pointer types are used only in unsafe code and will be discussed later in this chapter.

Value Types

In this section we survey all the value types, including the simple types, structures, and enumerations.

Simple Types

The simple data types are general-purpose value data types, including numeric, character, and Boolean.

  • The sbyte data type is an 8-bit signed integer.

  • The byte data type is an 8-bit unsigned integer.

  • The short data type is a 16-bit signed integer.

  • The ushort data type is a 16-bit unsigned integer.

  • The int data type is a 32-bit signed integer.

  • The uint data type is a 32-bit unsigned integer.

  • The long data type is a 64-bit signed integer.

  • The ulong data type is a 64-bit unsigned integer.

  • The char data type is a Unicode character (16 bits).

  • The float data type is a single-precision floating point.

  • The double data type is a double-precision floating point.

  • The bool data type is a Boolean ( true or false ).

  • The decimal data type is a decimal type with 28 significant digits (typically used for financial purposes).

Types in System Namespace

There is an exact correspondence between the simple C# types and types in the System namespace. C# reserved words are simply aliases for the corresponding types in the System namespace. Table 3-3 shows this correspondence.

Table 3-3. Types in C# and the System Namespace

C# Reserved Word

Type in System Namespace

sbyte

System.SByte

byte

System.Byte

short

System.Int16

ushort

System.UInt16

int

System.Int32

uint

System.UInt32

long

System.Int64

ulong

System.UInt64

char

System.Char

float

System.Single

double

System.Double

bool

System.Boolean

decimal

System.Decimal

Structures

A struct is a value type which can group heterogeneous types together. It can also have constructors and methods . In C++ the concept of class and struct is very close. In C++ a class has default visibility of private and a struct has default visibility of public , and that is the only difference. There is a more fundamental difference in C#.

In C# the key difference between a class and a struct is that a class is a reference type and a struct a value type. A class must be instantiated explicitly using new . The new instance is created on the heap, and memory is managed by the system through a garbage-collection process. Since a default constructor will be created for a struct if none is defined, a struct declared on the stack will be initialized . You may also use new . A new instance of a struct is created on the stack, and the instance will be deallocated when it goes out of scope.

There are different semantics for assignment, whether done explicitly or via call by value mechanism in a method call. For a class, you will get a second object reference, and both object references refer to the same data. For a struct, you will get a completely independent copy of the data in the struct.

A struct is a convenient data structure to use for moving data across a process or machine boundary, and we will use structs in our case study. For example, we will use a struct to represent customer data.

 public struct CustomerListItem  {     public int CustomerId;     public string FirstName;     public string LastName;     public string EmailAddress;  } 
Enumeration Types

The final kind of value type is an enumeration type. An enumeration type is a distinct type with named constants. Every enumeration type has an underlying type, which is one of the following.

  • byte

  • short

  • int

  • long

An enumeration type is defined through an enum declaration.

 public enum BookingStatus : byte  {        HotelNotFound,     // 0 implicitly        RoomsNotAvailable, // 1 implicitly        Ok = 5             // explicit value  } 

If the type is not specified, int is used. By default, the first enum member is assigned the value 0, the second member 1, and so on. Constant values can be explicitly assigned.

You can make use of an enumeration type by declaring a variable of the type indicated in the enum declaration (e.g., BookingStatus ). You can refer to the enumerated values by using the dot notation. Here is some illustrative code:

 BookingStatus status;  status = hotel.ReserveRoom(name, date);  if (status == BookingStatus.HotelNotFound)     Console.WriteLine("Hotel not found");  ... 

Reference Types

A variable of a reference type does not directly contain its data but instead provides a reference to the data stored in the heap. In C# there are the following kinds of reference types:

  • Class

  • Array

  • Interface

  • Delegate

Reference types have a special value null , which indicates the absence of an instance.

We have already examined classes in some detail, and we will look at arrays later in this chapter. Interfaces and delegates will be covered in Chapter 5.

Class Types

A class type defines a data structure that has fields, methods, constants, and other kinds of members . Class types support inheritance . Through inheritance a derived class can extend or specialize a base class. We will discuss inheritance in Chapter 4.

Two classes in the .NET Framework Class Library are so important that they have C# reserved words as aliases for them: object and string .

Object

The object class type is the ultimate base type for all types in C#. Every C# type derives directly or indirectly from object . The object keyword in C# is an alias for the predefined System.Object class. System.Object has methods such as ToString , Equals , and Finalize , which we will study later.

String

The string class encapsulates a Unicode character string. The string keyword is an alias for the predefined System.String class. The string type is a sealed class. (A sealed class is one that cannot be used as the base class for any other classes.)

The string class inherits directly from the root object class. String literals are defined using double quotes. There are useful built-in methods for string . For now, note that the Equals method can be used to test for equality of strings.

 string a = "hello";  if (a.Equals("hello"))        Console.WriteLine("equal");  else        Console.WriteLine("not equal"); 

There are also overloaded operators:

 if (a == "hello")        ... 

We will study string in detail later in this chapter.

Default Values

Several kinds of variables are automatically initialized to default values:

  • Static variables

  • Instance variables of class and struct instances

  • Array elements

Local variables are not automatically initialized, and you will get a compiler error message if you try to use a local variable that has not been initialized.

The default value of a variable of reference type is null .

The default value of a variable of value type is the value assigned in the default constructor. For simple types this value corresponds to a bit pattern of all zeros:

  • For integer types, the default value is 0

  • For char , the default value is '\u0000'

  • For float , the default value is 0.0f

  • For double , the default value is 0.0d

  • For decimal , the default value is 0.0m

  • For bool , the default value is false

For an enum type, the default value is 0. For a struct type, the default value is obtained by setting all value type fields to their default values, as described above, and all reference type fields to null .

Boxing and Unboxing

One of the strong features of C# is that is has a unified type system. Every type, including the simple built-in types such as int , derive from System.Object . In C# "everything is an object."

A language such as Smalltalk also has such a feature but pays the price of inefficiency for simple types. Languages such as C++ and Java treat simple built-in types differently from objects, thus obtaining efficiency but at the cost of a unified type system.

C# enjoys the best of both worlds through a process known as boxing . Boxing converts a value type such as int or a struct to an object reference and is done implicitly. Unboxing converts a boxed value type (stored on the heap) back to an unboxed simple value (stored on the stack). Unboxing is done through a type cast.

 int x = 5;  object o = x;      // boxing  x = (int) o;       // unboxing 
for RuBoard


Application Development Using C# and .NET
Application Development Using C# and .NET
ISBN: 013093383X
EAN: 2147483647
Year: 2001
Pages: 158

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net