0% found this document useful (0 votes)
13 views16 pages

Comparing C# Collection Types

This document provides a comprehensive comparison of various data structures in C#, including List, IEnumerable, IQueryable, ICollection, and IDictionary, highlighting their characteristics, advantages, and use cases. It explains the differences between fixed and dynamic sizes, strong typing, and the performance implications of each structure. Additionally, it covers related structures such as Array, ArrayList, HashTable, Stack, and Queue, along with practical code examples for better understanding.

Uploaded by

Harindra Gupta
Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
13 views16 pages

Comparing C# Collection Types

This document provides a comprehensive comparison of various data structures in C#, including List, IEnumerable, IQueryable, ICollection, and IDictionary, highlighting their characteristics, advantages, and use cases. It explains the differences between fixed and dynamic sizes, strong typing, and the performance implications of each structure. Additionally, it covers related structures such as Array, ArrayList, HashTable, Stack, and Queue, along with practical code examples for better understanding.

Uploaded by

Harindra Gupta
Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd

List vs IEnumerable vs IQueryable vs

ICollection vs IDictionary

Mahsa Hassankashi, 23 Feb 2015 CPOL


4.88 (301 votes)

Rate this: vote 1vote 2vote 3vote 4vote 5


This article is one of the first sources (with complete and clear comparision) about data
structure, Array, ArrayList, List, IList, ICollection, Stack, Queue, HashTable, Dictionary,
IQueryable, IEnumerable.
 IList vs IEnumerable vs IQueryable vs ICollection vs IDictionary - 494.3 KB
 Demo For Data Access Layer

Collection
Collection is set of related records. It includes a meaningful unit:
We should select appropriate container to store data temporarily for fetch and
modification process.
Appropriate container depends on:
1. Our aim which we want to do on data ( just reading, doing modification such as insert,
delete, update )
2. Number of records which should be transferred

Array
1. Fixed Length -> Its size is not flexible. It is determined at instantiation time.
2. Strongly Typed -> Developers determine its type at the instantiation time instead of
runtime. This feature makes to run fast at runtime, since it does not need to wait for type
definition.
3. Developers use "foreach" keyword to fill and iterate through array.
Fixed Length and Strongly Typed consume less memory, therefore it has good
performance.

Hide Copy Code


//It is obvious that strArray is //1. string --> Strongly Type //2.
Sized=10 --> Fixed Size
string[] strArray = new string[10];

for (int i = 0; i < 10; i++)


{
if (strArray[i]==null)
{
strArray[i] = (i+1).ToString();
}
}

[Link] = null;
[Link]();

[Link] = strArray;
[Link]();

ArrayList
1. Arraylist is NOT Fixed Length -> It is possible that data grows. On the one hand it is a
good feature whenever developers are not sure about size of arraylist and on the other
hand it might take long time for size definition.
2. Arraylist is NOT Strongly Typed -> Whenever developers are not sure about what is
exactly type definition for input or output data and they should wait until runtime to
appear its type. Its disadvantage is time consuming at the runtime for memory to
determine type definition.
3. Developers use "foreach" keyword to fill and iterate through arraylist.
Hide Copy Code
public class Product
{
public Product()
{

}
public Product(string Code, string Name)
{
_Code = Code;
_Name = Name;
}

public string _Code {get; set;}


public string _Name { get; set; }
}
ArrayList can accept string, integer and decimal Simultaneously.
Hide Shrink Copy Code
//It is NOT obvious that strArrayList is 1. string? int? object? decimal? --> NOT
Strongly Type // 2. Sized=10? 20? 100?
-->NOT Fixed Size // Namespace: [Link]
[Link] strArrayList = new [Link]();
//[Link] type of data is not specific runtime defered support
[Link]("Mahsa"); // "Mahsa": is string [Link](1); //
1 : is integer [Link](0.89); // 0.89: is decimal
[Link] = null;
[Link]();
[Link] = strArrayList;
[Link]();

[Link] str= new [Link]();

foreach (var item in strArrayList)


{
[Link](" , "+item);
}
[Link] = [Link]();

//Below is old way to fill obj from product , in Arraylist you need to create more than
one instance// Product objProduct = new Product();// [Link] = "1001";//
[Link] = "Chair";
//It is NOT obvious that strArrayList is //1. string? int? object? decimal? OR OBJECT??
--> NOT Strongly Type //2. Sized=10? 20? 100? -->NOT Fixed Size
// Namespace: [Link]
[Link] objArrayList = new [Link]();

[Link](new Product("1001", "Chair"));


[Link](new Product("1002", "Sofa"));
[Link](new Product("1003", "Carpet"));

[Link] = null;
[Link]();
[Link] = objArrayList;

//* Finding among Object of Array List is difficult , you have to find your specific
item by index Product objTemp = (Product)objArrayList[0];
[Link](objTemp);
//* [Link] = "_Name";
[Link] = "_Code";
[Link]();
[Link] = objArrayList;
[Link]();

HashTable
HashTable is another kind of data structure that defines key value for each data section.
Therefore finding data is easy just by point out to its key. It is NOT strongly typed and
NOT fixed size.

Hide Copy Code


//It is NOT obvious that strArrayList is //1. string? int? object? decimal? OR
OBJECT?? --> NOT Strongly Type //2. Sized=10? 20? 100?
-->NOT Fixed Size // Namespace: [Link] //Hashtable solve the
problem in Arraylist when we are looking for specific item //Hashtable dedicate
a key for each item, then finding item is easier and faster
[Link] objHashTable = new
[Link]();

[Link]("1001","Chair");
[Link]("1002", "Sofa");
[Link]("1003", "Carpet");

[Link] = null;
[Link]();
[Link] = objHashTable;
//* finding item is easier you just need to point to it by call its key
[Link]("1002");
//* [Link] = "Value";
[Link] = "Key";
[Link]();

Stack
We have different data structure and stack is one of them. Stack is subset of data
structure. Stack is prioritized data structure (such as List is indexed base). Stack defines
priority for each item, it means stack behavior force its items to put (push) inside stack
prioritized form. So stack put later item on the top of items and this behavior is "defining
priority for each item". Therefore whenever you want to insert item, you should add
(PUSH) it at the top of the stack and whenever you want to remove (POP) item from stack
you should remove it from top of the stack. As you got it, item that comes last one will be
selected to POP for first one and its expression in computer science is equal to "Last in
First out" == "LIFO".
It is NOT strongly typed and NOT fixed size.
Stack - Push
Hide Copy Code
//Stack is LIFO: Last in First Out [Link] objStackPush = new
[Link]();

//By Push method you can insert item at the top of the stack
[Link]("Mahsa");
[Link]("Hassankashi");
[Link] = "";
[Link] = [Link]();
[Link]();

Stack - Pop
Hide Copy Code
[Link] objStackPop = new [Link]();

[Link]("Mahsa");
[Link]("Hassankashi");
//By Pop method you can remove item from the top of the stack --> Last in First
[Link] = [Link]().ToString();
[Link] = [Link]();[Link]();

Queue
Queue is another kind of data structure that defines priority for each item in other form.
Therefore whenever you want to insert item, you should add (Enqueue) it at the head of
the queue and whenever you want to remove (Dequeue) item from queue you should
remove it from bottom of the queue. As you got it, item that comes first one will be
selected to Dequeue for first one and its expression in computer science is equal to "First
in First out" == "FIFO".
It is NOT strongly typed and NOT fixed size.

Queue - Enqueue
Hide Copy Code

//Queue is FIFO: First in First [Link] objQueue = new


[Link]();
//By Enqueue method you can insert item at the END of the [Link]("Mahsa");
[Link]("Hassankashi");
[Link]("Cosmic");
[Link]("Verse");
[Link] = "";[Link] =
[Link]();[Link]();
Queue - Dequeue
Hide Copy Code
[Link] objQueue = new [Link]();

[Link]("Mahsa");
[Link]("Hassankashi");
[Link]("Cosmic");
[Link]("Verse");
//By Dequeue method you can remove item from the BEGINING of the Queue --> First in First
out [Link]=[Link]().ToString();
[Link] = [Link]();[Link]();

List
Why we need List?
1. List is NOT Fixed Length -> It is possible that data grows. On the one hand it is a good
feature whenever developers are not sure about size of arraylist and on the other hand it
might take long time for size definition.
2. List is Strongly Typed when it is defined "Generic" -> Whenever developers are sure
about what is exactly type definition for input or output data and they do not wait until
runtime to appear its type. This feature makes to run fast at runtime, since it does not
need to wait for type definition.
3. Developers use "foreach" keyword to fill and iterate through array.
Since List is not Fixed Length makes developers feel flexible to use it, and because of it
is Strongly Typed when it is defined "Generic" so our code runs fast at runtime because it
does not need to wait for type definition.

Hide Copy Code


//Like Array is Strong Type//Like ArrayList with No
[Link]<string> strList = new List<string>();

[Link]("Mahsa");
[Link]("Hassankashi");
[Link]("Cosmic");
[Link]("Verse");
[Link] = strList;[Link]();

[Link] str = new [Link]();


foreach (var item in strList)
{
[Link](" , " + item);
}[Link] = [Link]();

IList
Why we need IList? IList is implemented by List, Ilist is an interface and implements
methods. Whenever you estimate probability that your code would be changed in future
you have to use IList because interface reduces dependency and with the little
modification your code runs. Therefore you should observe polymorphism in order to
decouple your app and control on adding or removing method that might be changed.
Everything else is similar. Whenever we want to change on some operation, so “IList”
allow us to do that easily with at least changing in the whole of codes.
Interfaces can not be instantiate, so it should be instantiate from List
Hide Copy Code

[Link]<string> strIList = new List<string>();

Difference between Concrete Class and Interface


1. Concrete Class inherits from just ONE class but it Can implements one or MORE than
one interfaces

2. You can write inside concrete class full version of your function while you have to
define just signature inside the interface.

3. You can define variable and value Inside Concrete Class while you are not allowed to
define variable inside interfaces.

4. An Concrete class can have constructor while you are not allowed to define
constructor inside interfaces.

5. Abstract class can containe access modifier while intefaces does not.
As I mentioned that how a class cannot be driven from two class it just can be driven
from only one class, so whenever you want to drive from two class it is not possible to
inherit from two abstract class but it is possible to drive from more than one class by
interfaces.
Later in future if developers decide to add some features on their class and inherit it from
another class, developers always prefer to use interface of collection so that if you want to
change your code and enhance its abilities, choose interfaces.
On the other hand interface keeps your program extensible and Decouple: The classes
are independent from each other, so error, exception and failure will happen rarely in
future changing code by interfaces.

Polymorphism: When you are using interface you absolutely observe and do
polymorphism and oop. It means encapsulate your designer. Interface means a point or a
node to join two part to each other it means making low dependency from two part and
make a joint section to make flexible change in future.
Hide Copy Code
//Ilist can not be instantiate from Ilist , so it should be instantiate from
[Link]<string> strIList = new List<string>();

[Link]("Mahsa");
[Link]("Hassankashi");
[Link]("Cosmic");
[Link]("Verse");

[Link] = strIList;[Link]();

[Link] str = new [Link]();


foreach (var item in strIList)
{
[Link](" , " + item);
}[Link] = [Link]();

IEnumerable
IEnumerable is suitable just for iterate through collection and you can not modify (Add or
Remove) data IEnumerable bring ALL data from server to client then filter them, assume
that you have a lot of records so IEnumerable puts overhead on your memory.

Hide Copy Code


//IEnumerable can not be instantiate from Enumerable , so it should be instantiate from
List [Link]<Employee> empIEnumerable = new
List<Employee>
{ new Employee { ID = 1001, Name="Mahsa"},
new Employee { ID = 1002, Name = "Hassankashi" },
new Employee { ID = 1003, Name = "CosmicVerse" },
new Employee { ID = 1004, Name = "Technical" }
};

[Link] = empIEnumerable;
[Link]();
[Link] str = new [Link]();

foreach (Employee item in empIEnumerable)


{
[Link](" , " + [Link] +"-"+[Link]);
}

[Link] = [Link]();

IQueryable
Whenever we encounter to huge data with so many records so we have to reduce
overhead from application. IQueryable prepares high performance in such situations
(huge data) by filtering data firstly and then sending filtered data to client.

Follow "Entity Framework DatabaseFirst" from this article for making DBContext
Hide Copy Code

DataAccessEntities ctx = new DataAccessEntities();


var ctx = new DataAccessEntities();
Data Access

Hide Shrink Copy Code


//Difference between IQueryable and IEnumerable
//You can instantiate IEnumerable from List
IEnumerable<employee> queryIEnumerable = new List<employee>() ;

//Bring ALL records from server --> to client then filter collection
//To bring all data from server you should omit where cluse from linq to sql
queryIEnumerable = from m in [Link] select m;

//If you use where as extension method with IEnumerable then All records will
be loaded queryIEnumerable = [Link](x => [Link] == 1).ToList();
//You can not instantiate IQueryable
IQueryable<employee> queryIQueryable=null;

//Bring just ONE record from server --> to client


queryIQueryable = (from m in [Link]
where [Link] == 1
select m);

//Whenever you call IQueryable so ==> It will be executed


[Link] = [Link]();
[Link]();</employee>

SQL Profiler:
How to trace your query generates TSQL & How many records will
be loaded:
Step 1:
Start -> MS SQL Server 2008 -> Performance Tools -> SQL Server Profiler

Step 2:
SQL Server Profiler -> File -> New Trace
Step 3:
Connect with you user name and password.

Step 4:
General (Tab) -> Use the Template: Standard
Step 5:
Event Selection (Tab) -> Event : TSQL -> Select : SQL-BatchCompleted | Select Show all
Columns
Press Column Filter -> Database Name: Like: "DataAccess"
Press Run

Step 6:
Go To MS SQL Server Management Studio -> Count all of records (records=5)
Step 7:
IEnumerable generates:
Hide Copy Code
SELECT
[Extent1].[ID] AS [ID],
[Extent1].[Name] AS [Name],
[Extent1].[Age] AS [Age]FROM [dbo].[Employee] AS [Extent1]

IQueryable generates:
Hide Copy Code
SELECT
[Extent1].[ID] AS [ID],
[Extent1].[Name] AS [Name],
[Extent1].[Age] AS [Age]FROM [dbo].[Employee] AS [Extent1]WHERE 1 = [Extent1].[ID]

ICollection
ICollection inherits from IEnumerable. There is one difference:
you can find IEnumerable[ i ] --> Index Based
you can NOT find ICollection[ i ] --> Not Index Based

Hide Shrink Copy Code


//IList {indexer and Modify} vs ICollection {randomly and Modify} //Collection can
not be instantiate from ICollection , so it should be instantiate from List
[Link]<string> strICollection = new List<string>();
[Link]("Mahsa");
[Link]("Hassankashi");
//Countable*** int ICollectionCount=[Link];

[Link] = strICollection;
[Link]();
[Link] str = new [Link]();
foreach (var item in strICollection)
{
[Link](" , " + item);
}
[Link] = [Link]();

//IList*** [Link]<Employee> objIList = new


List<Employee>();
objIList = (from m in [Link]
select m).ToList();

Employee obj = [Link](i => [Link] == "Sara").FirstOrDefault();int indexofSara=


[Link](obj);int cIList = [Link];

//ICollection*** [Link]<Employee> objICollection =


new List<Employee>();
objICollection = (from m in [Link]
select m).ToList();
Employee objIC = [Link](i => [Link] == "Sara").FirstOrDefault();
//You can not get index of object , if you clear comment from below code appears error//
int indexofSaraICollection = [Link](objIC); int cICollection =
[Link];

Stack Generic
Push:
Hide Copy Code

//Stack is LIFO: Last in First Out


//Here is for Push Stack in Generic
//[Link] objStackPush = new [Link]();
//Stack<T> can be instantiated from Stack<T>

[Link] <int> objStackPush = new


[Link]<int>();

[Link](1);
[Link](2);

[Link] = "";
[Link] = [Link]();
[Link]();

Pop:
Hide Copy Code
//Stack is LIFO: Last in First Out
//Here is for Pop Stack in Generic
//[Link] objStackPop = new [Link]();
//Stack<T> can be instantiated from Stack<T>

[Link] <int> objStackPop = new


[Link]<int>();

[Link](1);
[Link](2);
[Link] = [Link]().ToString();
[Link] = [Link]();
[Link]();

Queue Generic
Enqueue:
Hide Copy Code

//Queue is FIFO: First in First Out


//Here is for Enqueue Queue in Generic
//[Link] objQueue = new [Link]();
//Queue<T> can be instantiated from Queue<T>

[Link] <int> objQueue = new


[Link]<int>();
[Link](1);
[Link](2);

[Link] = "";

[Link] = [Link]();
[Link]();

Dequeue:
Hide Copy Code

//Queue is FIFO: First in First Out


//Here is for Dequeue Queue in Generic
//[Link] objQueue = new [Link]();
//Queue<T> can be instantiated from Queue<T>

[Link]<int> objQueue = new


[Link]<int>();

[Link](1);
[Link](2);

[Link] = [Link]().ToString();

[Link] = [Link]();
[Link]();

Dictionary and IDictionary


Dictionary is GENERIC while HashTable is not generic : Dictionary<TKey, TValue>, There is
a tiny difference between them that if dictionary can not find specific key will throw an
exception while HashTable just returns null.
IDictionary is interface and if you estimate big changes in future use IDictionary instead of
Dictionary.
Hide Copy Code
//Dictionary can instantiate from Dictionary , Dictionary is similar to
Hashtable,//Dictionary is GENERIC but Hashtable is NON GENERIC//Such Hashtable you can
find object by its [Link]<int, string="">
objDictionary = new Dictionary<int, string="">();

[Link](1001, "Mahsa");
[Link](1002, "Hassankashi");
[Link](1003, "Cosmicverse");
string str = objDictionary[1002];
[Link] =
objDictionary;[Link]();</int,>

Common questions

Powered by AI

The 'Last in First out' (LIFO) concept means that the most recently added item is the first to be removed, which impacts usage by making stacks suitable for tasks like function call management, undo mechanisms in applications, and parsing expressions. This behavior is inherent to stack operations where items are pushed and popped from the top .

The primary differences between `Dictionary` and `Hashtable` include type safety and exception handling. `Dictionary` is generic and strongly typed, meaning the types of keys and values are specified, while `Hashtable` is non-generic and not strongly typed. Additionally, if a `Dictionary` cannot find a specific key, it throws an exception, whereas `Hashtable` returns null .

Using `IList` can be advantageous over direct implementations like `List` or `ArrayList` in scenarios where future code changes are anticipated because it reduces dependency and allows for easier alteration. Interfaces like `IList` provide flexibility for implementing changes with minimal modification due to polymorphism and decoupling, making them ideal in evolving system architectures .

`Queue` follows a 'First in First out' (FIFO) principle where the first added item is the first to be removed, suitable for scenarios like order processing systems and scheduling tasks. In contrast, `Stack` operates on a 'Last in First out' (LIFO) principle, making it ideal for uses like reversing data orders or managing function calls in execution stacks. Each is applicable based on the order of processing required by the application .

`IQueryable` offers advantages in processing large datasets because it defers the execution of a query until it is iterated, allowing the application to filter data at the database level. This means only filtered data is retrieved from the server, reducing memory overhead. In contrast, `IEnumerable` brings all data from the server to the client before filtering, which can result in significant memory overhead .

Encapsulation and polymorphism in OOP allow classes to hide implementation details and enable different behaviors through a common interface, respectively. Using interfaces like `ICollection` and `IList` supports these principles by allowing different implementations to be accessed through the same interface, promoting flexibility and code extensibility. This abstraction reduces dependency between components and supports future modification without altering the overarching application logic .

A `HashTable` might be more beneficial in situations where the type of data is unknown at compile-time or when dealing with legacy systems that enforce non-generic collection usage. Its ability to handle objects without predefined type constraints can offer practical benefits in such contexts, despite the potential for runtime errors and lack of type safety compared to a `Dictionary` .

Type safety plays a significant role in selecting between `ArrayList` and `List<T>`. `List<T>` is strongly typed, meaning its type is defined at compile-time, which provides safety against runtime type errors and improves performance due to reduced need for type checking during execution. In contrast, `ArrayList` is not strongly typed and can store any data type, which can lead to runtime errors and performance overhead due to type checking and casting .

Fixed-size arrays offer performance advantages in terms of speed and memory efficiency because their size is determined at instantiation and they are strongly typed. However, they lack flexibility since their size cannot change. Dynamic structures like `List` and `ArrayList` provide flexibility as they can expand as needed, but this can lead to higher memory usage and performance overhead due to the need for resizing and type checks, particularly in `ArrayList` .

`ICollection` differs from `IEnumerable` in that it allows for data modification (adding/removing elements) and provides information like the count of elements, while `IEnumerable` only supports data iteration and does not allow modification. This makes `ICollection` more versatile for scenarios requiring dynamic data manipulation, whereas `IEnumerable` is preferred for simple data enumeration and iteration tasks .

You might also like