Wednesday 4 January 2012

Integral types

Because the type system in C# is unified with other languages that are CLI-compliant, each integral C# type is actually an alias for a corresponding type in the .NET framework. Although the names of the aliases vary between .NET languages, the underlying types in the .NET framework remain the same. Thus, objects created in assemblies written in other languages of the .NET Framework can be bound to C# variables of any type to which the value can be converted, per the conversion rules below. The following illustrates the cross-language compatibility of types by comparing C# code with the equivalent Visual Basic .NET code:
// C#
public void UsingCSharpTypeAlias()
{
int i = 42;
}
public void EquivalentCodeWithoutAlias()
{
System.Int32 i = 42;
}

Visual Basic .NET
Public Sub UsingVisualBasicTypeAlias()
Dim i As Integer = 42
End Sub
Public Sub EquivalentCodeWithoutAlias()
Dim i As System.Int32 = 42
End Sub
Using the language-specific type aliases is often considered more readable than using the fully-qualified .NET Framework type names.
The fact that each C# type corresponds to a type in the unified type system gives each value type a consistent size across platforms and compilers. That consistency is an important distinction from other languages such as C, where, e.g. a long is only guaranteed to be at least as large as an int, and is implemented with different sizes by different compilers.  As reference types, variables of types derived from object (i.e. any class) are exempt from the consistent size requirement. That is, the size of reference types like System.IntPtr, as opposed to value types like System. Int, may vary by platform. Fortunately, there is rarely a need to know the actual size of a reference type.
There are two predefined reference types: object, an alias for the System.Object class, from which all other reference types derive; and string, an alias for the System.String class. C# likewise has several integral value types, each an alias to a corresponding value type in the System namespace of the .NET Framework. The predefined C# type aliases expose the methods of the underlying .NET Framework types. For example, since the .NET Framework's System.Int32 type implements a ToString() method to convert the value of an integer to its string representation,
C#'s int type exposes that method:
int i = 97;
string s = i.ToString();
// The value of s is now the string "97".
Likewise, the System.Int32 type implements the Parse() method, which can therefore be accessed via C#'s int type:
string s = "97";
int i = int.Parse(s);
// The value of i is now the integer 97.
The unified type system is enhanced by the ability to convert value types to reference types (boxing) and likewise to convert certain reference types to their corresponding value types (unboxing). This is also known as casting.
object boxedInteger = 97;
int unboxedInteger = (int)boxedInteger;
Boxing and casting are, however, not type-safe: the compiler won't generate an error if the programmer mixes up the types. In the following short example the mistake is quite obvious, but in complex programs it may be real hard to spot. Avoid boxing, if possible.
object getInteger = "97";
int anInteger = (int)getInteger; // no compile-time error, the program will crash, however The built-in C# type aliases and their equivalent .NET Framework types follow:

Integers
C# Alias         .NET Type            Size (bits)         Range
  sbyte           System.SByte              8             -128 to 127
  byte             System.Byte                8               0 to 255
  short            System.Int16              16            -32,768 to 32,767
  ushort          System.UInt16           16             0 to 65,535
  char             System.Char              16             A unicode character of code 0 to 65,535
   int               System.Int32              32            -2,147,483,648 to 2,147,483,647
   uint             System.UInt32           32              0 to 4,294,967,295
   long            System.Int64              64           -9,223,372,036,854,775,808 to                                                                         9,223,372,036,854,775,807                                  
   ulong           System.UInt64          64             0 to 18,446,744,073,709,551,615

Floating-point
     C# Alias    .NET Type          Size (bits)   Precision                            Range
      float          System.Single         32           7 digits                       1.5 x 10-45 to 3.4 x 1038
     double       System.Double       64          15-16 digits                 5.0 x 10-324 to 1.7 x 10308
     decimal      System.Decimal     128       28-29 decimal places    1.0 x 10-28 to 7.9 x 1028

Other predefined types
 C# Alias   .NET Type          Size (bits)                               Range
  bool       System.Boolean     32                true or false, which aren't related to any integer in C#.
  object    System.Object       32/64            Platform dependant (a pointer to an object).
   string     System.String         16 * length   A unicode string with no special upper bound.