The objective of this article is to understand the generic collections in C# programming language. In the previous article of this tutorial, we saw non-generic types of collections, and in this article, we will be looking at the most widely used generic collections.
Why and when to use generic collections?
As we are aware, C# non-generic collections classes (ArrayList, Hashtable, Stack, and Queue) based on the object type that means the elements added in the collection are of the object type. In non-generic collections, we are were to adding different types (string, int, double) of elements in the collection, which may lead to runtime exception due to type mismatch. But the generic collections are strongly type-safe, which means the elements we are going to add in the collection must be of the same type (this is one advantage).
Another advantage of generic collection is in terms of performance. In the non-generic collection, when we have a big collection, we get poor performance because of boxing and unboxing. Boxing means converting value type data to object type (while storing elements in the collection), whereas unboxing means converting object type data to value type (while retrieving the elements from the collection). But in generic collections, we are explicitly mentioning the type of values that we are going to store into the collection. (for ex: Stack<T>
, here T means type of values).
The generic collections based on System.Collections.Generic namespace and it provides classes like List, Dictionary, Stack, Queue, etc. Let’s take see the practical examples of each one by one.
1. C# List<T>
The List<T>
collection is the generic version of ArrayList. Here, we are mentioning the type of values we are going to store. Like, ArrayList we are unable to add any types of value into the List<T>
collection, which prevents us from an exception occurs at runtime.
Let’s see an implementation of List<T>
collection
Filename: Program.cs
using System;
using System.Collections.Generic;
namespace Studytonight
{
public class Program
{
public static void Main(string[] args)
{
List<int> li = new List<int>();
li.Add(50);
li.Add(40);
li.Add(30);
li.Add(20);
li.Add(10);
Console.Write("List of elements: ");
for(int i=0; i<li.Count; i++)
{
Console.Write(li[i]+" ");
}
}
}
}
List of elements: 50 40 30 20 10
If you closely observe the above example, you will notice the first change as the namespace we used for generic collection, and the second most important change you can see is the type of values we stored are all the same. Next, we used the same add() method to add the elements into List<T> collection. Lastly, with the help of for-loop and Count property, we printed all the elements on a console.
2. C# Dictionary<TKey, TValue>
The Dictionary<TKey, TValue>
collection is the generic version of Hashtable. It works as same as the Hashtable except that it operates on a type object, and this is one of the most useful collections based on key and value pairs.
NOTE: The key must be unique in the dictionary.
Let’s see an implementation of Dictionary<T>
collection
Filename: Program.cs
using System;
using System.Collections.Generic;
namespace Studytonight
{
public class Program
{
public static void Main(string[] args)
{
Dictionary<int, string> dict = new Dictionary<int, string>();
dict.Add(50,"Mangoes");
dict.Add(40,"Oranges");
dict.Add(30,"Bananas");
Console.WriteLine("Dictionary elements: ");
foreach(KeyValuePair<int, string> kv in dict)
{
Console.WriteLine("Key: {0}, Value: {1}",kv.Key,kv.Value);
}
}
}
}
Dictionary elements:
Key: 50, Value: Mangoes
Key: 40, Value: Oranges
Key: 30, Value: Bananas
In this example, firstly, we have created the object of Dictionary class by specifying the type of values int and string. By using the add method, we have added keys and values, and lastly, with the help of for-loop, and Key and Value property, we printed all the pairs on the console.
3. C# Stack<T>
The stack is a linear data structure mainly based on the push and pop operations of the elements. The push operation adds an element in a collection, whereas pop operation used to remove the most recently added element from a collection. It follows the LIFO principle, which means Last In First Out. According to the LIFO principle, the last element pushed in the stack will get popped first.
Let's see an implementation of Stack<T>
generic collection.
Filename: Program.cs
using System;
using System.Collections.Generic;
namespace Studytonight
{
public class Program
{
public static void Main(string[] args)
{
Stack<string> s = new Stack<string>();
s.Push("One");
s.Push("Two");
s.Push("Three");
s.Push("Four");
s.Push("Five");
Console.WriteLine("Stack Elements: ");
foreach(String i in s)
{
Console.WriteLine(i+" ");
}
Console.WriteLine("Peek Element: "+s.Peek());
Console.WriteLine("Element Popped: "+s.Pop());
Console.WriteLine("\nStack Elements: ");
foreach(String i in s)
{
Console.WriteLine(i+" ");
}
}
}
}
Stack Elements:
Five
Four
Three
Two
One
Peek Element: Five
Element Popped: Five
Stack Elements:
Four
Three
Two
One
In this example, Firstly, we have created an object of Stack class by specifying the type as string, and with the help of an object, we have called a push, pop, and peek methods. The push method adds the element, the pop method removes the last pushed element, and the peek method returns the top element of the stack. In our case, "One" is the first pushed element, and "Five" pushed lastly. Hence the last element got popped first i.e "Five".
4. C# Queue<T>
The queue is a linear data structure mainly based on the enqueue and dequeue operations of the elements. Unlike stack, the queue is open at both ends (consider queue like a hollow pipe which has two ends). Similarly, the queue has two ends REAR and FRONT. The first element inserted from one end is called REAR and deleted from the other end called FRONT. The enqueue operation adds an element in a collection, whereas dequeue operation used to remove the firstly added element from a collection. It follows the FIFO principle, which means First In First Out. According to the FIFO principle, the first element inserted in the queue will get removed first.
Let’s see an implementation of Queue<T>
generic collection.
Filename: Program.cs
using System;
using System.Collections.Generic;
namespace Rextester
{
public class Program
{
public static void Main(string[] args)
{
Queue<string> q = new Queue<string>();
q.Enqueue("10");
q.Enqueue("20");
q.Enqueue("30");
q.Enqueue("40");
q.Enqueue("50");
Console.WriteLine("Queue Elements: ");
foreach(String i in q)
{
Console.WriteLine(i+" ");
}
Console.WriteLine("Peek Element: "+q.Peek());
Console.WriteLine("Element Popped: "+q.Dequeue());
Console.WriteLine("\nQueue Elements: ");
foreach(String i in q)
{
Console.WriteLine(i+" ");
}
}
}
}
Queue Elements:
10
20
30
40
50
Peek Element: 10
Element Popped: 10
Queue Elements:
20
30
40
50
In this example, Firstly, we have created an object of Queue class by specifying the type as string, and with the help of an object, we have called enqueue
, dequeue
, and peek
methods. The enqueue method insert the element, the dequeue method removes the first inserted element, and the peek method returns the head element of the queue. In our case, 10 is the first inserted element, and 50 inserted lastly. Hence the first element got removed first i.e 10.
We hope this article with practical examples of generic collections helped you to understand the concept.
You may also like: