Team LiB
Previous Section Next Section

Learning Common Types

Take an integer for example. Simple things such as the size of an integer are often taken for granted. Integers might not necessarily be the same size (or even in the same byte-order) on two different machines and operating systems. If you said 32 bits, you'd be somewhat correct. An integer on a 32-bit processor is in fact 32 bits in size. However, some languages such as C++ do not specify the size of an integer. They merely state that an integer is the size that can be handled by a single processing cycle for the target CPU. Okay. That's good for cross-platform languages such as C and C++. However, it makes it difficult for interoperability with other languages, such as Visual Basic.

The common type system does more than just define the size of an integer. The common type system provides three major functions:

  • Provides a framework for cross-language integration, type safety, and high-performance code.

  • Provides an object-oriented model that supports the complete implementation of many programming languages.

  • Defines rules that languages must follow. This ensures that objects written in different languages can interact with each other.

The common type system has two classifications of types: value types and reference types.

Understanding Value Types

Value types contain their data directly. In addition, value types are allocated on the runtime stack; this will become important during the discussion of the garbage collection system. Value types can be built-in, such as a char or int type, or user-defined via the struct keyword. Table 2.1 provides a listing of the value types in the Framework Class Library, hereafter referred to as the FCL.

Table 2.1. Value Types Defined by the .NET FCL


Class Name


C# Data Type



An 8-bit unsigned integer




An 8-bit signed integer*




A 16-bit signed integer




A 32-bit signed integer




A 64-bit signed integer




A 16-bit unsigned integer*




A 32-bit unsigned integer*




A 64-bit unsigned integer*


Floating point


A single-precision (32-bit) floating-point number




A double-precision (64-bit) floating-point number




True or false Boolean value




A Unicode (16-bit) character




A 96-bit decimal value




A signed integer whose size depends on the target platform




An unsigned integer whose size depends on the target platform



Value types with an asterisk in the description are not compliant with the common language specification (CLS). That means those particular types are not required or supported by all .NET-targeted languages. All Microsoft languages, such as VB .NET, C#, Managed C++, and JScript support the types listed in Table 2.1.

Table source:

Value types created within the scope of a method exist only for the duration of that method. After the method has returned, its call stack is reclaimed and the value type no longer exists. Classes can also contain value types. In this case, the data for the value type exists for the duration of the existence of the object.

Understanding Reference Types

Reference types are objects that are allocated and managed by the garbage collector. Reference types are instances of classes created using the new keyword. An example would be the following:

MyClass myClass = new MyClass( );

The myClass instance is created on the heap and managed by the garbage collector. Reference types do not disappear when they go out of scope the way that value types do. Rather, as the name implies, when all references to a reference type are gone, the garbage collector will reclaim the memory. More about the garbage collector will be discussed later.

Reference Versus Value Types

The key difference between value type and reference type is the way they are passed to methods. Depending on what language you're coming from, this might take some getting used to. For instance, in Visual Basic, not VB .NET, parameters default to pass by reference. That means that if a method (sub/procedure) modifies the parameter, the caller will see that modification. This is not the case with value types. Value types are passed to a method via a copy. A copy of the value is created on the call stack to the method. Sometimes it's just easier to see it in code, as in Listing 2.1.

Listing 2.1. Passing a Value Type to a Method
class MyClass {
    static public void ByValue( int i) {
        i = 20;

int i = 10;
Console.WriteLine( "Value of i := {0}", i );
MyClass.ByValue( i );
Console.WriteLine( "Value of i := {0}", i );

In Listing 2.1, a local variable i is declared and set to an initial value of 10. The WriteLine method displays the value to the output window. Next, the code passes the local variable i to the ByValue method of MyClass. In reality, a copy of i is placed on the call stack and not the actual variable i. This point is crucial. The code within the ByValue method is free to change the value of the parameter that was passed in; however, after the method has returned, any modifications made by the method to the parameter are lost. Therefore, the last WriteLine method will display the following message: Value of i := 10.

Armed with some basic knowledge of the .NET type system, the next step is to understand how the runtime system supports these types.

    Team LiB
    Previous Section Next Section