Collections in C#

Learn via video courses
Topics Covered

Overview

In today's world, data is quite important and so is organizing and managing it. Programmers use collections as a key tool to effectively organize and handle groups of related data. Collections are a crucial component of the .NET framework in the C# programming language, offering a variety of data structures to meet various demands. We'll look at the many collections available in C#, their features, and real-world uses further in this article.

Introduction to Collections in C#

A collection is basically an object that stores and manages a group of elements. These groups of elements can be of any data type, such as integers, strings, custom objects, or even other collections. These collections help us to perform various operations on objects such as a store, delete, update, search, and sort objects.

Collections are broadly classified into Generic collections and Non-Generic collections. Generic collections work on a specified type of elements that is defined into the program whereas the Non-Generic collections work on the object type, that is, an element can contain a value of different types.

The C# language offers several collection classes, each designed for specific purposes and optimized for different types of operations. These collection classes are grouped into three categories which are as follows:

  1. System.Collections.Generic Classes
  2. System.Collections Classes
  3. System.Collections.Concurrent

System.Collections.Generic Classes

The Generic classes in C# are present in the System.Collections.Generic namespace. It offers a general implementation of well-known data structures like dictionaries, queues, stacks, and linked lists.

These collections are type-safe because they are generic, which means that only objects that are type-compatible with the collection's type may be kept there. This prevents unintentional type mismatches.

Now, let us see the various classes and interfaces defined under the System.Collections.Generic collection.

Class nameUsage
ListIt is a class that implements the IList interface and provides all the functionalities similar to an Arraylist. It is considered a generic version of the Arraylist in which we can dynamically increase the size of the array.
SortedList<TKey,TValue>It implements the IComparer interface and provides a sorted list of key-value pairs. It provides functionalities similar to the non-generic sorted list class.
StackIt is a last-in first-out (LIFO) data structure that provides functionalities similar to that of the non-generic Stack class.
QueueIt is a first-in-first-out (FIFO) data structure that provides functionalities similar to that of the non-generic Queue class.
Dictionary<TKey,TValue>It stores a collection of key-value pairs and has all the functionalities similar to a non-generic hashtable data structure.
HashSetIt is a high performance class which stores an unordered collection of unique elements. It does not allow duplicate elements to be stored in it.
LinkedListIt has all the functionalities similar to a non-generic linked list. It allows fast insertion and deletion of elements.

Now, let us see a code example to better understand these generic classes in detail.

Output:

As you can see in the above code example, a generic stack class has been implemented. Some elements have been inserted into it and then printed using a foreach loop. Moreover, we have also used the Peek() function at the end to find the element which is present at the top of the array.

Similarly, other generic classes can also be implemented with their functionalities.

System.Collections Classes

The non-generic collections in C# are present in the System.Collections namespace. These types of collections or classes can handle any type of object but not in a type-safe manner. To ensure the type-safety, we need to use the generic collections already discussed in the previous section.

However, the System.Collections classes have basic data structure implementations like Stack, Queue, ArrayList, etc. Now, let us see the collection of interfaces and classes that define these non-generic collections.

Class nameUsage
ArrayListAn Arraylist is a modified version of an array in which we can increase or decrease the size dynamically at runtime.
StackIt is a LIFO data structure that follows the concept of Last-in First-out. It has just one end to insert and remove the elements.
QueueIt follows the First-in-First-out concept of insertion and deletion of elements. It has two ends, one from which the elements are inserted into the array and the second is the one from which the elements are removed.
HashtableIt stores the elements in the form of key-value pairs that are inserted on the hashcode of the key.

Now, let us see a code example to better understand the classes discussed above.

Output:

As you can see in the above code example, we have implemented the class ArrayList and inserted some elements into it. After which, we have used some functions on it like counting the number of elements present in the arraylist using the Count() method and finding if a particular element is present in the arraylist or not using the Contains()method.

Similarly, we you can implement other non-generic classes along with their functionalities.

System.Collections.Concurrent

This collection of classes is available from the .NET framework version 4. It offers a number of thread-safe collection classes that are used in place of the System.Collections and System.Collections.Generic namespaces when multiple threads are accessing the collection simultaneously.

Class nameUsage
BlockingCollectionIt implements the IProducerConsumerCollection interface and provides thread safety that is, multiple threads can insert and remove elements concurrently.
ConcurrentStackIt is a thread-safe collection class that follows the last-in first-out (LIFO) order of insertion and deletion.
ConcurrentQueueIt is a thread-safe collection class that follows the first-in first-out (FIFO) order of insertion and deletion.
ConcurrentDictionaryIt stores a collection of key-value pairs and allows multiple threads to perform insertion and deletion concurrently. It works similarly to the generic collection of the Dictionary class.
ConcurrentBagIt is a thread-safe collection that allows duplicate elements to be stored in an unordered manner.
PartitionerIt represents a specific approach to dividing a data source into different segments with partitioning strategies for arrays, lists, and enumerable.
OrderablePartitionerIt represents a specific approach to partitioning an orderable data source into several parts.

Now, let us see a code example to better understand the implementation of the classes discussed above.

Output:

In the code example, we have simply implemented the ConcurrentQueue class, inserted some elementes into it and have printed them.

Benefits of Collections in C#

There are several benefits that we get for collections in C# which are as follows:

  • Type-safety: - Strongly typed collections, such DictionaryTKey, TValue>, and ListT>, ensure type safety by allowing you to only store items of a particular data type in the collection.
  • Dynamic Size: - Many C# collections, such as lists and dictionaries, can dynamically resize themselves when entries are added or removed, unlike arrays that have a fixed size.
  • Grouping and Organizing Data: Collections allow you to group related data elements together, which makes it easier to manage and process them as a single unit. This is useful when dealing with large datasets or complex data structures.

Conclusion

  • Collections in C# are used to store and manage a group of elements.
  • These collections provide dynamic sizing, allowing them to grow or shrink as elements are added or removed, making them flexible and convenient.
  • Strongly typed collections provide type safety, which lowers the possibility of runtime errors and increases the robustness of the code.
  • Concurrent Collections ensure thread safety so that multiple threads can insert and remove elements concurrently.