Author avatar

Pavneet Singh

Deep Dive Into Array Basics - Arrays and Utility Methods

Pavneet Singh

  • Feb 8, 2019
  • 11 Min read
  • 2,429 Views
  • Feb 8, 2019
  • 11 Min read
  • 2,429 Views
C#
Arrays

Introduction

The previous guide, Deep Dive into Array Basics Part 1, I covered the fundamentals of using arrays to manage data. An array provides a simple and effective way to store data, but just storing data is not enough. Consider a billing application; often a requirement is to sort the data in descending order so that a customer can pay attention to the most expensive items first.

Arrays are a reference type, meaning they are type of Array class, therefore Array is the base/abstract class of every array object. An Array class is bundled with numerous utility methods to perform common tasks like copying, sorting, searching items, indexing, etc. In this guide, we will explore Array class and its helpful methods.

Array Class and Methods

An Array class is an abstract class and part of the System namespace. abstract class means that the object of an array class cannot be created using a new operator; instead you can use CreateInstance.

CreateInstance

  • CreateInstance: method used to construct an array.
1Array carArray = Array.CreateInstance(typeof(String), 5);
csharp

To create an array object we need:

  • Type: data that can be obtained either using typeof operator or using GetType() method .
1typeof(int);
2
3"PS".GetType();
4
5Type.GetType("System.String"); // using (namespace + class) as string value
csharp
  • Length: The size of the array to store specific amount of item(s).

Only a static method can be invoked using name of the class. Hence CreateInstance static method is invoked using class-name, i.e. Array.

SetValue

  • SetValue: To set a value in an array at a specific index.
1carArray.SetValue("Tesla", 0);
2
3carArray.SetValue("Waymo", 1);
4
5carArray.SetValue("GM", 2);
6
7carArray.SetValue("Uber", 3);
8
9carArray.SetValue("Ford", 4);
csharp

GetValue

  • GetValue: To get the value from array with an index.
1for(var i=0 ;i < carArray.Length; i++){
2
3    Console.Write("{0} ",carArray.GetValue(i));
4
5}
6
7// output: Tesla Waymo GM Uber Ford
csharp

Note: It is also possible to convert Array class object into native type array declaration using explicit casting.

1string[] arr = (string[])carArray;
2
3Console.WriteLine("[{0}]", string.Join(", ", arr)); // [Tesla, Waymo, GM, Uber, Ford]
csharp

Sort

  • Sort: To sort array in natural order (Ascending for numerics and Lexicographical for string values).
1Array.Sort(carArray); //output: Ford GM Tesla Uber Waymo
csharp

There are several overloaded methods available for sort and many others to customize the behavior. We can also sort the array in reverse order by passing IComparer object to a overloaded version of sort method:

1Array.Sort(carArray, new ReverserIComparerOrder()); // output: Waymo Uber Tesla GM Ford
2// ReverserIComparerOrder class
3
4public class ReverserIComparerOrder : IComparer
5{
6  int IComparer.Compare(Object x, Object y)
7  {
8    return ((new CaseInsensitiveComparer()).Compare(y, x)); // compare y with x instead of x with y
9  }
10}
csharp

The sorting algorithm depends upon the number of inputs:

  • If the partition size is fewer than 16 elements, it uses an insertion sort algorithm.

  • If the number of partitions exceeds 2 * Log ^ N, where N is the range of the input array, it uses a Heapsort algorithm.

  • Otherwise, it uses a Quicksort algorithm.

Search

Search: Arrays class provides BinarySearch method which is based on Binary search algorithm which will return the index value of the searched item.

Binary search is only applicable for sorted arrays, so an array must be sorted before applying binary search.

1int index = Array.BinarySearch(carArray, "Tesla"); //output: 2
csharp

BinarySearch method will return a negative value if an element is not present in an array.

Clear and Empty Arrays

  • Clear: Will reset all the values of an array element to their default value. For string, the default value is null.

Array.Clear(Array, start index, number of elements to clear)

1Array.Clear(carArray, 2, 2); // output: [Tesla,Waymo,GM,,]
csharp
  • Empty: When no valid return type of an array is available, then return Array.Empty<Type>() because it can avoid the clutter of null check or potential exceptions. To return an empty string array:
1Array.Empty<string>();  // here string can be replaced with reference class or value datatype name
csharp

ConvertAll

  • ConvertAll: To convert one type of array into another. The below code will convert the string type marks into int.
1string[] marksOf3 = {"70", "90", "85"};
2
3int[] intMarks = Array.ConvertAll(marksOf3, new Converter<string,int>(int.Parse));
4
5// int.Parse is a method name which converts a string to int
csharp

Copy

  • Copy: Array length is fixed, though a larger array can be created from a smaller one. The source array will be copied into larger array to store more values.
1string[] marksOf3 = {"70", "90", "85"};
2
3string[] marksOf5 = new string[5];
4
5Array.Copy(marksOf3,marksOf5,marksOf3.Length);// marksOf5 = [70,90,85,,] : now with two free places
csharp

Find or FindAll

  • Find or FindAll: To get single value or an array, after applying a condition.
1Array.Find(intMarks, mark => mark>80); // output: 90
2
3Array.FindAll(intMarks, mark => mark>80); // output: [90,85]
csharp

There are overloaded methods to find the index either from left or right side of array like IndexOf, LasrIndexOf

Resize

  • Resize: To manipulate the size of an array. Internally, it will create a larger array (of desired value) and perform the copy operation.
1Array.Resize<string>(ref marksOf3, 10); // read previous article for ref
csharp

Reverse

  • Reverse: To reverse the sequence
1Array.Reverse(carArray);
csharp

Generic Array

Generic provides the ability to handle any type of data or when data type is unknown while writing code. You can use Type object to create array of a particular type e.g. string in Array.CreateInstance(typeof(String), 5). Type is a class which stores the metadata about applicable methods, max/min value, memory information, etc., which are required to create objects at runtime and perform operations on them. A small example is to create a method to print elements of one dimensional array:

1static void PrintArray<T>(T[] data){
2  Console.WriteLine("[{0}]", String.Join(",", data));
3}
4
5PrintArray(new string[]{"P", "S"}); // output: [P,S]
6
7PrintArray(new int[]{1,2,3,4}); //output: [1,2,3,4]
csharp

Although you cannot perform any specific operation like addition to all elements because type will be resolved at compile time and will be replaced with a specific type, hence generic are only compile time. An appropriate substitution or code will be generated while resolving generic relations at compile time.

A generic array can also be created using generic parameter:

1public class GenericArray<T> {
2  private T[] array;
3  private int index = 0;
4
5  public GenericArray(int size) {
6    array = new T[size + 1];
7  }
8
9  public T GetItem(int index) {
10      return array[index];
11  }
12
13  public void SetItem(T item, int index){
14    if(index >= 0 && index < array.Length) // verify, index is neither negative nor greater than array capacity
15      array[index] = item;
16  }
17
18  public void AddItem(T item){
19    if(index < array.Length-1) // verify, array is not full
20      array[index++] = item;
21  }
22 }
23
24// Usage
25
26GenericArray<int> ints = new GenericArray<int>(5);
27
28ints.AddItem(5);
29
30ints.AddItem(3);
31
32Console.WriteLine(ints.GetItem(1)); // 3
33
34GenericArray<string> initials = new GenericArray<string>(5);
35
36initials.AddItem("P");
37
38initials.AddItem("S");
39
40Console.WriteLine(initials.GetItem(1)); // S
csharp

Some benefits of generics are type safety, code re-usability, and avoid using Object type with casting.

Thread Safety

Threads are sub-processes and are used to break a large process into smaller sub-processes while executing them simultaneously (also dependent on hardware). Like generating the sum of a large series by splitting the series into sub-series and adding the result of all sub-series.

Thread safety is related to the write/modify operation of data. If multiple threads can change the data at the same time then this can lead to unexpected changes in data, but read operations will have no side-effects. A locking mechanism can be used to synchronize the access meaning that only one process at a time (which has its write lock activated) can modify the data.

1lock(carArray.SyncRoot){
2  foreach (Object item in carArray)
3      Console.WriteLine(item);
4}
csharp

foreach is a loop to traverse the whole array. It is possible that other processes may try to modify the carArray while traversing an operation. This will cause an InvalidOperationException exception so lock will prevent carArray from being accessed by other processes.

Properties

Array properties like IsFixedSize, IsReadOnly, IsSynchronized will always return fix values as true, false and false respectively because they are constant values and used by the sub-classes of an array, specifically for collection framework implementation like ArrayList etc.

  • Rank: a property which describes the dimension of an array.
1Console.WriteLine(new int[2,2]{ {1,2},{3,4} }.Rank); // Rank is 2 because it's a two dimensional array
csharp
  • Length and LongLength return the count of total elements in the array as 32bit, 64bit int value respectively.

Note

  • Starting with the .NET Framework 2.0, the Array class implements the System.Collections.Generic.IList, System.Collections.Generic.ICollection, and System.Collections.Generic.IEnumerable generic interfaces but there is no generic information present at compile time. Array object can be explicitly cast to generic list types:
1IList<string> list = (IList<string>)carArray;
2
3//or
4
5char[] book = new[]{ 'W' , 'X' , 'Y' , 'Z' };
6
7IList<char> bookList = book;
csharp

but any attempt to invoke add, insert and remove

1list.Add("Gizmo");
csharp

This will result in NotSupportedException: an exception; considered as bad practice.

I hope you found this guide informative and engaging. Share your appreciation and press like on this guide. Thank you for reading!