#37 – All Value Types Have a Default Constructor

All built-in value types in C# support a default (parameterless) constructor using the new keyword.  The default constructor allows you to instantiate an object such that it takes on a default value.

You’d normally instantiate one of the built-in types by giving  the associated variable a value.  But it’s also possible to use the new keyword to cause the variable to take on a default value.

 int i;          // Not instantiated yet
 int n1 = 12;    // Instanatiated, w/value of 12
 int n2 = new int();   // Instantiated, w/default value

The default values for the built-in value types are:

  • bool type = false
  • Numeric types (e.g. int, float) = 0 or 0.0
  • char type = single empty character
  • DateTime type = 1/1/0001 12:00:00 AM

#36 – Variable Initialization and Definite Assignment

Variables must be assigned a value before they can be used.  You can declare a variable without initializing it, but attempting to reference the value of the variable before you’ve given it a value will result in a compiler error.

 int i;
 int j = i + 1;   // Error: Use of unassigned local variable 'i'

This requirement of definite assignment before use means that you are never able to reference an unassigned variable in C#.

It’s considered good practice to initialize a variable when you declare it.  This applies to both built-in types and custom types.

When you initialize a variable, the object that it references is said to be instantiated.

 Person p = new Person();
 int i = 0;

#35 – Declaring Variables

In C#, you declare a variable by specifying a type, followed by the name of the new variable.  You can also optionally initialize the variable at the time that you declare it.

If you initialize a variable at the time that it is declared, the initializer can be a literal value, an expression, or an array initializer.

 float length;
 int age = 46;
 string s = "Sean";
 Person p;
 Person q = new Person("Herman", 12);
 object o = s;
 int yrsLeft = 100 - age;
 int[] nums = { 10, 20, 30 };
 object[] stuff = { nums, age, q };

#34 – The object Type

In the .NET Framework, all types are derived from System.Object.  In C#, the object keyword is a synonym for this same type.  System.Object is the base class for all other types in .NET, including built-in types and custom types.

In C#, all types can be upcast to object.

 string msg = "A string";
 int n = 42;
 Person me = new Person("Sean", 46);

 // Can assign anything to an object variable
 object o = msg;
 o = n;
 o = me;

Any class that you create in C# is automatically derived from object.

The object type defines the following instance methods:

  • bool Equals(object)
  • void Finalize()
  • int GetHashCode()
  • Type GetType()
  • object MemberwiseClone()
  • string ToString()

The object type defines the following static methods:

  • bool Equals(object, object)
  • bool ReferenceEquals(object, object)

This means that every new class automatically inherits these methods.

 Person me = new Person("Sean", 46);
 int hash = me.GetHashCode();

#33 – The string Type

In addition to many built-in value types, like the numeric types, C# provides a built-in string type.  The string type is a reference type, equivalent to the .NET Framework System.String type.

Strings contain a sequence of Unicode (UTF16) characters, equivalent to an array of char.  Each character takes up exactly 2 bytes.

Strings are immutable, which means that you can’t change a string’s value without destroying the old string and creating a new one.

You can use the index operator [] to access individual characters in the string.  This will normally give you a single character, except for Unicode characters that are above U+FFFF and have to be represented using a surrogate pair.

Here are some examples:

 string msg = "We Love C#!";
 char fourth = msg[3];
 string thisnthat = "this" + "that";   // "thisthat"
string sub = msg.Substring(3, 4);  // "Love"
 string dash = msg.Replace(' ', '-');  // "We-Love-C#!"

 // Split into space-delimited words: "We", "Love", "C#!"
 string[] words = msg.Split(new char[]{' '});

 string concat = msg + " Yes we do.";
 bool foundLove = words[1].ToLower() == "love";

 // Convert to lowercase, find substring
 int findLove = msg.ToLower().IndexOf("love");

 // Iterate
 foreach (char c in msg)
 Console.Write(string.Format("{0}-", c));

 string newPtr = msg;   // Pointer to original string
 string new2 = String.Copy(msg);   // Creates new string instance
 msg = "change";        // But newPtr still pointing to old/orig string


#32 – Built-In Types

The C# language includes a variety of built-in types that you can use in your C# program.  Each has a built-in C# keyword for the type, but maps to a type in the .NET Framework.  The C# keyword is just shorthand for the complete type name as it exists in the framework.

Here are all of the C# built-in types that are value types, along with their class name in the .NET Framework.

  • bool – System.Boolean – 1 byte  (true|false)
  • byte – System.Byte – 1 byte   (0 to 255)
  • sbyte – System.SByte – 1 byte  (-128 to 127)
  • short – System.Int16 – 2 bytes  (-32,768 to 32,767)
  • ushort – System.UInt16 – 2 bytes  (0 to 65,535)
  • int – System.Int32 – 4 bytes  (-2,147,483,648 to 2,147,483,647)
  • uint – System.UInt32 – 4 bytes  (0 to 4,294,967,295)
  • long – System.Int64 – 8 bytes  (-9,223,372,036,854,775,808 to 9,223,372,036,854,775,807)
  • ulong – System.UInt64 – 8 bytes  (0 to 18,446,744,073,709,551,615)
  • float – System.Single – 4 bytes  (±1.5e−45 to ±3.4e38, 7 digit precision)
  • double – System.Double – 8 bytes  (±5.0e−324 to ±1.7e308, 15-16 digit precision)
  • decimal – System.Decimal – 16 bytes  (±1.0 × 10−28 to ±7.9 × 1028, 28-29 digit precision)
  • char – System.Char – 2 bytes  (U+0000 to U+ffff, UTF16 Unicode character)

#31 – Value Types and Reference Types

All types in C#, whether built-in or user-defined custom types, can be categorized as either value types or reference types.

  • Value types
    • Derive from System.ValueType (which derives from System.Object)
    • Allocated on the stack  (unless declared inside a reference type)
    • Value type variable contains value directly
    • Assignment makes a copy of the value
    • Passed by value (a copy is made)
    • Not garbage collected–die when they go out of scope
    • Either struct or enum
    • Sealed–can’t inherit from them
  • Reference types
    • Derive from System.Object or another reference type
    • Allocated on the heap
    • Reference type variable contains a reference (pointer) to the object’s contents (or contains null)
    • Assignment creates a new reference to the original object
    • Passed by reference  (pointer to object is passed)
    • Garbage collected
    • One of: class, delegate, array or interface
    • Support inheritance