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 looked at classes in the first section. 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. All types in C# are rooted in a fundamental base class called object.[3] 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.

[3] The C# keyword object is just another name for the .NET class System.Object.

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.

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).

STRUCTURES

A struct is a value type that can group heterogeneous types together. It can also have constructors and methods. In C++ the concepts of class and struct are 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 is 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.

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 ItemStatus :  byte
{
   NotFound,   // 0 implicitly
   NotEnough,  // 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:

ItemStatus status = inven.BuyItem(id, qty, out avail);
if (status == ItemStatus.NotFound)
   Console.WriteLine("Item not found");
...

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.

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

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")
    ...

Boxing and Unboxing

One of the strong features of C# is that it 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 non-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

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.145.59.187