Learning C#

C# offers a variety of data structures that can be broadly categorized into primitive types, collections, and more specialized data structures. Here is an overview of some commonly used data structures in C#:

Primitive Types

  1. int, long, float, double, char, bool, etc.

    • These are the basic building blocks for data manipulation in C#.

Collections

Arrays

  • Single-dimensional arrays: int[] array = new int[10];

  • Multi-dimensional arrays: int[,] matrix = new int[3, 3];

  • Jagged arrays: int[][] jaggedArray = new int[3][];

Collections from System.Collections Namespace

  • ArrayList: A non-generic collection of objects.

      using System;
      using System.Collections;
    
      class Program
      {
          static void Main()
          {
              // Create an ArrayList
              ArrayList arrayList = new ArrayList();
    
              // Add elements to the ArrayList
              arrayList.Add(1); // Adding an integer
              arrayList.Add("Hello"); // Adding a string
              arrayList.Add(3.14); // Adding a double
              arrayList.Add(DateTime.Now); // Adding a DateTime object
    
              // Accessing elements in the ArrayList
              Console.WriteLine("First element: " + arrayList[0]); // Output: First element: 1
              Console.WriteLine("Second element: " + arrayList[1]); // Output: Second element: Hello
              Console.WriteLine("Third element: " + arrayList[2]); // Output: Third element: 3.14
              Console.WriteLine("Fourth element: " + arrayList[3]); // Output: Fourth element: Current DateTime
    
              // Modify an element in the ArrayList
              arrayList[1] = "World";
              Console.WriteLine("Modified second element: " + arrayList[1]); // Output: Modified second element: World
    
              // Iterate through the ArrayList
              Console.WriteLine("\nIterating through the ArrayList:");
              foreach (var item in arrayList)
              {
                  Console.WriteLine(item);
              }
    
              // Remove an element from the ArrayList
              arrayList.Remove(3.14); // Remove the element with value 3.14
              Console.WriteLine("\nArrayList after removing 3.14:");
              foreach (var item in arrayList)
              {
                  Console.WriteLine(item);
              }
    
              // Check if an element exists in the ArrayList
              bool containsHello = arrayList.Contains("Hello");
              bool containsWorld = arrayList.Contains("World");
              Console.WriteLine("\nContains 'Hello': " + containsHello); // Output: Contains 'Hello': False
              Console.WriteLine("Contains 'World': " + containsWorld); // Output: Contains 'World': True
    
              // Clear the ArrayList
              arrayList.Clear();
              Console.WriteLine("\nArrayList after clearing all elements. Count: " + arrayList.Count); // Output: ArrayList after clearing all elements. Count: 0
          }
      }
    
  • Hashtable: A collection of key/value pairs, organized based on the hash code of the key.

      using System;
      using System.Collections;
    
      class Program
      {
          static void Main()
          {
              // Create a new Hashtable instance
              Hashtable hashtable = new Hashtable();
    
              // Adding key/value pairs to the Hashtable
              hashtable.Add(1, "One");
              hashtable.Add(2, "Two");
              hashtable.Add(3, "Three");
    
              // Accessing values in the Hashtable using keys
              Console.WriteLine("Value for key 1: " + hashtable[1]);
              Console.WriteLine("Value for key 2: " + hashtable[2]);
              Console.WriteLine("Value for key 3: " + hashtable[3]);
    
              // Checking if a key exists
              if (hashtable.ContainsKey(2))
              {
                  Console.WriteLine("Key 2 exists in the hashtable.");
              }
    
              // Checking if a value exists
              if (hashtable.ContainsValue("Three"))
              {
                  Console.WriteLine("Value 'Three' exists in the hashtable.");
              }
    
              // Removing a key/value pair
              hashtable.Remove(2);
    
              // Checking the count of elements in the Hashtable
              Console.WriteLine("Number of elements in hashtable: " + hashtable.Count);
    
              // Iterating through the Hashtable
              foreach (DictionaryEntry entry in hashtable)
              {
                  Console.WriteLine("Key: " + entry.Key + ", Value: " + entry.Value);
              }
    
              // Trying to access a removed key
              if (!hashtable.ContainsKey(2))
              {
                  Console.WriteLine("Key 2 has been removed from the hashtable.");
              }
          }
      }
    

Collections from System.Collections.Generic Namespace

  • List: A dynamic array that can grow as needed.

      using System;
      using System.Collections.Generic;
    
      class Program
      {
          static void Main()
          {
              // Create a new List instance
              List<int> list = new List<int>();
    
              // Adding elements to the List
              list.Add(1);
              list.Add(2);
              list.Add(3);
    
              // Accessing elements in the List using index
              Console.WriteLine("Element at index 0: " + list[0]);
              Console.WriteLine("Element at index 1: " + list[1]);
              Console.WriteLine("Element at index 2: " + list[2]);
    
              // Inserting an element at a specific index
              list.Insert(1, 5); // Inserts 5 at index 1
    
              // Accessing the updated list
              Console.WriteLine("After inserting 5 at index 1:");
              foreach (int item in list)
              {
                  Console.WriteLine(item);
              }
    
              // Removing elements from the List
              list.Remove(2); // Removes the first occurrence of 2
              list.RemoveAt(0); // Removes the element at index 0
    
              // Checking the count of elements in the List
              Console.WriteLine("Number of elements in list: " + list.Count);
    
              // Iterating through the List
              Console.WriteLine("Iterating through the list:");
              foreach (int item in list)
              {
                  Console.WriteLine(item);
              }
    
              // Checking if an element exists in the List
              if (list.Contains(3))
              {
                  Console.WriteLine("List contains the number 3.");
              }
    
              // Converting the List to an array
              int[] array = list.ToArray();
              Console.WriteLine("Elements in the array:");
              foreach (int item in array)
              {
                  Console.WriteLine(item);
              }
    
              // Clearing the List
              list.Clear();
              Console.WriteLine("Number of elements in list after clearing: " + list.Count);
          }
      }
    
  • Dictionary<TKey, TValue>: A collection of key/value pairs.

      using System;
      using System.Collections.Generic;
    
      class Program
      {
          static void Main()
          {
              // Create a new Dictionary instance
              Dictionary<int, string> dictionary = new Dictionary<int, string>();
    
              // Adding key/value pairs to the Dictionary
              dictionary.Add(1, "One");
              dictionary.Add(2, "Two");
              dictionary.Add(3, "Three");
    
              // Accessing values in the Dictionary using keys
              Console.WriteLine("Value for key 1: " + dictionary[1]);
              Console.WriteLine("Value for key 2: " + dictionary[2]);
              Console.WriteLine("Value for key 3: " + dictionary[3]);
    
              // Checking if a key exists
              if (dictionary.ContainsKey(2))
              {
                  Console.WriteLine("Key 2 exists in the dictionary.");
              }
    
              // Checking if a value exists
              if (dictionary.ContainsValue("Three"))
              {
                  Console.WriteLine("Value 'Three' exists in the dictionary.");
              }
    
              // Removing a key/value pair
              dictionary.Remove(2);
    
              // Checking the count of elements in the Dictionary
              Console.WriteLine("Number of elements in dictionary: " + dictionary.Count);
    
              // Iterating through the Dictionary
              foreach (KeyValuePair<int, string> entry in dictionary)
              {
                  Console.WriteLine("Key: " + entry.Key + ", Value: " + entry.Value);
              }
    
              // Trying to access a removed key
              if (!dictionary.ContainsKey(2))
              {
                  Console.WriteLine("Key 2 has been removed from the dictionary.");
              }
    
              // Updating the value for an existing key
              dictionary[3] = "Three Updated";
              Console.WriteLine("Updated value for key 3: " + dictionary[3]);
    
              // Adding a new key/value pair using the indexer
              dictionary[4] = "Four";
              Console.WriteLine("Value for key 4: " + dictionary[4]);
          }
      }
    
    • Dictionary<TKey, TValue> is type-safe, optimized for performance, and does not allow null keys.

    • Hashtable is a legacy, non-generic collection that allows null keys and requires casting, which can lead to runtime errors.


Queue: Follows FIFO (first-in, first-out). The first element added is the first one to be removed.

  • Adding index starts from (0,1,2..n), pop means removes always 0

  • Front means current 0 the index

  • Stack: Follows LIFO (last-in, first-out). The last element added is the first one to be removed.

  • Adding index starts from (n, n-1, n-2), pop means removes always nth index( -1 index in python)

  • Front means current nth index( -1 index in python)

  • Primary Operations:

    • Queue:

      • push(): Adds an element to the back of the queue.

      • pop(): Removes the front element of the queue.

      • front(): Accesses the front element.

      • back(): Accesses the back element.

    • Stack:

      • push(): Adds an element to the top of the stack.

      • pop(): Removes the top element of the stack.

      • top(): Accesses the top element.

Uses

  • Queue:

    • Breadth-First Search (BFS): Used in graph and tree traversal algorithms.

    • Task Scheduling: Managing tasks in a multi-tasking environment.

    • Buffer Management: Implementing buffers in networking and I/O operations.

  • Stack:

    • Depth-First Search (DFS): Used in graph and tree traversal algorithms.

    • Expression Evaluation: Evaluating mathematical expressions and parsing.

    • Backtracking Algorithms: Solving puzzles and pathfinding problems.

    • Function Call Management: Managing function calls and recursion in programming languages.


    Queue: A first-in, first-out (FIFO) collection.

    using System;
    using System.Collections.Generic;

    class Program
    {
        static void Main()
        {
            // Create a new Queue instance
            Queue<string> queue = new Queue<string>();

            // Adding elements to the Queue
            queue.Enqueue("First");
            queue.Enqueue("Second");
            queue.Enqueue("Third");

            // Displaying the front element
            Console.WriteLine("Front element: " + queue.Peek()); // Outputs "First"

            // Removing elements from the Queue
            string removedElement = queue.Dequeue();
            Console.WriteLine("Removed element: " + removedElement); // Outputs "First"

            // Displaying the new front element after dequeue
            Console.WriteLine("New front element: " + queue.Peek()); // Outputs "Second"

            // Checking the count of elements in the Queue
            Console.WriteLine("Number of elements in queue: " + queue.Count);

            // Iterating through the Queue
            Console.WriteLine("Elements in queue:");
            foreach (string item in queue)
            {
                Console.WriteLine(item);
            }

            // Checking if the Queue contains a specific element
            if (queue.Contains("Second"))
            {
                Console.WriteLine("Queue contains 'Second'");
            }

            // Clearing the Queue
            queue.Clear();
            Console.WriteLine("Number of elements in queue after clearing: " + queue.Count);
        }
    }
  • Stack: A last-in, first-out (LIFO) collection.

      using System;
      using System.Collections.Generic;
    
      class Program
      {
          static void Main()
          {
              // Create a stack of strings
              Stack<string> stack = new Stack<string>();
    
              // Push items onto the stack
              stack.Push("First");
              stack.Push("Second");
              stack.Push("Third");
    
              // Display all items in the stack
              Console.WriteLine("Items in the stack:");
              foreach (string item in stack)
              {
                  Console.WriteLine(item);
              }
    
              // Pop items from the stack
              Console.WriteLine("\nPopping items:");
              while (stack.Count > 0)
              {
                  string poppedItem = stack.Pop();
                  Console.WriteLine($"Popped: {poppedItem}");
              }
    
              // Check if the stack is empty
              if (stack.Count == 0)
              {
                  Console.WriteLine("\nThe stack is now empty.");
              }
    
              // Push more items
              stack.Push("Fourth");
              stack.Push("Fifth");
    
              // Peek at the top item without popping it
              string topItem = stack.Peek();
              Console.WriteLine($"\nThe item at the top of the stack is: {topItem}");
    
              // Display all items in the stack after peeking
              Console.WriteLine("\nItems in the stack after peeking:");
              foreach (string item in stack)
              {
                  Console.WriteLine(item);
              }
          }
      }
    
  • HashSet: A collection of unique elements.

      using System;
      using System.Collections.Generic;
    
      class Program
      {
          static void Main()
          {
              // Create a new HashSet instance
              HashSet<int> hashSet = new HashSet<int>();
    
              // Adding elements to the HashSet
              hashSet.Add(1);
              hashSet.Add(2);
              hashSet.Add(3);
    
              // Attempting to add duplicate elements
              bool added = hashSet.Add(2); // This will return false as 2 is already in the set
    
              // Checking if elements exist in the HashSet
              Console.WriteLine("Contains 1: " + hashSet.Contains(1)); // Outputs true
              Console.WriteLine("Contains 4: " + hashSet.Contains(4)); // Outputs false
    
              // Removing an element from the HashSet
              hashSet.Remove(2);
    
              // Checking the count of elements in the HashSet
              Console.WriteLine("Number of elements in hashSet: " + hashSet.Count);
    
              // Iterating through the HashSet
              Console.WriteLine("Elements in hashSet:");
              foreach (int item in hashSet)
              {
                  Console.WriteLine(item);
              }
    
              // Converting the HashSet to an array
              int[] array = new int[hashSet.Count];
              hashSet.CopyTo(array);
              Console.WriteLine("Elements in the array:");
              foreach (int item in array)
              {
                  Console.WriteLine(item);
              }
    
              // Clearing the HashSet
              hashSet.Clear();
              Console.WriteLine("Number of elements in hashSet after clearing: " + hashSet.Count);
          }
      }
    

Collections from System.Collections.Concurrent Namespace

  • ConcurrentDictionary<TKey, TValue>: A thread-safe dictionary.

      ConcurrentDictionary<int, string> concurrentDictionary = new ConcurrentDictionary<int, string>();
    
  • ConcurrentQueue: A thread-safe FIFO collection.

      ConcurrentQueue<string> concurrentQueue = new ConcurrentQueue<string>();
    
  • ConcurrentStack: A thread-safe LIFO collection.

      ConcurrentStack<string> concurrentStack = new ConcurrentStack<string>();
    
  • BlockingCollection: A thread-safe collection for adding and taking items.

      BlockingCollection<string> blockingCollection = new BlockingCollection<string>();
    

Specialized Data Structures

  • LinkedList: A doubly linked list.

      LinkedList<int> linkedList = new LinkedList<int>();
    
  • SortedList<TKey, TValue>: A collection of key/value pairs, sorted by key.

      SortedList<int, string> sortedList = new SortedList<int, string>();
    
  • SortedDictionary<TKey, TValue>: A dictionary that maintains the order of elements based on the keys.

      SortedDictionary<int, string> sortedDictionary = new SortedDictionary<int, string>();
    
  • SortedSet: A set that maintains order.

      SortedSet<int> sortedSet = new SortedSet<int>();
    

Immutable Collections

  • ImmutableList: A list that does not change.

      ImmutableList<int> immutableList = ImmutableList.Create<int>();
    
  • ImmutableDictionary<TKey, TValue>: A dictionary that does not change.

      ImmutableDictionary<int, string> immutableDictionary = ImmutableDictionary.Create<int, string>();
    
  • ImmutableQueue: A queue that does not change.

      ImmutableQueue<int> immutableQueue = ImmutableQueue.Create<int>();
    
  • ImmutableStack: A stack that does not change.

      ImmutableStack<int> immutableStack = ImmutableStack.Create<int>();
    
  • ImmutableHashSet: A set that does not change.

      ImmutableHashSet<int> immutableHashSet = ImmutableHashSet.Create<int>();
    

These data structures cover a wide range of use cases, from simple collections to more complex and thread-safe structures, providing a robust foundation for data manipulation in C#.