Preparing For .NET Interviews: Traditional And Generic Collections - Part Eight

I am here to continue the series related to .NET interview preparation. Today we will discuss the common questions related to traditional and generic collections and present the answers in an easy way.

You can learn from my previous parts:

So let’s takethe questions one by one.

Question 1: What are the main benefits of using collection over array? Do we still have some advantages in using array?

Answer

The main benefit of using collection is that we need not to define the fix size when declaring them. Collections automatically increase their size as the element grows.

Yes, we still have some advantages in using array especially when we can predict the size and type. The reason is that flexible size benefit in collections comes with the cost of performance due to dynamic pointer overhead.

Question 2: Explain the collections available with System.Collections namespace with example? What are the disadvantages they have?

Answer

Collections in namespace System.Collections are the traditional collections introduced first to address the need of having dynamic number of additions which array doesn’t support.

These collections are loosely typed and hence doesn’t enforce compile-time type checking.

Also they are of object type by default and clearly it’s to accommodate all other types.

For example,

  • ArrayList (obj) - Can be defined as flexible size object array.
  • Hashtable (key, val) - Key-value pair object type collection for faster lookup.
  • Stack (obj) - Last in First out (LIFO) object type collection.
  • Queue (obj) - First in First out (FIFO) object type collection.
    1. static void Main()  
    2. {  
    3.     Console.Title = "Traditional Collections demo";  
    4.     ArrayList al = newArrayList();  
    5.     al.Add("Prakash");  
    6.     al.Add("1000");  
    7.     al.Add("true");  
    8.     Console.WriteLine("Using ArrayList");  
    9.     foreach(objectobjin al)  
    10.     {  
    11.         Console.WriteLine(obj);  
    12.     }  
    13.     Stackstk = newStack();  
    14.     stk.Push("101");  
    15.     stk.Push("Aradhana");  
    16.     stk.Push("Tripathi");  
    17.     Console.WriteLine("\nUsing Stack");  
    18.     foreach(objectobjinstk)  
    19.     {  
    20.         Console.WriteLine(obj);  
    21.     }  
    22.     Queue que = newQueue();  
    23.     que.Enqueue("101");  
    24.     que.Enqueue("Aradhana");  
    25.     que.Enqueue("Tripathi");  
    26.     Console.WriteLine("\nUsing Queue");  
    27.     foreach(objectobjin que)  
    28.     {  
    29.         Console.WriteLine(obj);  
    30.     }  
    31.     Hashtableht = newHashtable();  
    32.     ht.Add(1000, "102");  
    33.     ht.Add(1001, "Prakash");  
    34.     ht.Add(1002, "Tripathi");  
    35.     Console.WriteLine("\nUsingHashtable");  
    36.     foreach(DictionaryEntrykvpinht)  
    37.     {  
    38.         Console.WriteLine("Key: {0}, value: {1}", kvp.Key, kvp.Value);  
    39.     }  
    40. }  
    Output



    As you can see in the traditional collections illustrated above that it uses object type to facilitate all other types and due to that it has few dis-advantages as following.

  • When using value types with traditional collection, boxing/unboxing happens behind the scene and that lead to performance degradation.

  • Since traditional collections are not strongly typed, using them may cause run-time errors for incompatible casting.

Question 3: What are the generic collections and how do they address the issues in traditional collections? Explain with example.

Answer

Generic collections (Namespace: System.Collections.Generic) are the collections that separate business logic with data types and hence provide code reusability among other benefits.

Generic collections enforce type safety at compile time itself and address the possible runtime type casting errors. These collections are strongly typed and that solves boxing/unboxing issues which was with traditional collections and in turn provide better performance.

Also since compiler is aware of the type (primitive or complex) of the object, type casting is no longer required that leads to clean code.

For example,

  • List<int> - Can be defined as strong primitive type array list.
  • List<IEmployee> - Can be defined as strong complex type array list.
  • Dictionary <int, Employee> - Strong typed key-value pair collection for faster lookup.
  • Stack <string> - Strong typed Last in First out (LIFO) collection.
  • Queue <double> - Strong typed First in First out (FIFO) collection.
    1. Console.Title = "Generic Collections demo";  

    2. List < int > list = newList < int > ();  
    3. //list.Add("Prakash"); //Error, cannot convert from string to int.  
    4. list.Add(1000);  
    5. list.Add(1002);  
    6. list.Add(1003);  
    7. Console.WriteLine("Using Generic List (Generic version of ArrayList)");  
    8. foreach(intiin list)  
    9. {  
    10.     Console.WriteLine(i);  
    11. }  
    12. Stack < string > stk = newStack < string > ();  
    13. stk.Push("Aradhana");  
    14. stk.Push("Prakash");  
    15. stk.Push("Tripathi");  
    16. Console.WriteLine("\nUsing Generic Stack");  
    17. foreach(stringstrinstk)  
    18. {  
    19.     Console.WriteLine(str);  
    20. }  
    21. Queue < double > que = newQueue < double > ();  
    22. que.Enqueue(1042.5);  
    23. que.Enqueue(1243.5);  
    24. que.Enqueue(3245.54);  
    25. Console.WriteLine("\nUsing Generic Queue");  
    26. foreach(objectobjin que)  
    27. {  
    28.     Console.WriteLine(obj);  
    29. }  
    30. Dictionary < intstring > dict = newDictionary < intstring > ();  
    31. dict.Add(100, "Prakash");  
    32. dict.Add(101, "Tripathi");  
    33. dict.Add(102, "Beeda");  
    34. Console.WriteLine("\nUsing Dictionary (Generic version of Hashtable)");  
    35. foreach(varkvpindict)  
    36. {  
    37.     Console.WriteLine("Key: {0}, value: {1}", kvp.Key, kvp.Value);  
    38. }  
    Output

Question 4: What is Hashset and when to use it?

Answer

Hashset is a unique unordered collection. This is optimized to store the unique elements even though we enter duplicate elements. Hashset internally performs union of the elements added in order to provide unique collection.

Hashset members can't be accessed by index and hence it's more suitable in cases when we just want to check existence of any item in set. 
  1. Console.Title = "HashSet demo";  
  2. List < string > nameList = new List < string > ()  
  3. {  
  4.     "Prakash",  
  5.     "Tripathi",  
  6.     "Prakash",  
  7.     "Satna",  
  8.     "Beeda",  
  9.     "Satna"  
  10. };  
  11. Console.WriteLine("Using List. Members count: {0}", nameList.Count);  
  12. foreach(string str in nameList)  
  13. {  
  14.     Console.WriteLine(str);  
  15. }  
  16. HashSet < string > nameHS = new HashSet < string > (nameList);  
  17. Console.WriteLine("\nUsing HashSet. Members count: {0}", nameHS.Count);  
  18. foreach(string str in nameHS)  
  19. {  
  20.     Console.WriteLine(str);  
  21. }   
Output
 

 
As you can see that list has six elements including two duplicates whereas when we pass the same list to the HashSet, it excludes the duplicates and shows only the unique elements.
 
You can also download the attached demo project (CollectionsDemo.zip) to go through the sourse code used in the article.
 
Hope you have liked the article. Look forward for your comments/suggestions.