#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

More

#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

#30 – Types, Variables, Values, Instances

In C#, a type dictates what kind of values can be stored in a variable.  A variable is a storage location for some data.  Every variable is an instance of a specific type and will have a value that can change during the lifetime of a program.

Constants are variables whose values do not change.  They also have a specific type.

Expressions resolve to a particular value when they are evaluated.  They also have a specific type.

There are a number of built-in types in C#  (e.g. int, float) as well as constructs that allow you to create your own types (e.g. class, enum).

#29 – Comments

Comments in a C# program denote text that is ignored by the compiler and therefore has no effect on the behavior of the program.

There are two types of comments in C#:

  • Single line comments:  start with //, extend to end of line
  • Delimited comments:  surrounded by /*  */, can span multiple lines

Examples:

 string s1 = "Hi";        // This is a single-line comment

 /*  Multiple line
  *  comment.  Nice convention to use
  *  asterisk at the start of each line. */

 string s2 = "/* This is a string, rather than a comment */";
 string s3 = "// same here";

 // Nested comments /* ignored */

 //--------------------------------------
 // Even better style for block comment
 //--------------------------------------

More

#28 – Operator Precedence

Each operator has an associated precedence, which indicates the order in which the operators are evaluated when evaluating the  expression.

When an expression has operators of the same precedence, they are evaluated according to their rules of associativity–left to right for all binary expressions, except for assignment and conditional operators, which are right to left.

Here are the C# operators, in order of precedence.  Operators in each group are of equal precedence.

  • Primary:  x.y  f(x)  a[x]  x++  x–  new  typeof  checked  unchecked
  • Unary:  +  –  !  ~  ++x  –x  (T)x
  • Multiplicative:  *  /  %
  • Additive:  +  –
  • Shift:  <<  >>
  • Relational:  <  >  <=  >=  is  as
  • Equality:  ==  !=
  • Logical AND:  &
  • Logical XOR:  ^
  • Logical OR:  |
  • Conditional AND:  &&
  • Conditional OR:  ||
  • Conditional:  ?:
  • Assignment:  =  *=  /=  %=  +=  -=  <<=  >>=  &=  ^=  |=

Precedence can be changed by using parentheses, the inner expressions being evaluated first.

More

#27 – Expressions, Operators and Operands

Expressions are sequences of operators and operands.  Evaluating an expression results in a single value for the entire expression.

Operators are the symbols used in expressions, indicating what operations apply to the operands in the expression.

Operands are the values acted upon by the operators, e.g. literals, results of function calls, other expressions.

There are three kinds of operators:

  • Unary – Takes one operand.  E.g.  x++
  • Binary – Takes two operands.  E.g.  x+y
  • Ternary – Takes three operands (the conditional operator).  E.g.  e ? x : y

More

#26 – Null Literal

The keyword null represents a null literal.  A null value indicates that a reference points to no object.

Examples:

 object o1 = null;
 if (o1 == null) Console.WriteLine("Yup, it's null");

 string s1 = null;    // Strings can also be null
 int n1 = s1.Length;  // Throws NullReferenceException, since s1 doesn't point to anything

#25 – String Literals

A string literal in C# represents a sequence of Unicode characters.  There are two main types of string literals in C#–regular string literals and verbatim string literals.  Verbatim string literals allow including special characters in a string directly, rather than having to specify them using an escape sequence.  All string literals are of type string.

Here are some examples of string literals:

 string s1 = "Hi";
 string s2 = @"Hi";       // Verbatim string literal--same thing
 string s3 = "C:\\Dir";   // C:\Dir  (escape seq for backslash)
 string s4 = @"C:\Dir";   // No escape seq required
 string s5 = "\x48\x69";  // Hi  (hex codes for each character)
 string s6 = "\x20AC 1.99";  // € 1.99
 string s7 = "€ 1.99";    // Unicode directly in string

 // UTF-32 characters using surrogate pairs
 string s8 = "\U00020213";      // U+20213 (UTF-32)
 string s9 = "\ud840\ude13";    // Equiv surrogate pair
 string s10 = "𠈓";             // Same character

Note:

  • \u is followed by 4-byte UTF16 character code
  • \U is followed by 8-byte UTF32 character code, which is then converted to equivalent surrogate pair