| for RuBoard |
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
In C# there are three kinds of types:
Value types
Reference types
Pointer 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
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 are used only in unsafe code and will be discussed later in this chapter.
In this section we survey all the value types, including the simple types, structures, and enumerations.
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).
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.
|
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 |
A
struct
is a value type which can
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
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
public struct CustomerListItem
{
public int CustomerId;
public string FirstName;
public string LastName;
public string EmailAddress;
}
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
BookingStatus status;
status = hotel.ReserveRoom(name, date);
if (status == BookingStatus.HotelNotFound)
Console.WriteLine("Hotel not found");
...
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.
A class type defines a data structure that has fields, methods, constants, and other kinds of
Two classes in the .NET Framework Class Library are so important that they have C# reserved words as aliases for them: object and string .
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.
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.
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 .
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
int x = 5; object o = x; // boxing x = (int) o; // unboxing
| for RuBoard |