6.interfaces and Collections
6.interfaces and Collections
Collections
Chapter - 6
Objectives
Interface – basic concepts
C# How to implement Interfaces in C#?
C# Difference between Interfaces and
C# Abstract base Classes
C# Interface References: 'is', 'as', etc.
Interfaces as Parameters
Interfaces and Polymorphism
Building Customized Types
IConvertible, IEnumerator, ICloneable, and
IComparable, Interfaces
System.Collections Interface
ArrayList, Hashtable, Queue, SortedList, and Stack
S. Nandagopalan, BIT 2
Part - I
Interface – basic concepts
C#
C# How to implement Interfaces in C#?
C# Difference between Interfaces and
C# Abstract base Classes
Interface References: 'is', 'as', etc.
Interfaces as Parameters
Interfaces and Polymorphism
S. Nandagopalan, BIT 3
Interface – Basic Concepts
Definition: An interface is nothing more than a
C# named collection of semantically related abstract
C# members
C# Interface is to achieve polymorphism in another way
C# Interfaces can have static members, nested types,
and abstract, virtual members, properties, and events
COM programmers lived only with interfaces, as the
client can communicate only through interface
pointers with COM classes (not through object
references)
Interfaces do not specify a base class, or access
modifier, etc, but provide polymorphism
Interfaces do not implement any methods
S. Nandagopalan, BIT 4
Advantages of Interfaces
So, what are interfaces good for if they don't
C# implement functionality?
C# They're great for putting together plug-n-play like
C# architectures where components can be
C# interchanged at will (example follows…).
Since all interchangeable components implement the
same interface, they can be used without any extra
programming.
The interface forces each component to expose
specific public members that will be used in a certain
way.
You can achieve multiple inheritance.
You can use interface with structures.
S. Nandagopalan, BIT 5
Real World Example
C#
USB
C#
C# Interface1 Interface3
C# Interface2
S. Nandagopalan, BIT 6
Simple Example
using System; public static void Main()
C# interface ISample {
C# { Sample s = new Sample();
void notify(); s.notify();
C#
double cubic(double e); ISample i = (Isample) s;
C# } i.notify();
class Sample : ISample }
{
public void notify()
{ }
public double cubic(double x)
{ return x * x * x; }
}
S. Nandagopalan, BIT 7
Polymorphism
Collection of contracts
C#
C# Steering is a contract between driver (user)
C# and car (object)
C# A car may have many contracts (tasks) –
brake, steering, horn, etc.
Interfaces are useful in developing UI
components.
Example: Buttons, Textboxes, Menus, etc.
S. Nandagopalan, BIT 8
Example
using System; class Car : IVehicle
C# interface IVehicle {
{ public void steering()
C#
void steering(); { }
C# public void brake( x)
double brake(double e);
C# } { }
}
class Bus : IVehicle
Class Test
{
{
public void steering()
public static void Main()
{ }
{
public void brake( x) Ivehicle b = new Bus();
{ } b.steering(); b.brake();
} Ivehicle c = new Car();
c.steering(); c.brake();
}
S. Nandagopalan, B 9
}IT
Multiple Inheritance
interface IPrinter
{ class Program
{
C#
void LaserJet();
void DeskJet(); static void Main(string[] args)
C# }
interface IPenDrive
{
C# {
USB u = new USB();
IPrinter printer = (IPrinter)u;
void Access();
C# } u.LaserJet();
class USB : IPrinter, IPenDrive u.DeskJet();
{ u.Access();
public void LaserJet() }
{
}
Console.WriteLine("IPrinte::Laserjet");
}
public void DeskJet()
{
Console.WriteLine("IPrinte::Deskjet");
}
public void Access()
{
Console.WriteLine("IPenDrive::Access");
}
S. Nandagopalan, BIT 10
}
Implementing an Interface
A class that implements an interface can explicitly implement
C# a member of that interface
Interfaces may be implemented by classes and structures
C#
When a member is explicitly implemented, it can not be
C# accessed through a class instance, but only through an
C# instance of the interface
public interface IA
{
// Members…..
}
public class Foo1: IA
{
// implementation details of the interface
}
public class Foo2 : Foo1, IA
{
// derives from BaseClass and implements the interface
}
S. Nandagopalan, BIT 11
Shapes Hierarchy
C# Shape Class
Draw( )
C#
C#
C#
Hexagon
Circle
Class
Triangle Class
Class
S. Nandagopalan, BIT 12
Example-1 : Shapes Hierarchy
interface IPoints
{
C# byte GetNumberOfPoints( );
C# }
public abstract class Shape
C# {
C# protected string petName;
// Constructors.
public Shape( )
{ petName = "NoName";}
public Shape(string s)
{ this.petName = s; }
// All child objects must define for themselves what
// it means to be drawn.
public abstract void Draw();
public string PetName
{
get {return this.petName;}
set {this.petName = value;}
}
S. Nandagopalan, BIT 13
}
Circle SubClass
The Circle subclass does not implement the
C#
interface IPoints!
C#
C# public class Circle : Shape
C# {
public Circle() { }
// Call base class constructor.
public Circle(string name): base(name) { }
public override void Draw()
{
Console.WriteLine("Drawing " + PetName + " Circle");
}
}
S. Nandagopalan, BIT 14
Hexagon SubClass
public class Hexagon : Shape, IPoints
{
C#
public Hexagon( )
C# { }
C# public Hexagon(string name): base(name)
C# { }
// Implements IPoints
byte IPoints.GetNumberOfPoints()
{ return 6; }
}
S. Nandagopalan, BIT 15
Example-1…
public static int Main(string[] args)
{
C# Circle c = new Circle("Red");
C# c.Draw();
Hexagon h = new Hexagon("Blue");
C# h.Draw();
C# //IPoints MyShape = (IPoints) h;
//Console.WriteLine(MyShape.GetNumberOfPoints());
Console.WriteLine(h.GetNumberOfPoints()); // Error
}
Example - 2
Interfaces can contain named properties
C#
C# Person Example:
C#
C# interface IAge
{
int Age { get; } // note: no implementation
string Name { get; }
}
S. Nandagopalan, BIT 17
Example – 2…
class Person : IAge
C# {
private string firstName;
C#
private string lastname = "......";
C# private int yearBorn;
C# public int Age
{
get
{
return DateTime.Now.Year - yearBorn;
}
set
{
yearBorn = value;
}
}
S. Nandagopalan, BIT 18
Example – 2…
static void Main(string[] args)
C# {
C# Person p = new Person();
C# p.Name = "Geetha";
C# p.Age = 1986;
Console.WriteLine("Name = {0}",
p.Name);
Console.WriteLine("Age = {0}", p.Age);
S. Nandagopalan, BIT 21
Example-3…
public static void Main()
{
C# // Declare a class instance "myBox":
C# Box myBox = new Box(30.0f, 20.0f);
C# // Declare an interface instance "myDimensions":
C# IDimensions myDimensions = (IDimensions) myBox;
// Print out the dimensions of the box:
/* The following commented lines would produce
compilation errors because they try to access an explicitly
implemented interface member from a class instance: */
//Console.WriteLine("Length: {0}", myBox.Length());
//Console.WriteLine("Width: {0}", myBox.Width());
/* Print out the dimensions of the box by calling the
methods from an instance of the interface: */
Console.WriteLine("Length: {0}", myDimensions.Length());
Console.WriteLine("Width: {0}", myDimensions.Width());
}
} S. Nandagopalan, BIT 22
Interfaces Vs. Abstract Classes
Similarities
C#
C# Direct instantiation is not possible
C# Declare variables of these types and then use
C# these members of these types thro' these
variables
S. Nandagopalan, BIT 23
Interfaces Vs. Abstract Classes
Why do we need "interface"? Because C# allows
C# abstract methods in base classes
C# Abstract base classes permit more than the abstract
C# methods – private, public, protected member data
and methods which could be accessed in derived
C# classes
In Interfaces, you can't define other than abstract
methods and implementations for them
interface IPoints
{
byte GetNumberOfPoints()
{ } // ERROR
}
Interfaced programming provides another way of
polymorphism
S. Nandagopalan, BIT 24
Interfaces Vs. Abstract Classes
Only a single abstract class may be inherited from the base
C# class.
C# Classes may use as many interfaces as they wish (we can also
C# do this in abstract!)
C# In interfaces, all methods must be implemented that inherit
Interface members are by default public, but in abstract classes
it need not be.
Interfaces can't contain: constructors, destructors, static
members, const, etc.
Purpose of Abstract classes: intended for use as base class for
family of objects
Interfaces: intended for use by classes that might differ far more
fundamental level
S. Nandagopalan, BIT 25
Advantages of Interfaces
Using interface based design concept provides
C# loose coupling
C# component-based programming
C# easier maintainability
code base more scalable
C#
code reuse much more accessible
Because implementation is separated from the interface.
Interfaces add a plug and play like architecture into your
applications.
It defines a contract (agreement or blueprint, however you
chose to define it), between your application and other objects.
This indicates what sort of methods, properties and events are
exposed by an object.
S. Nandagopalan, BIT 26
Example
All vehicles have similar items,
namespace InterfaceExample
but are different enough that we
C# { could design an interface that
holds all the common items of a
C# public interface IVehicle
vehicle.
C# {
Some vehicles have 2 wheels,
C# int Doors { get; set; }
some have 4 wheels and can
int Wheels { get; set; } even have 1 wheel.
Color VehicleColor { get; set; }
Common - they're all movable,
int TopSpeed { get; set; } they all have some sort of
int Cylinders { get; set; } engine, they all have doors, but
int CurrentSpeed { get; } each of these items may vary.
S. Nandagopalan, BIT 28
Example…
{ get { return _currentSpeed; } }
public Motorcycle(int doors, int wheels, Color color, int topSpeed, int
C# horsePower, int cylinders, int currentSpeed)
C# {
C# this.Doors = doors;
this.Wheels = wheels;
C# this.VehicleColor = color;
this.TopSpeed = topSpeed;
this.HorsePower = horsePower;
this.Cylinders = cylinders;
this._currentSpeed = currentSpeed;
}
public string DisplayTopSpeed()
{ return "Top speed is: " + this.TopSpeed; }
public void Accelerate(int step)
{ this._currentSpeed += step; }
}
S. Nandagopalan, BIT 29
Design Pattern
"Program to an interface, not an implementation.“
C# Use more formal definition by declaring a basic design pattern called an
Interface Pattern
C#
Result of three different ways of reading a file.
C#
The client classes of the code sample are: BlueGUI, RedGUI and
C# YellowGUI. The provided services are: XMLInput (reading an XML file),
INIInput (reading an INI/text file) and BinInput (reading a binary file).
The three client classes and the three services providing classes
communicate indirectly through an interface called IInput.
S. Nandagopalan, BIT 30
Code
public interface IInput
C# {
NotifyOutput();
C# }
C#
C#
S. Nandagopalan, BIT 31
Code…
C#
C#
C#
C#
S. Nandagopalan, BIT 32
Advantages
It is easy to extend the application with new
C# functionalities.
C# If the customer wants a new functionality, say a
C#
new service provider reading from another
C#
source which is not currently present, the
problem is solved by writing a new reader class
implementing IInput.
This is a good way of extending the system since
the developer does not have to change any
existing code.
S. Nandagopalan, BIT 33
Example
C#
C#
C#
C#
IPassengerCarrier
IHeavyLoadCarrier
S. Nandagopalan, BIT 34
Interface Reference through is & as
Using "as" keyword, you can reference the interface
C# members
C# Hexagon h2 = new Hexagon();
C# IPoints ipts2;
C# ipts2 = h2 as IPoints;
Console.WriteLine(ipts2.GetNumberOfPoints());
ipts2 may be set to null if a given interface is not
supported by the object
You can also use "is" keyword
Hexagon h2 = new Hexagon();
if (h2 is IPoints)
Console.WriteLine(ipts2.GetNumberOfPoints());
else ERROR
S. Nandagopalan, BIT 35
Exercising the Shapes Hierarchy
Shape[ ] s = {new Hexagon(), new Circle(),
C# new Triangle("Joe"), new Circle("JoJo")};
C# for (int i = 0; i < s.Length; i++)
C# {
C#
s[i].Draw();
// Who's points?
if (s[i] is IPoints)
Console.WriteLine("-> Points: {0}",
((IPoints)s[i]).GetNumberOfPoints());
else
Console.WriteLine("-> {0}\'s not points!", s[i].PetName);
}
S. Nandagopalan, BIT 36
Interfaces as Parameters
Methods can take interfaces as parameters
C# Assume the following interface:
C# interface IDraw3D
C# {
C# void Draw3D();
}
Now assume that the Circle subclass is revised to provide an
additional implementation for IDraw3D
public class Circle : Shape, IDraw3D
{
// ……….
public void Draw3D()
{ Console.WriteLine("Drawing a 3D Circle");
}
S. Nandagopalan, BIT 37
Interface as Parameter…
The following method declares the interface as a
C# parameter
C# public static void DrawIn3D(IDraw3D int3D)
C# {
C# Console.WriteLine("Drawing in 3D:");
int3D.Draw3D();
}
public static void Main()
{ ….
if (s[i] is IDraw3D) DrawIn3D((IDraw3D)s[i]);
…..
}
S. Nandagopalan, BIT 38
Explicit Implementation Issues
Can we write like the one that follows? The answer is yes
C# interface IDraw3D
{
C#
void Draw();
C#
}
C# Won't it clash with the overriding method as shown below:
public class Line : Shape, IDraw3D
{
public override void Draw()
{ Console.WriteLine("Drawing an ordinary line"); }
public void IDraw3D.Draw()
ERROR { Console.WriteLine("Drawing a 3D line"); }
} // given interface method is bound at interface level.
// Hence, public doesn't make any sense
S. Nandagopalan, BIT 39
Part - II
C#
IConvertible
C# IEnumerator and IEnumerable
C#
C# ICloneable
IComparable and IComparer
S. Nandagopalan, BIT 40
IConvertible Interface
Allows dynamic conversion of data types through
C# interface based programming technique
C# What are the methods defined in IConvertible
C#
Interface?
C#
public interface IConvertible
{
bool ToBoolean(IFormatProvider provider);
char ToChar(IFormatProvider provider);
……
UInt64 ToUInt64(IFormatProvider provider);
}
S. Nandagopalan, BIT 41
Accessing Members
To gain access to each member of IConvertible
C# interface, you must explicitly request access to the
C# interface
C# // uses explicit interface implementation
C#
bool myBoll = true;
IConvertible i = (IConvertible) myBool;
Now i is convertible to any valid type
IConvertible.ToXXXX() Methods
These methods provide a way to convert from one type
into another (is it always?!!!)
From char to DateTime possible? No
If attempted, InvalidCastException will be raised
S. Nandagopalan, BIT 42
Type Conversions
Integer
using System.Globalization;
C# int theInt = 65;
C# Console.WriteLine("Type code of int is: ",theInt.GetTypeCode());
C# Int to Char using Type Casting
C# char theChar = (char)theInt;
Console.WriteLine("Type code int converted to char is: {0}",
theChar.GetTypeCode());
Console.WriteLine("Value of converted char: {0}", theChar);
Int to Byte using IConvertible
IConvertible itfConvert = (IConvertible)theInt;
byte theByte = itfConvert.ToByte(CultureInfo.CurrentCulture);
Console.WriteLine("Type code int converted to byte is: {0}",
theByte.GetTypeCode());
Console.WriteLine("ValueS.of converted int: {0}", theByte);
Nandagopalan, BIT 43
Type Conversion…
Convert a System.String into a System.Boolean
C# using System.Convert
C# string theString = "true";
C#
bool theBool = Convert.ToBoolean(theString);
C#
Console.WriteLine("Type code string converted to
bool is: {0}",
theBool.GetTypeCode());
Console.WriteLine("Value of converted string: {0}", theBool);
S. Nandagopalan, BIT 50
Implementation of MoveNext()….
public
publicbool
boolMoveNext()
MoveNext() public
publicvoid
voidReset()
Reset()
C# {{ {{
C# if(pos
if(pos<<carArray.Length)
carArray.Length) pos
pos==0;0;
C# {{ }}
C# pos++;
pos++; public
publicobject
objectCurrent
Current
return
returntrue;
true; {{
}}
else get
get
else
return {{
returnfalse;
false;
}} return
returncarArray[pos];
carArray[pos];
}}
}}
S. Nandagopalan, BIT 51
Advantages
User types can be iterated through 'foreach'
C#
loop
C#
C# When the IEnumerator members are explicitly
C# implemented, we provide an alternate method
of accessing the objects in the container
……. Add some more points ………
S. Nandagopalan, BIT 52
Reducing the Code Size
Since the System.Array type already implements
C# IEnumerator, you need not add this interface to
C# Cars class
C# public class Cars : IEnumerable //, IEnumerator
C# {
private car[ ] carArray;
……..
public IEnumerator GetEnumerator()
{
return carArray.GetEnumerator( );
}
……..
}
With this, there is no need to implement manually
MoveNext(), Reset(), S.etc. (refer ObjEnum folder)
Nandagopalan, BIT 53
Building Cloneable Objects
Implementing ICloneable interface using a
C#
Point Class
C#
C# Recall System.Object has a member
C# MemberwiseClone() which does shallow copy
Object users can call this method with an
instance for cloning process
Let us make things clear……
S. Nandagopalan, BIT 54
Example
public class Point
C# {
public int x, y;
C#
public Point(){}
C# public Point(int x, int y)
C# { this.x = x; this.y = y; }
public override string ToString()
{ return "X: " + x + " Y: " + y; }
}
The following piece of code makes two references
pointing to the same copy of the objects in heap
Point p1 = new Point(50, 50);
Point p2 = p1;
p2.x = 0;
Notice that by modifying p2, the object p1 also gets
modified.
S. Nandagopalan, BIT 55
ICloneable Interface
To avoid the shallow copy problem we must
C# implement the ICloneable interface
C# public interface ICloneable
{
C# object Clone();
C# }
This means the Clone() method need to be redefined
to suit the customer type. This ensures deep copy
semantics
public class Point : ICloneable
{
…..
public object Clone()
{ return new Point(this.x, this.y); }
….
}
S. Nandagopalan, BIT 56
Calling Clone() Method
Point p1 = new Point(50, 50);
// p2 will point to the copy of p1
C#
Point p2 = (Point)p1.Clone();
C#
p2.x = 0; // will not affect p1
C# Console.WriteLine(p1);
C# Console.WriteLine(p2);
The above WriteLine commands will print two
different objects
If a type does not contain references to other internal
reference types, then we can write
public object Clone()
{ return this.MemberwiseClone(); }
What happens if the Point type contains references to
other internal reference types?
S. Nandagopalan, BIT 57
Building Comparable Objects
Let us show how to implement IComparable interface
C# Defines a generalized comparison method that a value type or
class implements to create a type-specific comparison method
C#
CompareTo(object o) - Compares the current instance with
C# another object of the same type
C# public interface IComparable
{
int CompareTo(object o);
}
Recall, the System.Array class defines a method Sort() which
sorts int, float, char, etc. However, if the array contains a set of
Cars, it fails.
Array.Sort(intArr); // OK
Array.Sort(myCars); // ArgumentException will be thrown
So the advantage of IComparable is to provide a way to sort
your own types S. Nandagopalan, BIT 58
Example – Student Class
public class Student : IComparable
{
C# private int USN;
C# public Student() {USN = 0; }
C# public Student(int USN) { this.USN = USN; }
public int RegNo
C# { CompareTo() return Value:
get
{ return USN; } < 0 : less than object
} 0 : equal to object
int IComparable.CompareTo(object o)> 0 : greater than object
{
Student temp = (Student) o;
if(this.USN > temp.USN) return 1;
if(this.USN < temp.USN) return -1;
else return 0;
}
}
S. Nandagopalan, BIT 59
Sorting the Objects
static void Main(string[] args)
{
C# Student[] cseStd = new Student[3];
C# cseStd[0] = new Student(111);
C# cseStd[1] = new Student(100);
cseStd[2] = new Student(45);
C# try
{
Array.Sort(cseStd);
}
catch(Exception e)
{
Console.WriteLine(e.StackTrace);
}
Console.WriteLine("Array after sorting");
foreach(Student s in cseStd)
Console.WriteLine(s.RegNo);
}
S. Nandagopalan, BIT 60
Sorting Order (IComparer)
Suppose if you wish to sort the student objects based
C# on USN and also Name – how do we solve this
C# problem?
C# This could be solved by using another interface
C# called IComparer
public interface IComparer
{
int Compare(object o1, object o2)
}
Recall, the IComparable interface was implemented
using the type name (Student). But, IComparer is
implemented using some helper classes, one for
each sort order (USN, Name, etc).
S. Nandagopalan, BIT 61
Modified Student Class
using System.Collections;
public class Student
C# {
C# public int USN;
public string Name;
C# public Student() {USN = 0; Name = null;}
C# public Student(int USN, string Name)
{
this.USN = USN;
this.Name = Name;
}
public class SortName : IComparer // helper class
{
public SortName() { }
int Compare(object o1, object o2)
{
Student s1 = (Student) o1;
Student s2 = (Student) o2;
return String.Compare(s1.Name, s2.Name);
}
} S. Nandagopalan, BIT 62
Using Multiple Sort Order
System.Sort has a number of overloaded methods. One of them is to take
an object implementing IComparer
C# static void Main(string[] args)
{
C# Student[] cseStd = new Student[3];
C# cseStd[0] = new Student(111,"Scott");
cseStd[1] = new Student(100,"Allen");
C# cseStd[2] = new Student(45,"John");
try
{
Array.Sort(cseStd, new SortName());
}
catch(Exception e)
{
Console.WriteLine(e.StackTrace);
}
Console.WriteLine("Array after Sorting by Name:");
foreach(Student s in cseStd)
Console.WriteLine(s.USN + " " + s.Name);
}
} S. Nandagopalan, BIT 63
Static Helper Class
The helper classes may be static
C#
C# public static IComparer class SortName
C#
C#
{ …. }
// Calling program
Array.Sort(cseStd, Student.SortName());
S. Nandagopalan, BIT 64
System.Collections Namespace
Sytem.Collections has many classes
C#
C# ArrayList Dynamic array of IList, ICollection,
objects IEnumerable, & ICloneable
C#
C# Hashtable collection of objects IDictionary, ICollection,
identified by keys IEnumerable, & ICloneable
Queue FIFO ICollection, IEnumerable, &
ICloneable
SortedList Same as IDictionary, ICollection,
Dictionary, but IEnumerable, & ICloneable
accessed by index
Stack LIFO ICollection and IEnumerable
S. Nandagopalan, BIT 65
System.ArrayList
AddRange() populates the array with Cars
C# // Create ArrayList and fill with some initial values.
C# Console.WriteLine("***** Fun with ArrayList *****");
ArrayList carArList = new ArrayList();
C# carArList.AddRange(new Car[ ] { new Car("Fred", 90, 10),
C# new Car("Mary", 100, 50), new Car("MB", 190, 0)});
Console.WriteLine("Items in carArList: {0}", carArList.Count);
S. Nandagopalan, BIT 66
System.ArrayList….
Index() is used to plug a new Car at any
C# position/index
C# // Insert a new item.
C# Console.WriteLine("-> Inserting new item");
carArList.Insert(2, new Car("TheNewCar", 0, 0));
C#
Console.WriteLine("Items in carArList: {0}", carArList.Count);
S. Nandagopalan, BIT 67
System.Collections.Queue
Dequeue() – Delete and return first object from the Queue
C# Enqueue() – Insert an object into the Queue
C# Peek() – Return the first object without deleting
C# Console.WriteLine("\n***** Queue Demo *****");
C# // Now make a Q with three items
Queue carWashQ = new Queue();
carWashQ.Enqueue(new Car("FirstCar", 0, 0));
carWashQ.Enqueue(new Car("SecondCar", 0, 0));
carWashQ.Enqueue(new Car("ThirdCar", 0, 0));
S. Nandagopalan, BIT 68
System.Collections.Queue
// Remove each item from Q
C# WashCar((Car)carWashQ.Dequeue());
C# WashCar((Car)carWashQ.Dequeue());
C#
WashCar((Car)carWashQ.Dequeue());
C#
// Try to de-Q again?
try
{
WashCar((Car)carWashQ.Dequeue());
}
catch(Exception e)
{ Console.WriteLine("Error!! {0}", e.Message);}
S. Nandagopalan, BIT 69
System.Collections.Stack
Stack stringStack = new Stack();
stringStack.Push("One");
C# stringStack.Push("Two");
C# stringStack.Push("Three");
// Now look at the top item.
C#
Console.WriteLine("Top item is: {0}", stringStack.Peek());
C# Console.WriteLine("Popped off {0}", stringStack.Pop());
Console.WriteLine("Top item is: {0}", stringStack.Peek());
Console.WriteLine("Popped off {0}", stringStack.Pop());
Console.WriteLine("Top item is: {0}", stringStack.Peek());
Console.WriteLine("Popped off {0}", stringStack.Pop());
try
{
Console.WriteLine("Top item is: {0}", stringStack.Peek());
Console.WriteLine("Popped off {0}", stringStack.Pop());
}
catch(Exception e)
{ Console.WriteLine("Error!! {0}\n", e.Message);}
S. Nandagopalan, BIT 70