Collections in C# are used to store and retrieve data. You can take advantage of collections to dynamically allocate memory to store data, and then retrieve it using a key or index as and when required. It is important to understand that collections represent a collection of items that may be accessed by iterating over each of the members of the collection.
This article talks about how you can work with non-generic collections in C#. The next part in this series of articles on collections will talk about generic and concurrent collections in C#.
What are Generic and Non-Generic Collections in C#?
Collections in .NET are of two types: generic collections and non-generic collections. Generic collections are those that include just one type of item. Because there are no boxing and un-boxing overheads for saving and retrieving components into and from generic collections, generic collections offer type safety as well as much improved performance than other types of collections.
Read: .NET Framework: Collections and Generics
The System.Collections Namespace in C#
The System.Collections namespace comprises several classes, interfaces, methods and properties to work with different types of data structures. The System.Collections namespace includes the following interfaces:
- ICollection
- IList
- IEnumerable
- IEnumerator
- IDictionary
- The classes that extend the ICollection interface are:
- System.Collections.Stack
- System.Collections.Queue
- System.Collections.BitArray
- System.Collections.Specialized.NameValueCollection
The IDictionary interface is a type that represents generic collections using name/value pairs. The IDictionary interface includes the following classes:
- System.Collections.SortedList
- System.Collections.Hashtable
- System.Collections.Specialized.HybridDictionary
- System.Collections.Specialized.ListDictionary
The IList interface in the System.Collections namespace represents collections that have only one value. The classes that extend this interface include the following:
- System.Array
- System.Collections.ArrayList
- System.Collections.Specialized.StringCollection
Working with the Collection classes in C#
In this section, we will examine some of the collection classes in C# with relevant code examples wherever appropriate.
The C# ArrayList Class
An array consists of a collection of homogeneous elements. On the contrary, the ArrayList class can store dynamic arrays of heterogeneous objects; for example, you can use an ArrayList to store objects of dissimilar types. These objects are stored as object types only. An ArrayList object can store objects of primitive as well as user-defined types. However, all such objects are stored as object types.
The ArrayList class implements the IList interface and represents an index-based collection whose size may be increased dynamically, and which can hold items of any kind. An ArrayList uses its indices to identify a specific object in its collection.
The Count property of the ArrayList class can be used to retrieve a count of the total number of items in an ArrayList object. The Capacity property sets or gets the maximum number of items the ArrayList object may contain. You can take advantage of the Add() method to add objects to an ArrayList. To remove an object from the ArrayList you can use the Remove() method.
The following code snippet illustrates how you can work with an ArrayList in C#:
int i = 10; double d = 100.5; string str = “Joydip Kanjilal”; ArrayList arrayList = new ArrayList(); arrayList.Add(str); arrayList.Add(i); arrayList.Add(d); for (int x = 0; x < arrayList.Count; x++) Console.WriteLine(arrayList[x]);
Read: Using Collections in .NET
The Stack Class in C#
The Stack class represents a collection of items of the System.Object type. These items are organized in a LIFO manner. LIFO is an acronym for Last-in-first-out; items are inserted and removed from the top.
The following code snippet shows how you can work with a Stack in C#:
Stack stack = new Stack(); stack.Push("Joydip Kanjilal"); stack.Push("Steve Smith"); stack.Push("Michael Stevens"); while (stack.Count > 0) Console.WriteLine(stack.Pop());
The Queue Class
The Queue class represents a data structure that stores items in a FIFO manner. FIFO is an acronym for First-in-first-out; items are added at the rear of the queue. This process is called enqueue. Items are removed from the front of the queue. This process can also be called dequeuing. If you want a synchronized and thread-safe queue, you should utilize the ConcurrentQueue class.
The following code snippet shows how you can work with a Queue in C#:
Queue queue = new Queue(); queue.Enqueue("Joydip Kanjilal"); queue.Enqueue("Steve Smith"); queue.Enqueue("Michael Stevens"); while (queue.Count > 0) Console.WriteLine(queue.Dequeue());
C# Hashtable Class
The Hashtable class represents a collection that may hold data as key/value pairs. It is a faster way of storing and retrieving objects of the same object type. Hashtable provides support for key-based searches. The keys in a Hashtable are unique. The Hashtable class has a method called GetHashCode() that returns the object instance’s hashcode.
The following code snippet illustrates how you can work with a Hashtable in C#:
Hashtable hashTable = new Hashtable(); hashTable.Add(1, "A"); hashTable.Add(2, "B"); hashTable.Add(3, "C"); hashTable.Add(4, "D"); Console.WriteLine("Please enter the key to search"); int p = int.Parse(Console.ReadLine()); Console.WriteLine(hashTable[p].ToString());
StringCollection
The StringCollection is a part of the System.Collections.Specialized namespace and represents a collection of strings. The following code snippet illustrates how you can work with a StringCollection in C#:
StringCollection stringCollection = new StringCollection(); stringCollection.Add("Joydip Kanjilal"); stringCollection.Add("Steve Smith"); stringCollection.Add("Michael Stevens"); foreach(string str in stringCollection) { Console.WriteLine(str); }
StringDictionary
Like StringCollection, there is another collection class known as StringDictionary. A StringDictionary is a dictionary of strings. The following code snippet illustrates how you can work with a StringDictionary class in C#:
StringDictionary stringDictionary = new StringDictionary(); stringDictionary.Add("A", "Joydip Kanjilal"); stringDictionary.Add("B", "Steve Smith"); stringDictionary.Add("C", "Michael Stevens"); foreach(string str in stringDictionary.Values) { Console.WriteLine(str); }
SortedList Class in C#
The SortedList class represents a collection of items that are stored as key/value pairs, sorted by keys, and accessed by their keys and indexes. The following code snippet shows how you can work with a SortedList in C#:
SortedList sortedList = new SortedList(); sortedList.Add(1, "A"); sortedList.Add(3, "B"); sortedList.Add(2, "C"); sortedList.Add(4, "D"); foreach(string str in sortedList.Values) { Console.WriteLine(str); }
Read: C++ Classes and Objects Overview
The System.Collection.Concurrent Namespace in C#
The System.Collections.Concurrent namespace comprises types that provide support for thread safety. Thread Synchronization is used to prevent concurrent access by multiple threads to a shared resource and limit access to a shared resource. Some of the most significant thread-safe collection classes in the System.Collections.Concurrent namespace are: BlockingCollection, ConcurrentQueue, ConcurrentStack, and ConcurrentDictionary<TKey, TValue>.
We will learn more on concurrent collections in the next part in this series.
What are Type Safe Collections in C#?
When dealing with an in-memory collection of data, you may use generics to guarantee type safety while also improving performance since there is no boxing and unboxing cost to contend with. When you use generics, the compiler performs compile-time tests on your code to comply with type safety requirements. It is important to note that type-safe collections, also known as strong collections, include data pertaining to a predefined or known type.
Type safe collections include items that belong to a known type. You can implement a strong typed collection using any one of these classes.
- CollectionBase
- ReadOnlyCollectionBase
- DictionaryBase
The advantages of type-safe collections include:
- Supports indexing items in the collection
- Supports enumeration
- Supports dynamic resizing of the collection
- Supports serialization
Summary of Collections in C#
Collections provide an elegant way to work with a group of objects. Contrary to arrays, the group of objects you deal with may expand and decrease dynamically based on your application’s requirements. Some collections, such as the Hashtable, allow you to assign a key for any object you place in the collection. This allows you to quickly retrieve the object using the key.
Read: Constructors in C#