1 chap02
Jason Zhu edited this page 2021-08-06 10:38:54 +10:00

Chapter 2. C# Language Basics

2.1 A First C# Program

2.2 Syntax

2.3 Type Basics

2.4 Numeric Types

2.5 Boolean Type and Operators

2.6 Strings and Characters

2.7 Arrays

Array = a fixed number of variables (i.e. elements) of a particular type

  • elements in array always stored in a continuous block of memory. Hence, fast access
  • declared using type[] array_name (square brackets after element type)
  • access element using [i] following 0-based index.

e.g. Declare an array

char[] vowels = new char[5];

Length of array:

  • Length property of an array return number of elements in array
  • Array length cannot be changed after creation (memory is reserved)
  • For more flexible data structure, System.Collection namespace provides more, like dynamically sized array, or dictionaries.

Array initialization expression declare and populate in single step:

char[] vowels = new char[] {'a','e','i','o','u'};
// or
char[] vowels = {'a', 'e', 'i', 'o', 'u'};

System.Array class (detailed in Chap7):

  • all arrays inherit from it
  • This array class provides many methods, e.g. get, set elements

2.7.1 Default Element Initialization

Creating an array will preintialize the element with default values using 0s (i.e. bitwise 0ing the memory block)

int[] a = new int[1000];
Console.Write(a[123]); // 0

Values types versus reference types

Array itself is a reference type object.

  • it can be null
int[] a = null;

What happen when element is Value types or Reference type?:

  • Value type: each element value is allocated as part of array (i.e. initialized by 0ing memory block)
  • Reference type: element is allocated as null reference
    • Solution: explicitly instantiate all elements after instantiating the array
// Element are value type
public struct Point { public int X, Y; }
Point[] a = new Point[1000];
int x = a[500].X;

// Element are reference type
public class Point { public int X, Y; }
Point[] a = new Point[1000];
int x = a[500].X; // Run-time error, NullReferenceException

// Solution: instantiate element after array instantiate
Point[] a = new Point[1000];
for (int i = 0; i < a.Length; i++ )
{
    a[i] = new Point();
}

2.7.2 Indices and Ranges

Indcies & Ranges types (introduced in C#) simplify working with array elements

Indices

Index: refer element relative to the end of array using ^

  • ^0 equals to length of array
  • C# implement indices using Index type

e.g. access element using index

char[] vowels = new char[] {'a','e','i','o','u'};
char lastElement = vowels[^1]; // 'u', last element
char secondToLast = vowels[^2]; // 'o'
// vowels[^0]; create error as out of index

e.g. Index type

Index first = 0;
Index last = ^1; // access last
char firstElement = vowels[first]; // 'a'
char lastElement = vowels[last]; // 'u'

Ranges

C# implement ranges using Range type to slice array using:

  • .. operator: from index a to index b
  • ^ operator: from the end

e.g. Use Range for slicing array

char[] firstTwo = vowels[..2]; // 'a', 'e'
char[] lastThree = vowels[2..]; // 'i', 'o', 'u'
char[] middleOne = vowels[2..3]; // 'i'
char[] lastTwo = vowels[^2..]; // 'o', 'u'

e.g. Range type

Range firstTwoRange = 0..2;
char[] firstTwo = vowels[firstTwoRange];

2.7.3 Multidimensional Arrays

2 varieties of multidimensional array:

  • Rectangular (长方形): a n-dimensional block of memory
  • jagged (锯齿状): arrays of arrays (each element array may not be the same size)

Rectangular arrays

  • Declaring array using commas to separate dimension in square bracket int[3,3]
  • .GetLength() return length for given dimension (e.g. .GetLength(0) for dimension 0)

e.g. declaring array

int[,] matrix = new int[3,3];

e.g. get dimension

for (int i = 0; i < matrix.GetLength(0); i++)
{
  for (int j = 0; j < matrix.GetLength(1); j++)
  {
    matrix[i,j] = i * 3 + j;
  }
}

Jagged arrays

  • Declare jagged array using successive square bracket for each dimension int[3][]
    • Inner dimension aren't specified, as inner array can be an arbitrary length.
    • Each inner array is implicitly initialized to null. Hence, need mannually create each inner array via for loop or explicit initialization
// Declaration
int[][] matrix = new int[3][];

// Create inner array in matrix
for (int i = 0; i < matrix.Length; i++ )
{
  matrix[i] = new int[3]; // Create inner array
  for (int j = 0; j < matrix[i].Length; j++)
  {
    matrix[i][j] = i * 3 + j;
  }
}

e.g. explicit array initialization

int[][] matrix = new int[][]
{
  new int[] {0,1,2},
  new int[] {3,4,5},
  new int[] {6,7,8,9}
};

2.7.4 Simplified Array Initialization Expressions

Full array initialization is shown as e.g. above. Two ways of shorten array initialization expression

  • Method 1: Omit new and type qualification
  • Method 2: use var to let compiler deduct type
    • Can be further simplified by omit type qualifier after new and have compiler infer the array type

e.g. method 1

char[] vowels = {'a', 'e', 'i', 'o', 'u'};
int[,] rectangularMatrix = 
{
  {0,1,2},
  {3,4,5},
  {6,7,8}
};
int[][] jaggedMatrix = {
  new int[] {0,1,2},
  new int[] {3,4,5},
  new int[] {6,7,8,9}
};

e.g. method 2

var i = 3;
var s = "sausage"; // implicitly type string

var rectMatrix = new int[,]
{
  {0,1,2},
  {3,4,5},
  {6,7,8}
};

var jaggedMat = new int[][]
{
  new int[] {0,1,2},
  new int[] {3,4,5},
  new int[] {6,7,8,9}
}

// Further simplified
var vowels = new[] {'a','e','i','o'};

2.7.5 Bounds Checking

IndexOutOfRangeException will be thrown if use invalid index, as all array indexing is bounds checked by the runtime.

int[] arr = new int[3];
arr[3] = 1; // IndexOutOfRangeException thrown

2.8 Variables and Parameters

2.9 Expressions and Operators

2.10 Null Operators

C# provides 3 operators to work with null:

  • null-coalescing operator: ??;
  • null-coalecing assignment operator (introduced in C# 8): ??=;
  • null-conditional operator: ?.;

2.10.1 Null-Coalescing Operator

??: Means "If the operand to the left is non-null, give it to me; otherwise, give me another value"

string s1 = null;
string s2 = s1 ?? "nothing";

2.10.2 Null-Coalescing Assignment Operator

?=: Means "If the operand to the left is null, assign the right operand to the left

if (myVariable == null) myVariable = someDefault;

2.10.3 Null-Conditional Operator

?. is the null-conditional or Elvis operator: Allows developer to call methods and access members just like the standard dot operator except that if the operand on the left is null, instead get NullReferenceException

  • Useful in implementing lazy evaluation
  • Elvis can be repeated
System.Text.StringBuilder sb = null;
string s = sb?.ToString(); // No error, instead of evaluating to null
// Same as
string s = (sb == null ? null : sb.ToString());

System.Text.StringBuilder sb = null;
string s = sb?.ToString().ToUpper(); // evaluates to null without error

// Repeated use of Elvis
x?.y?.z
// Same as
x == null ? null : (x.y == null ? null : x.y.z)

TODO: Summary not finished, will come back after nullable value type in chap4

2.11 Statements

2.12 Namespaces

2.12.1 The using Directive

2.12.2 using static

2.12.3 Rules Within a Namespace

2.12.4 Aliasing Types and Namespaces

2.12.5 Advanced Namespace Features