Вы находитесь на странице: 1из 19

Collections Interfaces

Chapter 7:

Collections Interfaces

Objectives
This chapter discusses about collections in C# and how to work with different
collection classes along with IEnumerable, IEnumerator and IComparable interfaces. At
the end of this chapter delegate would be in a position to accomplish the following
activities.

What is a collection and different interfaces what collections are implementing


How to Work ArrayList, Queue, Stack, HashTable and SortedList Classes
What are IEnumerable and IEnumerator interfaces and how to use them.
Working with IComparable interface

Collections Interfaces
Introduction
The most primitive container within the .NET platform is the System.Array type.
As you have seen over the course of the previous chapters, C# arrays allow you to define
a set of identically typed items (including an array of System.Objects, which essentially
represents an array of any types) of a fixed upper limit. While this will often fit the bill,
there are many other times where you require more flexible data structures, such as a
dynamically growing and shrinking container, or a container that can hold only items that
meet a specific criteria (e.g., only items deriving from a given base class, items
implementing a particular interface, or what not).
To begin understanding the task of building flexible and type-safe containers, this
chapter will first examine the System.Collections namespace that has been part of the
.NET base class libraries since the initial release. The .NET Framework provides
specialized classes for data storage and retrieval. These classes provide support for
stacks, queues, lists, and hash tables. Most collection classes implement the same
interfaces, and these interfaces may be inherited to create new collection classes that fit
more specialized data storage needs.
The Interfaces of the System.Collections Namespace:
The System.Collections namespace defines a number of interfaces. A majority of the
classes within System.Collections implement these interfaces to provide access to their
contents. Below table gives a breakdown of the core collection-centric interfaces.
System.Collections
Interface
ICollection

Meaning

IComparer
IDictionary

Allows two objects to be compared.


Allows a collection object to represent its contents using
name/value pairs.
Returns the IEnumerator interface for a given object.
Enables foreach style iteration of subtypes.
Returns the hash code for the implementing type using a
customized hash algorithm.
Provides behavior to add, remove, and index items in a list
of objects. Also, this interface defines members to determine
whether the implementing collection type is read-only
and/or a fixed-size container.

IEnumerable
IEnumerator
IHashCodeProvider
IList

Defines general characteristics (e.g., size, numeration,


thread safety) for all collection types.

Collections Interfaces
Many of these interfaces are related by an interface hierarchy, while others are
stand-alone entities. Below figure illustrates the relationship between each type.

The Class Types of System.Collections:


System.Collections
Class
ArrayList
HashTable

Queue
Sorted List
Stack

Meaning

Key Interfaces
Implemented
Represents a dynamically sized IList, ICollection, and
array of objects.
IEnumerable.
Represents a collection of
IDictionary, ICollection,
Objects identified by a
and IEnumerable.
Numerical key.
Represents FIFO Queue
ICollection and
IEnumerable.
Like a dictionary. The elements IDictionary,
ICollection,
Can also accessed by position
and IEnumerable.
Represents LIFO Queue
ICollection and
IEnumerable.

Array List

The System.Collections.ArrayList class is similar to arrays, but can store elements


of any data type.

Collections Interfaces

We don't need to specify the size of the collection when using an ArrayList (as
we used to do in the case of simple arrays).

The size of the ArrayList grows dynamically as the number of elements it


contains changes.

An ArrayList uses an array internally and initializes its size with a default value
called Capacity.

As the number of elements increase or decrease, ArrayList adjusts the capacity


of the array accordingly by making a new array and copying the old values into it.

The Size of the ArrayList is the total number of elements that are actually present
in it while the Capacity is the number of elements the ArrayList can hold without
instantiating a new array.

An ArrayList can be constructed like this:


ArrayList demoAL = new ArrayList();

Example 1:
class Program
{
static void Main(string[] args)
{
ArrayList demoAl = new ArrayList();
//Get the number of Elements
Console.WriteLine("No.of elements in the arraylist: {0} ", demoAl.Count);
Console.WriteLine("Adding elements");
demoAl.Add(6);
demoAl.Add("Hi");
demoAl.Add(4.321);
demoAl.Add("Hello");
//Get the number of Elements
Console.WriteLine("No.of elements in the arraylist: {0} ", demoAl.Count);
Console.WriteLine("Removing elements");
// Remove elements from the array list.
demoAl.Remove(6);
// Capacity of the array list
Console.WriteLine("Current capacity: " + demoAl.Capacity);

Collections Interfaces
//Change array contetns using ArrayIndex
Console.WriteLine("Change first three elements");
demoAl[0] = 'X';
demoAl[1] = 'Y';
demoAl[2] = 'Z';
Example2:
class Program
{
static void Main(string[] args)
{
// create an array list
ArrayList al = new ArrayList();
// Add elements to the array list
al.Add(155);
al.Add(413);
al.Add(-41);
al.Add(818);
al.Add(31);
al.Add(191);
Console.Write("Original contents: ");
foreach (object i in al)
Console.Write(i + " ");
Console.WriteLine("\n");
// Sort
al.Sort();
// Use foreach loop to display the list.
Console.Write("Contents after sorting: ");
foreach (object i in al)
Console.Write(i + " ");
// Copy
string[] array1 = new string[10];
al.CopyTo(array1, 0);
Console.WriteLine("Array 1:");

Collections Interfaces
foreach (string s in array1)
{
Console.WriteLine("\t{0}", s);
}
// Reverse
al.Reverse();
foreach (string s in al)
{
Console.WriteLine("\t{0}", s);
}
al.TrimToSize();
Queue:
Queues are containers that ensure items are accessed using a first-in, first-out manner.
Sadly, we humans are subject to queues all day long: lines at the bank, lines at the movie
theater, and lines at the morning coffeehouse. When you are modeling a scenario in
which items are handled on a firstcome, first-served basis, System.Collections.Queue fits
the bill. In addition to the functionality provided by the supported interfaces, Queue
defines the key members which are given below.

Dequeue ():

Removes and returns the object at the beginning of the Queue

Enqueue ():

Adds an object to the end of the Queue

Peek ():
Returns the object at the beginning of the Queue without removing it
Example 1: Enqueue & DeQueue
namespace Queue_Example1
{
class Program
{
static void Main(string[] args)
{
Queue q = new Queue();
q.Enqueue(1);
q.Enqueue(2);
q.Enqueue(3);
q.Enqueue(4);

Collections Interfaces

Console.Write("queue: ");
foreach (int i in q)
Console.Write(i + " ");
Console.WriteLine();
Console.Write("Dequeue -> ");
int a = (int)q.Dequeue();
Console.WriteLine(a);
Console.Write("queue: ");
foreach (int i in q)
Console.Write(i + " ");
Console.WriteLine();
Console.WriteLine("The Peek element is ");
Console.WriteLine(q.Peek());
q.Clear();
}
}
}
Do note that if you attempt to remove items from an empty queue, a runtime exception is
thrown.
The big difference of the queue is that the interface IList is not implemented. You cannot
access the queue using an indexer
Stack:

The System.Collections.Stack class is a kind of collection that provides controlled


access to its elements.

A stack works on the principle of Last In First Out (LIFO), which means that the
last item inserted into the stack will be the first item to be removed from it.

Stacks and Queues are very common data structures in computer science and they
are implemented in both hardware and software.

The insertion of an item onto the stack is termed as a 'Push' while removing an
item from the stack is called a 'Pop'.

Collections Interfaces

If the item is not removed but only read from the top of the stack, then this is
called a 'Peek' operation.

The Stack class can be instantiated in a manner similar to the one we used for the
ArrayList
Stack demoStack = new Stack();

Example1:
class Program
{
static void Main(string[] args)
{
Stack DemoStack = new Stack();
DemoStack.Push(34);
DemoStack.Push("Hi");
DemoStack.Push(23.456);
DemoStack.Push("Hello");
Console.WriteLine("Printing the elements in the stack");
foreach (object o in DemoStack)
{
Console.Write(o + "\t");
}
Console.WriteLine();
Console.WriteLine("The no.of elements in the stack is " + DemoStack.Count);
object a = DemoStack.Pop();
Console.WriteLine("The no.of elements in the stack is " + DemoStack.Count);
Console.WriteLine(DemoStack.Peek());
DemoStack.Clear();
}
}
Dictionary

Dictionaries are a kind of collection that store items in a key-value pair fashion.

Each value in the collection is identified by its key.

All the keys in the collection are unique and there cannot be more than one key
with the same name.

Collections Interfaces

This is similar to the English language dictionary like the Oxford Dictionary
where each word (key) has its corresponding meaning (value).

The two most common types of Dictionaries in the System.Collections namespace


are the Hashtable and the SortedList.

Hash Table:
This session helps us to understand how the hash table collection works. A hash table is a
data structure that associates keys with values. The Base Class Libraries offer a
HashTable class that is defined in the System.Collections namespace so that you are not
required to code your own hash tables. When an element is added to the Hashtable, the
element is placed into a bucket based on the hash code of the key. Subsequent lookups of
the key use the hash code of the key to search in only one particular bucket, thus
substantially reducing the number of key comparisons required to find an element.
Because hashing eliminates the need for costly searching of data to retrieve the data, you
can use hashing to efficiently retrieve data.
In computer science, a hash table or hash map is a data structure that uses a hash
function to efficiently map certain identifiers or keys (e.g., person names) to associated
values (e.g., their telephone numbers).
Constructing a Hashtable
There are constructors available to instantiate a hashtable;
Hashtable ht = new Hashtable();
Example:
class Program
{
static void Main(string[] args)
{
Hashtable ht = new Hashtable();
ht.Add("Name", "Sreekanth");
ht.Add("Salary", 10000);
ht.Add("DeptNo", 5);
Console.WriteLine("No.Of elements in the hash-table is:" + ht.Count);
Console.WriteLine("All the keys in the HashTable are :");
foreach (object o in ht.Keys)

Collections Interfaces
{
Console.WriteLine(o + "\t");
}
Console.WriteLine("Hash Table is fixed ? " + ht.IsFixedSize);
Console.WriteLine("All the values in the HashTable are :");
foreach (object o in ht.Values)
{
Console.WriteLine(o + "\t");
}
ht.Remove("Salary");
Console.WriteLine("All the keys in the HashTable are :");
foreach (object o in ht.Keys)
{
Console.WriteLine(o + "\t");
}
//ht.Add("DeptNo", 25);
Console.WriteLine("\n value=" + ht["DeptNo"]);
if (ht.Contains("Name"))
{
Console.WriteLine("Key Exists");
}
else
{
Console.WriteLine("Key doesnot exists");
}

}
}
SortedList:
The SortedList class represents a collection of key-and-value pairs that are sorted by the
keys and are accessible by key and by index. A SortedList is a hybrid between a
Hashtable and an Array. When an element is accessed by its key using the Item indexer
property, it behaves like a Hashtable. When an element is accessed by its index using
GetByIndex or SetByIndex, it behaves like an Array. If Count already equals Capacity,
the capacity of the SortedList object is increased by automatically reallocating the
internal array, and the existing elements are copied to the new array before the new
element is added.

Collections Interfaces
Example 1:
class Program
{
static void Main(string[] args)
{
SortedList DemoSL = new SortedList();
DemoSL.Add(1, "HI");
DemoSL.Add(2, "Hello");
DemoSL.Add(3, "How");
DemoSL.Add(4, "Are you");
Console.WriteLine("Capacity of the SortedList is {0}",DemoSL.Capacity);
Console.WriteLine(DemoSL.ContainsValue("How"));
Console.WriteLine(DemoSL.GetByIndex(2));
Console.WriteLine("The items in the sorted order:\n");
for (int i = 0; i < DemoSL.Count; i++)
{
Console.WriteLine("\t {0} \t\t{1}", DemoSL.GetKey(i),
DemoSL.GetByIndex(i));
}
DemoSL[2] = "Hello Good morning";
Console.WriteLine(DemoSL.GetByIndex(1));

}
}
Example 2:
class Program
{
static void Main(string[] args)
{
SortedList mySortedList = new SortedList();
mySortedList.Add("NY", "New York");
mySortedList.Add("FL", "Florida");
mySortedList.Add("AL", "Alabama");
mySortedList.Add("WY", "Wyoming");
mySortedList.Add("CA", "California");
foreach (string myKey in mySortedList.Keys)

Collections Interfaces
{
Console.WriteLine("myKey = " + myKey);
}
foreach (string myValue in mySortedList.Values)
{
Console.WriteLine("myValue = " + myValue);
}
Console.WriteLine("Getting the key list");
IList myKeyList = mySortedList.GetKeyList();
foreach (string myKey in myKeyList)
{
Console.WriteLine("myKey = " + myKey);
}
Console.WriteLine("Getting the value list:");
IList myValueList = mySortedList.GetValueList();
foreach (string myValue in myValueList)
{
Console.WriteLine("myValue = " + myValue);
}
}
}
Indexers:
Indexers are location indicators and are used to access class objects, just like accessing
elements in an array. An indexer looks like a property and is written the same way a
property is written, but with two differences:
The indexers takes an index argument and looks like an array.
The indexer is declared using the name this.
The indexer is implemented through get and set accessors for the [] operator.
Public double this [Parameter]
{
get
{
// Get codes goes here
}
set

Collections Interfaces
{
// Set codes goes here
}
}
The implementation rules for the get and set accessors are the same as for properties. The
return type determined what will be returned.
Example:
class ParentClass
{
private string[] range = new string[5];
public string this[int indexrange]
{
get
{
return range[indexrange];
}
set
{
range[indexrange] = value;
}
}
}
/* The Above Class just act as array declaration using this pointer */
class childclass
{
public static void Main()
{
ParentClass obj = new ParentClass();
/* The Above Class ParentClass create one object name is obj */
obj[0] = "ONE";
obj[1] = "TWO";
obj[2] = "THREE";
obj[3] = "FOUR ";
obj[4] = "FIVE";
Console.WriteLine("WELCOME TO C# CORNER HOME PAGE\n");
Console.WriteLine("\n");

Collections Interfaces
Console.WriteLine("{0}\n,{1}\n,{2}\n,{3}\n,{4}\n", obj[0], obj[1], obj[2], obj[3],
obj[4]);
Console.ReadLine();
}
}
Use indexers only when it makes sense, when the representation of the class data as
multiple objects is proper.
As pointed out earlier, indexers and properties are very similar in concept, but differ in
the following ways:

A property can be static member, whereas an indexer is always an instance


member.
A get accessor of a property corresponds to a method with no parameters, whereas
a get accessor of an indexer corresponds to a method with same formal parameter
list as the indexer.
A set accessor of a property corresponds to a method with a single parameter
named value, whereas a get accessor of an indexer corresponds to a method with
same formal parameter list as the indexer, plus the parameter named value.

Enumerable Types:
IEnumerable, IEnumerator interfaces, which facilitates the iterative access in a custom
collection. Unlike C++, .NET Framework facilitates accessing individual elements in the
custom collection while implementing IEnumerable and IEnumerator interfaces. For
example, it is a hassle free job to access types collected in an ArrayList. This had been
eased by ArrayList class while implementing IEnumerable and IEnumerator interfaces.
The IEnumerable interface contains an abstract member function called GetEnumerator()
and return an interface IEnumerator on any success call. This IEnumerator interface will
allow us to iterate through any custom collection.
See the figure. This is how it works.

Collections Interfaces

Members of IEnumerator Interface


Reset(), MoveNext(), Current()
The signature of IEnumerator members is as follows:

void Reset():This method returns a void type and helps you to position the
pointer just before the start point. This reset method will also help you to reset the
iteration pointer anywhere from the start position.

bool MoveNext():This method will help you to position the location of the
required element in the collection while sending a flag value. And its objective is
to inform the caller whether the current position holds any value or not. If it has,
then MoveNext will return true or return false in case there is no value.

object Current: The object Current property of IEnumerator interface will return
an individual element of a given collection. This property is used to return an
element in the collection by using the specified location pointer.

If you are trying to enumerate for the first time, then you need to call methods and
properties in this hierarchy: Reset() - > MoveNext () -> Current.
From second time onwards the hierarchy is : MoveNext () -> Current.
Example:
public class SimpleCollection : IEnumerable
{

Collections Interfaces
public SimpleCollection(object[] array)
{
items = array;
}
public IEnumerator GetEnumerator()
{
return new Enumerator(items);
}
private object[] items = null;
}
public class Enumerator : IEnumerator
{
private int cursor;
private object[] elements = null;
public Enumerator(object[] items)
{
elements = new object[items.Length];
Array.Copy(items, elements, items.Length);
cursor = -1;
}
public bool MoveNext()
{
++cursor;
if (cursor > (elements.Length - 1))
{
return false;
}
return true;
}
public void Reset()
{
cursor = -1;
}
public object Current
{
get
{
return elements[cursor];
}

Collections Interfaces
}
}
public class Starter
{
public static void Main()
{
SimpleCollection simple = new SimpleCollection(new object[] { 1, 2, 3, 4, 5, 6, 7
});
IEnumerator enumerator = simple.GetEnumerator();
while (enumerator.MoveNext())
{
Console.WriteLine(enumerator.Current);
}
}
Comparable Objects:
The System.IComparable interface specifies a behavior that allows an object to be
sorted based on some specified key. Defines a generalized comparison method that a
value type or class implements to create a type-specific comparison method.
To enable your classes to be able to support custom comparisons, your class needs to
implement the IComparable interface. IComparable contains a single method,
CompareTo(),that your class will have to implement. The CompareTo() method compares
the current instance of an object to another object of the same type.
public interface IComparable
The formal definition is:
public interface IComparable
{
int CompareTo(object o);
}
Example:
public class Task : IComparable
{
public int ID, Priority;
public Task(int pID, int pPriority)
{
ID = pID;
Priority = pPriority;

Collections Interfaces
}
public int CompareTo(Object obj)
{
Task SomeTask = (Task)obj;
return this.Priority - SomeTask.Priority;
}
}
class Program
{
static void Main(string[] args)
{
Random Rnd = new Random();
ArrayList Tasks = new ArrayList();
for (int i = 1; i <= 5; i++)
Tasks.Add(new Task(i, Rnd.Next(100)));
Console.WriteLine("Unsorted:\r\nID - Priority");
foreach (Task t in Tasks)
Console.WriteLine(" " + t.ID + " - " + t.Priority);
Console.WriteLine();
// Sort the tasks
Tasks.Sort();
Console.WriteLine("Sorted:\r\nID - Priority");
foreach (Task t in Tasks)
Console.WriteLine(" " + t.ID + " - " + t.Priority);
}
}

Points to Remember
The C# Collection classes are a set of classes designed specifically for
grouping together objects and performing tasks on them.

A majority of the classes within System.Collections implement interfaces to


provide access to their contents.
ArrayList class is similar to arrays, but can store elements of any data type.
The size of the ArrayList grows dynamically as the number of elements it

Collections Interfaces
contains changes.
Queues are containers that ensure items are accessed using a first-in, first-out
manner.
If you attempt to remove items from an empty queue, a runtime exception is
thrown.
Stack works on the principle of Last In First Out (LIFO), which means that the
last item inserted into the stack will be the first item to be removed from it.
A hash table is a data structure that associates keys with values.
When an element is added to the Hashtable, the element is placed into a bucket
based on the hash code of the key.
The SortedList class represents a collection of key-and-value pairs that are sorted
by the keys and are accessible by key and by index.
A SortedList is a hybrid between a Hashtable and an Array.
Indexers are location indicators and are used to access class objects, just like
accessing elements in an array.
IEnumerable, IEnumerator interfaces facilitates the iterative access in a custom
collection.
The System.IComparable interface specifies a behavior that allows an object to
be sorted based on some specified key.

Check YourSelf

Exercise:
Write a Program to implement hast Table objects as elements in Sorted List.
Write the differences between Hash Table and Sorted List.
Illustrate the use of Custom Collections and write a Program to implement it.
Write a Program to convert an ArrayList to Array.
Write a Program to show the differences between SortedList and
SortedDictionary.

Вам также может понравиться