Understanding C# Arrays

An array is a set of data items, accessed using a numerical index. More specifically, an array is a set of contigous data points of the same type (an array of ints,an array of string, an array of SportsCar, etc...)

// Create an array of 3 integers
int[] myInts = new int[3];
// Create a 100 item string array, indexed 0-99
string[] booksOnDotNet = new string[100];

After you have defined an array variable, you are then able to fill the elements index by index.

// Filling
myInts[0] = 12;
myInts[1] = 100;
myInts[2] = 555;
// Now printing
foreach (int i in myInts)
{
    Console.WriteLine(i);
}

Note: Be aware that if you declare an array, but do not explicitly fill each index, each item will be set to the default value of the data type. (boo -> false, int -> 0 ...).

Looking at the C# Array Initialization Syntax

In addition to filling an array element by element, you can fill the items of an array using C# array initialization syntax. To do so, specify each array item within the scope of curly brackets ({}). This syntax can be helpful when you are creating an array of a known size and want to quickly specify initial values.

// 1.rule
string[] strArray = new string[] {"one","two","three"};
// 2.rule
bool[] boolArray = {false,true,false};
// 3.rule
int[] intArray = new int[4] {1,2,3,4};

Understanding Implicitly Typed Local Arrays

The var keyword can be used to define "implicitly typed" local array. Using this technique, you can allocate new array variable without specifying the type contained within the array itself. (Note: You must use the new keyword when using this approach).

// a is really int[]
var a = new int[]{1,10,100,1000};
// b is really double[]
var b = new[]{1,1.5,2.5,2};
// c is really string[]
var c = new[]{"Hello",null,"three"};

An implicity typed local array does not default to System.Object; thus, the following generates a compile-time error.

// Compile-time error
var d = new[] {1, 2.5, 3}; // Error: Mixed types.

Working with Multidimensional Array

C# supports 2 varieties of multidimensional arrays. The first of these is termed a rectangular array, which is simply an array of multiple dimensions, where each row is of the same length. To declare and fill a multidimensional rectangular array, as follows:

// A rectangular MD array
int[,] myMatrix;
myMatrix = new int[3, 4];
for (int i = 0; i < 3; i++)
 {
     for (int j = 0; j < 4; j++)
     {
         myMatrix[i, j] = i + j;
     }
 }

The second type of multidimensional array is termed a "jagged array". As the name implies, jagged arrays contain same number of inner arrays, each of which may have a different upper limit.

int[][] myJagArray = new int[5][];
// Create the jagged array.
for (int i = 0; i < myJagArray.Length; i++)
 {
     myJagArray[i] = new int[i + 7];
 }
// A int each row (remember,wach element is default zero!)
for (int i = 0; i < myJagArray.Length; i++)
 {
     for (int j = 0; j < myJagArray[i].Length; j++)
     {
         myJagArray[i][j] = i + j;
         Console.Write(myJagArray[i][j]);
     }
     Console.WriteLine();
 }

Using Arrays As Arguments or Return Values

After you have create an array, you are free to pass it as an argument or receive it as a member return value.

static void PrintArray(int[] myInts)
 {
     for (int i = 0; i < myInts.Length; i++)
     {
         System.Console.WriteLine("Item {0} is {1}", i, myInts[i]);
     }
 }
static string[] GetStringArray()
 {
     string[] theStrings = { "Hello", "from", "GetStringArray" };
     return theStrings;
 }

These methods can be invoked as you would expect:

// Pass array as parameter.
int[] ages = { 20, 22, 23, 0 };
PrintArray(ages);
// Get array as return value.
string[] strs = GetStringArray();
foreach (string s in strs)
 {
     Console.WriteLine(s);
 }

Using the System.Array Base Class

Every array you create gathers much of its functionality from the System.Array class. Using these common members, you can operate on an array using a consistent object model.

Members

Clear()This static method sets a range of elements in the array to empty values (0 for numbers, null for object references, false for Booleans.)
Copy()This method is used to copy elements from the source array into the destination array.
LengthThis property returns the number of items within the array.
RankThis property returns the number of dimensions of the current array.
Reverse()This static method reverses the contents of a one-dimensional array.
Sort()This static method sorts a one-dimensional array of intrinsic types. If the elements in the array implements Icomparer interface, you can also sort your custom types.

// İnitialize items at startup
string[] gothicBands = { "Tones on Tail", "Bauhaus" };
// Print out names in declared order.
for (int i = 0; i < gothicBands.Length; i++)
 {
     Console.WriteLine(gothicBands[i]);
 }
// Reverse them
Array.Reverse(gothicBands);
// Clear them
Array.Clear(gothicBands);

Notice that many members of System.Array are defined as static members and,are ,therefore, called at the class level(e.g, the Array.Sort()). Methods such as these are passed in the array you want to process other members of System.Array (such as the Length property) are bound at the object level; thus, you can invoke the member directly on the array.

Using Indices and Ranges (New 8.0, Updated 10.0)

C# 8 introduces 2 new types and 2 new operators for use when working with arrays.

  1. System.Index represents an index into a sequence.
  2. System.Range represents a subrange of indices.
  3. The index from end operator (^) specifies that the index is relative to the end of the sequence.
  4. The range operator (..) specifies the start and end of a range as its operands.

Note: Indices and ranges can be used with arrays, strings, Span<T>, ReadOnlySpan<T>, and IEnumerable<T>.

for (int i = 0; i < gothicBands.Length; i++)
 {
     Index idx = i;
     Console.WriteLine(gothicBands[idx]);
 }

The index from end operator lets you specify how many positions from the end of sequence, starting with the length.

for (int i = 1; i <= gothicBands.Length; i++)
 {
     Index idx = ^i;
     Console.WriteLine(gothicBands[idx]); // Write the array in reverse.
 }

The range operator specifies a start and end index and allows for access to a subsequence within a list. The start of the range is inclusive, and the end of the range is exclusive.

foreach (var item in gothicBands[0..2])
 {
     Console.WriteLine(item);
 }

Ranges can also be passed to a sequence using the new Range data type;

Range r = 0..2;
foreach (var item in gothicBands[r])
 {
     Console.WriteLine(item);
 }

Ranges can be defined using integers or Index variables.

Index idx1 = 0;
Index idx2 = 2;
Range r = idx1..idx2;
foreach (var itm in gothicBands[r])
 {
     Console.WriteLine(itm);
 }

The ElementAt() extension method (in the System.Linq namespace retrieves the element from the array at the specified location). The following code gets the second-to-last band from the list.

var band = gothicBands.ElementAt(^2);
Console.WriteLine(band);