Sei sulla pagina 1di 394

Documents downloaded from www.funducode.

com

Article: .C# - The whole new way of programming...

If you are a C++ or a Java programmer you would find lot of things similar when you take a first
look at C# code. However, apart from the initial similarity you will find C# a lot easier than C++
and Java. It offers simplicity of Visual Basic, power of C++ and platform independence of Java, all
bundled into one language. The highlighting features of C# are as follows:

a. Full support for object-oriented programming


b. In-built support for automatic generation of XML documentation.
c. Automatic cleanup of dynamically created memory.
d. Access to .Net class library as well as Windows API.
e. Can be used to create a ASP.Net dynamic web pages.

Most of these features are available on VB.Net as well as VC++.Net. However, since C# is
designed from the start to work with .Net, it uses .Net features with ease and efficiency that would
be found wanting in VB.Net and VC++.Net.

C# has been developed by a team led by Anders Hejlsberg who was also the leader of the J++
team. Hence you will find the design and syntax of C# much similar to Java. However, as of now
Java has one strong advantage over C#-platform independence. The same Java code can be
executed on any platform that has a Java Runtime (JVM) implementation. Since JVM's are
already in existence for most major platforms Java is truly portable today. Same is not true about
C#-at least not as of now. In contrast, C# has two advantages over Java. These are as under:

a. C# supports operator overloading. If required C# programs can use pointers by enclosing


them within 'unsafe' blocks.
b. C# can interoperate with code written in other .Net languages.

Without much ado lets get on with C# programming. Here we go…

The First C# Program

All that you need to program in C# is Microsoft VisualStudio.Net Beta 2, .Net SDK Beta 2. (These
you can either download from msdn.microsoft.com or you can get it along with your MSDN
subscription.) You need to install it on a machine running under Windows 98, Windows 2000 or
Windows XP.

namespace Simple
{
using System ;

class Class1
{
static void Main ( string[ ] args )
{
Console.WriteLine ( "Hello C#" ) ;
}
}
}

Before we understand how the program works, let us first see the steps involved in creating it.

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

a. Start Microsoft Visual Studio.NET 7.0 from Start | Program | Microsoft Visual
Studio.NET 7.0 menu option.
b. Create a new C# project from File | New | Project menu option. A New Project dialog as
shown in the following figure would appear.

c. From the New Project dialog box select project type as Visual C# Projects.
d. Select Console Application from the list of Templates.
e. Select a location (directory/folder) where this project should get saved. Give name to the
project as Simple. Click on OK button.
f. A Class1.cs file would get created. This file would contain skeleton program. The
VisualStudio.Net environment automatically creates this program. It contains a class
called Class1 containing the function Main( ) .
g. Add the following line to the skeleton code.

Console.WriteLine ( "Hello C#" ) ;

h. To compile and execute the program use Ctrl + F5. On execution the message "Hello C#"
would be displayed on the screen.

Now a few useful tips about the program…

a. C# is a pure object oriented language. It doesn't allow global variables or functions. All
variables and functions should be defined inside a class.
b. All C# programs start from Main( ). Since Main( ) cannot be global it is enclosed in a
class called Class1. void before the word Main specifies that Main( ) does not return
anything. The static modifier used with Main( ) indicates that it can be called without
creating an object of the class Class1.
c. string is a data type used to store strings. string[ ] represents an array of strings. Thus
args is an array of strings. It stores the command line parameters, if specified by the user
while executing the program.
d. To display anything on the screen we need to call the WriteLine( ) function. To this
function we can pass strings, integers, floats, etc. Since the WriteLine( ) function belongs
to the Console class we have to call it using Console.WriteLine( ). A function within the
class can be accessed using the '.' Operator. Console class is used to perform input from
keyboard and output to screen.
e. In C#, namespaces provide a way to group classes. Console class belongs to the
System namespace. Hence to be able to use the Console class we need to import it
from the System namespace. This has been done through the using System statement.
The way the Console class has been enclosed within the System namespace, likewise

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

our class Class1 has been enclosed in the Simple namespace. The namespace concept
is similar to packages in Java.
f. C# is a case-sensitive language. The naming convention used by .NET is that class
names would start with a capital letter. If a single class name contains multiple words,
each word's starting letter would be capital. The same applies to function names also. All
keywords are in small case.

Let us now write another program that would show how to receive input from the keyboard. Here
it is…

namespace Simple
{
using System ;

class Class1
{
static void Main ( string[ ] args )
{
string s ;
s = Console.ReadLine( ) ;
Console.WriteLine ( s ) ;
}
}
}

To receive input from the keyboard we have used the ReadLine( ) function. This function returns
a string. This function is also a static member function of the Console class, hence we have
called it using Console.ReadLine( ).

Note that C# does not have its own class library. It uses the class library provided by the .Net
Framework. The .Net Framework provides the class library in the form of .Net Base Classes.
Thus Console is a .Net base class. This class can be used by any other .Net-aware language.

Command-line Arguments

Instead of receiving input from keyboard we may want to supply input to it in the form of
command-line arguments. Following program shows how to receive these arguments and print
them out.

using System;

namespace cmdline
{
class Class1
{
static void Main ( string[ ] args )
{
foreach ( string str in args )
{
Console.WriteLine ( str ) ;
}
}
}
}

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

To supply command-line arguments we have to open the properties window of the project from
the "Solution Explorer". A window will pop up. This window consists of properties that appear on
the left pane of the window. We have to select "Configuration Properties" from it. As soon as we
select this it expands into a tree with more underlying properties. Now we have to select the
"Debugging" property. On doing this all fields related to the "Debugging" property appear on the
right pane of the window. We then need to fill in the command-line arguments in the "Command
Line Arguments" option. Press OK to finalize the option. In this program we have set command-
line arguments as Nagpur Mumbai Bangalore. On executing the program it would output these
arguments.

We can run this program from the Run dialog box that appears when we select 'Start | Run'
option. To do so we must specify the command line arguments after the name of the EXE file.

FileHandling

.Net offers two classes for file operations-the File class and the FileInfo class. Both these
classes are defined in System.IO namespace. The File class is derived from the Object class. It
contains static methods and never gets instantiated. The FileInfo class is derived from
FileSystemInfo class, which represents the file system. We can instantiate this class. The
hierarchy of these classes is shown in the following figure:

Let us now understand the objective of creating two classes for file operations.

The static functions of the File class can be called to perform various file operations without
creating an object. This avoids the overhead of instantiating objects. As against this, to call the
member functions of the FileInfo class it is necessary to create an object. This is because
FileInfo class contains non-static member functions. So if we wish to carry out a single operation
on the file we can use the File class, avoiding the object creation overheads thereby. On the other
hand if we wish to carry out multiple operations on the file (with the preservation of state of the
object) we can use the FileInfo class. When we create a FileInfo object all the relevant
information like size, attributes, authentication permissions are read in through the constructor.
This information is then shared by other functions while carrying out multiple operations. If we use
the File class for carrying our multiple operations then this information will have to be read in
each time we perform a new operation.

Also, at times we are required to pass the file information to another application. In such a case it
is necessary to create a FileInfo object and then pass its state to other application (this process
is known as marshalling). Marshalling of object is possible only if the class in derived from the
MarshalByRefObject class. Since the object of the File class cannot be created it has not been
inherited from MarshalByRefObject class.

Reading And Writing To A Text File

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

In the following program we will perform reading and writing operations on a text file. We plan to
write a few strings to a text file and read the strings back from it.

namespace fileoperation
{
using System ;
using System.IO ;

class Class1
{
static void Main ( string[ ] args)
{
string str1 = "The .NET Revolution" ;
string str2 = "Long live C# " ;
string str3 = "Targeting the internet" ;

StreamWriter sw =
new StreamWriter ( "C:\\file2.txt", false ) ;
sw.WriteLine ( str1 ) ;
sw.WriteLine ( str2 ) ;
sw.WriteLine ( str3 ) ;
sw.Close( ) ;

StreamReader sr =
new StreamReader ( @"C:\file2.txt" ) ;
// @ ensures that we don't have to use C:\\

string str ;
do
{
str = sr.ReadLine( ) ;
Console.WriteLine( str ) ;
} while ( str != null ) ;
sr.Close( ) ;
}
}
}

To understand this program we must first know what a Stream is. A stream is a sequence of
bytes traveling from source to destination or traveling over a communication link. Two basic types
of streams exist: Input stream and Output stream. An input stream is used for read operations
while an output stream is used for write operations. The System.IO namespace contains
functions to perform input and output operations.

Here we have created a new StreamWriter object and have passed 'false' to the constructor of
the StreamWriter class along with the path. Here 'false' specifies that if the file exists, it should
be overwritten. If we pass a true and if the file exists, it should be appended. In either case if the
file does not exist, a new file is created. The WriteLine( ) member function of the StreamWriter
class is overloaded to write out entities like object, boolean, int, etc. to a file.

Next, we have used a StreamReader class to perform the reading operation. Its ReadLine( )
function reads a line of characters from the current stream and returns the data as a string. This
process is repeated till the end of file is reached. The hierarchy of stream I/O classes is shown in
the following figure:

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

We have taken the first few toddling steps in C#. Imbibe the matter presented here. We would
take a peek below the hood of C# and explore its internal working next time.

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

Article: .C# - WinForms, Win App development made simple...

For building Windows applications the .NET Framework provides two things-classes for
managing the user-interface controls and an Integrated Development Environment (IDE) to
design the Windows applications visually. Any window displayed in an application is created as a
form. WinForms is a programming model used for building Windows applications through a form
designer.

Using the form designer we can create standard windows, borderless windows, MDIs, dialog
boxes, etc. We can add controls, set properties, create event handlers, and add programming
logic to our form. A separate class governs each control that is added to a form. All the control
classes are derived from the Control class. The classes are present in the
System.Windows.Forms namespace. The classes remain same no matter which .NET language
we use.

If you have used the Resource Editor of VB or VC++ you will have to spend little time to get
familiar with the way the IDE works. You simply have to drag controls from a toolbox and drop
them onto a form. Once inserted you can set the properties of the form as well as the controls
using the IDE. The IDE generates only source code and not resource files as in VC++. The basic
program to create a form looks like this:

using System;
using System.Window.Forms
public class myform : Form
{
public myform ( )
{
}
static void Main ( )
{
myform a = new myform( ) ;
Application.Run ( a ) ;
}
}

In Main( ) the Run( ) method of the Application class is called. To this method we have passed
an instance of the form. The Application class provides static methods and properties to
manage an application, such as methods to start and stop an application, to process Windows
messages, and properties to get information about an application. The Run( ) method starts a
standard application message loop on the current thread. If we execute this program it would
merely show a blank form. Let us now see how to attach a menu to this blank form. Carry out the
following steps:

a. Drag in the 'MainMenu' control from the toolbox and release it on the blank form.
b. Click on the control and type the menu item name as 'File'.
c. Add the items 'New', 'Open', 'Save', 'Generate' and 'Exit' to the 'File' menu in a similar
manner.

The resultant form is shown in the following figure.

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

Each menu item is governed by a control variable of the type MenuItem. We can change the
names of these variables through the 'Properties' window. For the program that follows we have
used the names as filemenu that will hold the other menu items, newmenu, openmenu,
savemenu, generatemenu and exitmenu.

Let us now decide what should happen when these menu items are selected. When we select the
'Generate' menu item, shapes like rectangle, ellipse and line should get generated at random and
in random colors. On selecting the 'Save' menu item these shapes should be saved in a file. We
must be able to load this file and display the shapes again. This would be achieved through the
'Open' menu item. When we click the 'New' menu item the earlier shapes should vanish and we
must get a new form to draw new shapes.

While saving the shapes we should not save the image of the shape. Instead we should save the
relevant information of the shape using which we should be able to regenerate the shape again
when the file is loaded. This means we must write the object onto the disk while saving it and load
it back while opening the file. This process of writing the state of an object is called serialization
and reading it back is called deserialization.

To make all these activities to happen we need to add handlers for these menu items. The
Windows Forms programming model is event based. When we click on a menu item it raises an
event. In order to handle an event, our application should register an event-handling method. For
adding these handlers click on the menu item for which we wish to add the handler. Then go to
the 'Properties' window and select the 'Events' tab (shown by a yellow lightening icon). From the
list of events select 'Click'. As a result an event handler called say, openmenu_Click( ) would get
added to our code. On similar lines rest of the handlers can be added. All these handlers will get
added to the Form1 class, which is the default class name.

Before we add code to these menu handlers let us insert four new classes. The first amongst
these is an abstract class called shapes. In this class we will store the color of the shape in
variables r, g, b, representing red, green and blue components of the color. The other three
classes that we would add are line, rectangle and ellipse. These classes are derived from the
shapes class. In these classes we will store the coordinates of the shapes. Each of these three
classes would have a constructor to initialize the data members. Each class would have a
function draw( ) which would contain the logic to draw the respective shape. This function would
be declared as abstract in the base class shapes. To make all the classes capable of carrying

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

out serialization/desrialization we need to add the attribute Serializable as shown in the program
listing given below.

using System ;
using System.Drawing ;
using System.Collections ;
using System.ComponentModel ;
using System.Windows.Forms ;
using System.Data ;
using System.IO ;
using System.Threading ;
using System.Runtime.Serialization ;
using System.Runtime.Serialization.Formatters.Binary;

namespace myapp
{
[Serializable]
abstract class shapes
{
protected int r, g, b ;
Random rd = new Random( ) ;
public shapes( )
{
r = rd.Next ( 255 ) ;
g = rd.Next ( 255 ) ;
b = rd.Next ( 255 ) ;

// put the thread to sleep for next 5


// milliseconds to ensure proper color
// generation
Thread.Sleep ( 5 ) ;
}
public abstract void draw ( Graphics g ) ;
}
[Serializable]
class line : shapes
{
int x1, y1 ;
int x2, y2 ;
public line ( int i, int j, int k, int l )
{
x1 = i ;
y1 = j ;
x2 = k ;
y2 = l ;
}
public override void draw ( Graphics gg )
{
Color c = Color.FromArgb ( r, g, b ) ;
Pen p = new Pen ( c, 4 ) ;
gg.DrawLine ( p, x1, y1, x2, y2 ) ;
}
}

[Serializable]

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

class rectangle : shapes


{
int x1, y1 ;
int width, height ;

public rectangle ( int x, int y, int h, int w )


{
x1 = x ;
y1 = y ;
height = h ;
width = w ;
}
public override void draw ( Graphics gg )
{
Color c = Color.FromArgb ( r, g, b ) ;
Pen p = new Pen ( c, 4 ) ;
gg.DrawRectangle ( p, x1, y1, width, height ) ;
}
}
[Serializable]
class ellipse : shapes
{
int x1, y1 ;
int width, height ;

public ellipse ( int x, int y, int h, int w )


{
x1 = x ;
y1 = y ;
height = h ;
width = w ;
}
public override void draw ( Graphics gg )
{
Color c = Color.FromArgb ( r, g, b ) ;
Pen p = new Pen ( c, 4 ) ;
gg.DrawEllipse ( p, x1, y1, width, height ) ;
}
}
public class Form1 : System.Windows.Forms.Form
{
private System.Windows.Forms.MainMenu
mainMenu1 ;
private System.Windows.Forms.MenuItem
filemenu ;
private System.Windows.Forms.MenuItem
newmenu ;
private System.Windows.Forms.MenuItem
openmenu ;
private System.Windows.Forms.MenuItem
savemenu ;
private System.Windows.Forms.MenuItem
generatemenu ;
private System.Windows.Forms.MenuItem
exitmenu ;
private System.ComponentModel.Container

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

components = null ;
ArrayList s = new ArrayList( ) ;
BinaryFormatter b = new BinaryFormatter ( ) ;

public Form1( )
{
InitializeComponent( ) ;
}
protected override void Dispose ( bool disposing )
{
if( disposing )
{
if ( components != null )
{
components.Dispose( ) ;
}
}
base.Dispose( disposing ) ;
}
[STAThread]
static void Main( )
{
Application.Run ( new Form1 ( ) ) ;
}
private void openmenu_Click ( object sender,
System.EventArgs e )
{
OpenFileDialog od = new
OpenFileDialog( ) ;
od.Filter = "dat files ( *.dat )|*.dat" ;

if ( od.ShowDialog( ) == DialogResult.OK )
{
FileInfo f=new FileInfo ( od.FileName);
Stream st = f.Open ( FileMode.Open );

while ( st.Position != st.Length )


s.Add ( b.Deserialize ( st ) ) ;
st.Close ( ) ;
}
Invalidate( ) ;
}
private void savemenu_Click ( object sender,
System.EventArgs e )
{
SaveFileDialog sd = new
SaveFileDialog( );
sd.Filter = "dat files ( *.dat ) | *.dat" ;

if ( sd.ShowDialog( ) == DialogResult.OK )
{
FileInfo f = new FileInfo(sd.FileName);
Stream st = f.Open ( FileMode.Create,
FileAccess.ReadWrite ) ;
foreach ( shapes ss in s )
b.Serialize ( st, ss ) ;

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

st.Close ( ) ;
}
}
private void generatemenu_Click ( object
sender, System.EventArgs e )
{
Size sz = ClientSize ;
Random rd = new Random( ) ;

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


{
int shapeno = rd.Next ( 3 ) ;
int x1 = rd.Next ( sz.Width ) ;
int y1 = rd.Next ( sz.Height ) ;
int x2 = rd.Next ( sz.Height - y1 ) ;
int y2 = rd.Next ( sz.Width - x1 ) ;

switch ( shapeno )
{
case 0:
s.Add ( new line ( x1, y1, x2, y2 ) ) ;
break ;
case 1:
s.Add ( new rectangle ( x1, y1, x2, y2 ) ) ;
break ;
case 2:
s.Add ( new ellipse ( x1, y1, x2, y2 ) ) ;
break ;
}
}
Invalidate( ) ;
}

private void exitmenu_Click ( object sender,


System.EventArgs e )
{
Dispose( ) ;
}

private void Form1_Paint ( object sender,


System.Windows.Forms.PaintEventArgs e )
{
Graphics g = e.Graphics ;
foreach ( shapes ss in s )
ss.draw ( g ) ;
}

private void newmenu_Click ( object sender,


System.EventArgs e )
{
s.Clear( ) ;
Invalidate( ) ;
}
}
}

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

When we click the 'Generate' menu item its handler gets called. In this handler an object of the
Random class is created. The Next( ) method of this class generates a positive random number
less than the specified number passed to it.

We have used this function to not only decide which shape should be generated but also the
coordinates of this shape. Using these coordinates we have created an object of rectangle,
ellipse or line class. While creating these objects the constructors of the respective classed get
called. Since all these classes are derived from the shapes class, firstly the base class
constructor gets called. This constructor selects a random color.

The references of objects of line, rectangle and ellipse are stored using a collection class called
ArrayList. The object s of this class now consists of references of objects of the line, rectangle
and ellipse classes. As these classes are derived from shapes, it is perfectly legitimate for a
reference to shapes to be set up to point to either shapes or one of its derived classes.

Next we have called the Invalidate( ) method which results in the Form1_Paint( ) method getting
called. Here we have collected back each reference from the array s into a reference ss of type
shapes. Using this reference it has then called the draw( ) method. Depending upon which (line,
rectangle or ellipse) reference is present in ss the draw( ) function of that class gets called. The
resulting form is shown below.

If we wish to save the file we can click on 'Save' menu item. When we do so savemenu_Click( )
gets called. We have created an object of the SaveFileDialog class and used a "*.dat" filter for it.
When we type in a file name and click Ok, a FileInfo object gets created with the selected name.
The Open( ) function returns a Stream object associated with the file. We have collected it in a
Stream reference. We have used the BinaryFormatter object to serialize the objects. The
BinaryFormatter serializes and deserializes an object, in binary format. We have added a
BinaryFormatter object b to our class. The Serialize( ) method of this class serializes the object
to the given stream. After serializing all the elements of the array we have closed the stream
using the Close( ) method.

When we click 'Open' menu item an OpenFileDialog is popped with the appropriate filter. Here
also we have created a FileInfo object and collected the corresponding Stream of the specified
file. Next we have used a while loop to deserialize the objects until the end of stream is reached.
The Deserialize( ) method deserializes the specified stream into an object. We have collected

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

these objects into our array, closed the stream and called Invalidate( ) function for painting these
shapes.

When we click 'New' menu item the array is cleared by deleting all the elements in the array. After
this we have called Invalidate( ). This time the method Form1_Paint( ) draws nothing as the array
is empty, thereby resulting a clean form.

On clicking the 'Exit' menu item the Dispose( ) method gets called and the form is disposed.

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

The earliest form of reuse was in the form of Static Libraries. These libraries contained object
code of functions. During linking the object code of the library functions (usually stored in .Lib
file(s)) was linked with the object code of the program calling those functions to form an
executable file. The linking phase used to precede execution. This way the library functions could
be reused by different applications calling them. This however led to wastage of storage space as
the object code from the function library used to get replicated into every application using it. This
is shown in Figure 1.

Figure 1

In multitasking environments if two applications are running in memory each calling the same
library function then two copies of the same function would be running in two different processes.
This led to wastage of precious memory space.
Also if a bug was found in the library functions the library as well as the client program using it
had to be re-compiled and re-distributed. A recipe for disaster for sure!

To avoid the wastage of memory and disk space Microsoft suggested the concept of Dynamically
Linked Libraries (DLLs). Functions from these libraries never became part of an application trying
to call them. Instead they used to get linked with the applications calling them at run-time.
Moreover, multiple applications calling them used to share the same copy of the library function
present in memory. A developer could simply place the DLL in Windows directory,
Windows\System directory or in the same directory as the EXE file using that DLL and then rely
on the operating system to do the linking at run-time.

This to begin with was a welcome change from the static libraries of the past. However, as
programmer's started building DLLs they realized that the concept though apparently promising is
infested with several problems listed below:

Name mangling - To permit function overloading C++ compilers mangle (decorate) the name of
each function called/defined in the program. Since the C++ language doesn't lay down any rules
about how name mangling should be done, each compiler writer adopted his own strategy to

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

create mangled names. As a result, if one is to load the DLL explicitly as shown in the following
code it was difficult to mention the mangled name.

HMODULE h = :: LoadLibrary ( "myfunctions.dll" ) ;


fptr = getProcAddress ( h, "mangled function name" ) ;
// call the function using the function pointer fptr

Thus the DLL created using one C++ compiler was not of much use to another C++ program that
is compiled through another compiler. As a remedy to this it was suggested that we should use
ordinal numbers in place of function names. Easier said than done! Ask yourself ids of how many
of your co-employees you remember and you would get the answer why this scheme was not
practical.

Cross-Language Usage - Instead of storing exported functions we can create a DLL that would
hold a C++ class. But this class is of little use to a C programmer (as C doesn't understand a
class) or to a Java programmer (as Java doesn't understand the C++ syntax). Thus a cross-
language usage was a no-no in DLLs.

DLL Hell - Imagine a DLL containing some classes. Over a period of time we might be required to
change the signature of the methods present in classes for implementing additional functionality.
If we create this DLL and overwrite the existing DLL with the new one then the clients using the
older version of the DLL would break. To avoid this we need to maintain both the DLLs leading to
versioning problems.

Location Transparency - DLLs did not offer location transparency, as the clients using the DLL
were not independent of the path where the DLL was stored.

Component Object Model

Component software is a paradigm for designing and implementing an application by putting


together independent pieces of software instead of writing one big monolithic application.

COM components have unique characteristics that make them very attractive as building blocks
for larger applications. They can be distributed either as DLLs or as EXEs. Clients can bind to the
components at run-time and don't have to be recompiled due to any upgrades to the components.
The components can be transparently relocated on a remote computer without affecting the
clients i.e. local and remote components are treated in the same manner. This makes distributed
computing very easy. The components can be written in any programming language as long as
they follow a standard memory layout prescribed by the COM specifications. Additionally COM is
object-oriented. COM components along-with COM interfaces support the concept of
encapsulation and polymorphism.

These smaller units with well-defined behavior can be reused across any language. Thus a COM
component written in VisualBasic could be reused by a Visual C++ client and vice versa. COM
imposed a binary standard. Under this standard, components communicated with each other via
interfaces. COM identified components via Globally Unique identifiers (CLSIDs or GUIDs).
Components were registered in the system registry. The benefit of registering was that it was very
easy to see what components were available on one machine. With COM it became easy to write
a component in any of the languages supporting COM and to call it from other languages. But this
ease was topped up with complexity. COM was difficult to learn. Moreover storing information
about all components in the registry made the process of installing software quite complex.

Side-By-Side

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

Windows 2000 introduced a feature called side-by-side that lets us install DLLs in the
application's directory. We can install two versions of the same DLL in a system. Applications are
then free to use the specific version for which they were designed and tested. This way different
applications can use different versions on the same system. This arrangement allows developers
to build and deploy more reliable applications because developers are able to specify the version
they will use for their application, independent of other applications on the system. However, the
down side of this arrangement is that un-installation of these versions becomes complicated.

Assemblies

If an application is to use a COM component it needs the methods and properties stored in COM
component, the type library information and the registry entry of the component. If for any reason
any of these is unavailable the component is rendered unusable. Let us now see how .Net
overcomes this problem using Assemblies.

Assemblies is the .NET's approach to code reuse. It has taken some concepts from its
predecessors, namely, DLLs and COM/COM+. Any .Net code on compilation is stored in an
Assembly. In addition to the IL code an assembly also contains metadata that describes the
assembly as well as any resources that are used by the IL code.

Figure 2

The metadata include the types (classes, methods and properties) exported from the assembly
and a manifest. A manifest is a data structure. It serves the same purpose as the type library and
associated registry entries do for a COM component. Manifest contains more information than a
type library. The details of the manifest structure would be discussed in the next article.

Assemblies can be loaded using the side-by-side technique. This means a different version of the
same assembly can be used inside a single process.

Assemblies support Zero-impact installations. Installations can be as easy as copying the files
that belong to an assembly.

An assembly may represent one file or might be spread across several files.

Shared and Private Assemblies

There are two types of assemblies available: private assemblies and shared assemblies. A
private assembly is used by only one application while a shared assembly is shared amongst
different applications.

By default when we compile a C# program, the assembly produced will be a private assembly.
This assembly (DLL/EXE) should be placed in the same folder as the calling application. With a
private assembly it's not necessary to think about naming conflicts with other classes or
versioning problems because each application has its own copy of the assembly.

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

In shared assemblies we must be careful that the assembly must be unique, and therefore, have
a unique name (called strong name).

Building Private Assemblies

Now we will see how to build a private assembly. We plan to write a class library consisting of a
function called display( ). We will call this function in a client program, which we will create later.
To build a library start VisualStudio.NET and create a Visual C# project with template type as
'Class Library'. Name the project as fontassembly. By default the assembly created for this
project would be private.

Add the following code to the Class1.cs file.

using System ;
using System.Drawing ;
using System.Windows.Forms ;

namespace fontassembly
{
public class mytext
{
public void display ( Form fr, String s, Color c,
String fname, int size, Point pt )
{
Graphics g = fr.CreateGraphics( );
Font myfont = new Font ( fname, size ) ;
SolidBrush mybrush = new SolidBrush (c);
g.DrawString ( s, myfont, mybrush, pt ) ;
}
}
}

The display( ) function simply draws text with the specified Font and Brush. On building the
project a fontassembly.dll file would get created in the fontassembly\bin\Debug subfolder.

Building the client

Let us now build a client that would use the private assembly that we have created. We plan to
make a from-based client. To create the client select a 'Windows Application' project.

When we click on the form some text should be displayed at the position where we click. This can
be achieved by calling the display( ) function from fontassembly.dll in the myform_MouseDown(
) handler. The client code is shown below:

using System;
using System.Drawing;
using System.Collections;
using System.ComponentModel;
using System.Windows.Forms;
using System.Data;
using fontassembly ; // to be added

namespace fontclient
{

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

public class myform :


System.Windows.Forms.Form
{
private System.ComponentModel.Container
components = null;
mytext t = new mytext( ) ;
public myform( )
{
InitializeComponent( ) ;
}
protected override void Dispose( bool disposing )
{
if( disposing )
{
if (components != null)
{
components.Dispose( ) ;
}
}
base.Dispose( disposing );
}
[STAThread]
static void Main( )
{
Application.Run(new myform( ) ) ;
}
private void myform_MouseDown ( object sender,
System.Windows.Forms.MouseEventArgs e )
{
if ( e.Button == MouseButtons.Left )
{
Point pt = new Point ( e.X, e.Y ) ;
t.display ( this, "Hello", Color.Red,
"Comic Sans MS", 30, pt ) ;
}
}
}
}

Note that the mouse event handler should be added separately. For this go to the 'Properties'
window and select the 'Events' tab (shown by a yellow lightening icon). From the list of events
select 'MouseDown'. An event handler called myform_MouseDown( ) would get added to our
code.

In the myform_MouseDown( ) event handler we have first checked whether the left mouse
button has been clicked. If so then we have called the display( ) method of the mytext class from
the fontassembly assembly.

We have created a mytext object in our form class. For the mytext class to become available we
have added the statement using fontassembly. However this is not enough. We also need to
add a reference to the library. To do this we should right click on 'References' in the Solution
Explorer window and select 'Add References'. On doing so the following window appears.

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

Since our assembly is a private assembly (and not a shared one) it would not be listed in this
window. So click on 'Browse' and select the fontassembly.dll from the fontassembly\bin\Debug
directory. As a result the DLL would get copied into the fontclient\bin\Debug subfolder of the
client. Now we can refer to this class in the client code.

On executing the client you would get the window shown below. Click on the form anywhere
using the left mouse button and a string "Hello" would appear there.

With the first assembly under your belt, you are ready to get into the more complicated stuff like
shared assemblies, versioning, application domains, etc. But that would have to wait till the next
article.

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

Article: The .Net


Revolution

If you take a peep into the future you would see .Net written all over it. .Net offers a whole new
paradigm that will change the way you think about writing software. This chapter would help you
to understand the .Net vision.

Though it might be difficult to imagine today the world was still in the mainframe era two decades
ago. Few people had access to or used computers. Home computing was unheard of and
computers were used only through an IT department at work. The three most influential factors
that were responsible for changing this scenario are the PC, the Graphical User Interface and the
World Wide Web. With their arrival millions of more users started using computers. The ability of
handling graphics, audio and video with ease was sufficiently exciting for an average user to get
drawn towards computing. They were responsible for democratizing computing for hundreds of
millions of people and for transforming computer into a mass-market product. Computing has now
become a key activity in the daily lives of business employees and home users.

What will the next generation of computing look like? It would be an online world where millions of
PCs, servers, PDAs (Personal Data Assistants), email devices, mobile phones, digital diaries,
digital copiers, etc, would collaborate with each other through internet based services. It would
make available the information that you and your business needs irrespective of the place where
you are and the computing device, platform or the application that you are using. This vision
however is yet to be achieved. Let us now see what are the major hurdles that current computing
world needs to cross to achieve this vision.

Server-Centric Model

Today's Internet is still the reflection of mainframe era's server-centric model. Most of the
information your business needs is locked up in centralized databases and served to you a page
at a time. The browser largely plays the role of the dumb terminal. Web pages provide a "picture"
of data, not the data itself. Integrating this data with your business's existing systems and that of
your partners is not only costly but often frustrating.

Poor Integration

Though today's standalone applications and web sites provide good functionality and data most
of the time they still work in isolation. One has to navigate manually between websites, devices
and applications, rarely being able to integrate the functionality and data. An apparently simple
task of arranging a meeting with colleagues and automatically updating every attendee's calendar
still remains a complicated computing job. As a result, productivity suffers.

Device-Centric View

As the software engineering matured the demand on productivity, scalability and robustness
increased. This led to developing software in the form of reusable components. With the
widespread availability of network the concept of componentization was extended to Distributed
Computing. The DCOM (Distributed Component Object Model) from Microsoft, CORBA (Common
Object Request Broker Architecture) from Object Management Group and the RMI (Remote
Method Invocation) from Sun became popular models for developing software in the form of
components that would work in the distributed environment. To help build these reusable
components two frameworks came into existence-the DNA (Distributed Network Architecture)
framework and the J2EE (Java Enterprise Edition) from the Java camp. However, both these
frameworks were built around the platform that is connected to the Internet. This promotes a
device-centric view of the world.

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

Web-Centric View

What is needed today is to change the framework from device centric to Internet/Intranet/Web-
centric. Under this framework software will be available as a set of distributed services with the
devices (PC, PDA, Mobile, etc.) acting as mere points of delivery of services. These services are
known as Web Services. Like components they are programmable and reusable. They are
available anywhere via the Internet. Programs built using this model will run across multiple
websites extracting information from each of them and combining and delivering it in a
customized form to any device anywhere in the world.

The potential of Web Services is unlimited. For example, a software company may provide a Web
Service to calculate income tax. Any company that wants to calculate income tax can subscribe to
this Web Service. The customer company need not deploy the income tax calculator. It simply
needs to access the Web Service. The company offering the service can dynamically update it to
accommodate new taxation rates. The subscribers won't have to do anything to get the new
updates. In future a collection of such Web Services may replace packaged software. Other Web
Services that can be developed include weather information; stock quotes, shipping status, news
items, etc. I think you get the picture now.

How will businesses and their customers benefit from Web services? As Web services break
down the distinctions between the Internet, standalone applications and computing devices of
every kind, they enable businesses to collaborate to offer and unprecedented range of integrated
and customized solutions--solutions that enable their customers to act on information any time,
any place and on any device. The following figure captures the essence of the .Net vision.

To meet the challenge of next generation of internet-based computing Microsoft has come up with
the .Net platform. This platform simplifies the process of building these solutions and provides a
framework for integration and interoperability. This platform is based on open standards like (XML
and SOAP) so that it can work across all programming languages and operating systems. It helps
you to combine the power of PCs and smart devices with the richness of Internet. To make Web
services a reality Microsoft has addressed the problem at three levels. It has provided a
framework to help build the web services, development tools and languages to make this
development easy and a server infrastructure to deploy and operate the web services. Let us take
a brief look at each of these.

Development Tools and Technologies

A productive set of tools is critical to carry out successful development on a new platform like
.Net. Visual Studio.net provides a complete solution for building, deploying, and running Web
services. It helps you to maximize the performance, realiability, and security of your Web
services.

Visual Studio.Net helps developers quickly build Web services and applications that scale easily,
using the language of their choice. This multi-language development tool has been built
especially for .Net. You can use programming languages like Visual Basic, C++ and the new
language C# for your development work under .Net. Visual Basic was not object oriented, hence
it has been spruced up and christened into VB.Net. Visual C++ has been extended to build Web
services. You can continue to use it build traditional desktop Windows application s too. A brand
new language called C# (pronounced as C sharp) has also been introduced. This language
combines RAD (Rapid Application Development) feature of Visual Basic, OO of Visual C++ and
portability and platform independence of Java. In addition to these languages provided by
Microsoft, there will be over 20 languages provided by partners, including Perl, Python, COBOL,
and Eiffel from which developers can choose. For server side programming instead of using non-
OO scripting languages like VB SCript we can use C#, VB.Net or C++. Access to databases has
also been improved by providing ADO.Net.

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

Framework

The .Net framework is a high productivity, standards-based, multi-language application execution


environment that handles essential plumbing chores and eases deployment. It provides an
application execution environment that manages memory, addresses versioning issues and
improves the reliability, scalability, and security of your application. The .Net framework consists
of several parts, including the Common Language Runtime and a rich set of class libraries.

Microsoft has also provided a set of core Web services that releases developers from the burden
of building everything themselves. By integrating with these core services to perform routine
tasks, developers can concentrate on building high-value, business-critical Web services.
Microsoft Passport is the first such service which provides authentication services. Microsoft and
many other companies plan to develop more core services for users and enterprises.

Server Infrastructure

Web services should be built on a infrastructure that offers developers the benefits of modular
architecture, economical and linear scaling, security, reliability, manageability, and high
availability. The .Net Enterprise Servers and the Windows 2000 Server family make up the
Microsoft .Net server infrastructure for deploying, managing, and orchestrating Web services.
Designed with mission-critical performance in mind, they provide enterprises with the agility they
need to integrate their systems, applications, and partners through Web services, and the
flexibility to adapt to changing business requirements.

The .NET Enterprises Servers are:

• Application Center 2000 to deploy and manage highly available and scalable Web
applications
• BizTalk Server 2000 to build XML-based business process across applications and
organizations
• Commerce Server 2000 for quickly building scalable e-commerce solutions
• Content Management Server 2001 to manage content for dynamic e-business Web sites
• Exchange 2000 Server to enable messaging and collaboration
• Host Integration Server 2000 for bridging data and application on legacy systems
• Internet Security and Acceleration Server 2000 for secure, fast Internet connectivity
• Mobile Information 2001 Server to enable application support by mobile devices like cell
phones
• SharePoint Portal Server 2001 to find, share and publish business Information
• SQL Server 2000 to store, retrieve and analyze structured XML data.

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

Article: The .Net Framework

.Net is a platform that would help us to build service-oriented applications to meet the demands of
today's Internet businesses. These applications typically gather information from, and interact
with, a wide variety of sources regardless of the platforms or languages in use. Integration of
services available through different sources and platforms calls for an open standard for
describing data and a development platform to help developers create and deploy distributed
applications (services). To this effect Microsoft has decided on XML (Extensible Markup
Language) for describing the data and the .Net framework as the development platform. The .Net
framework is very versatile and addresses many problems that the developers commonly face.
This article would discuss these problems and the solutions offered by .Net.

OS Usage

In the older days of DOS programming calling the ROM-BIOS or DOS routines was a messy
affair. These functions did not have names hence to call these functions it was necessary to pick
up these addresses from Interrupt Vector Table (IVT). Moreover to communicate with these
functions it was necessary to setup the CPU registers. And if you managed to master this you
were required to content with the hardware dependencies. That is the process of a simple
operation like drawing a line varied from one type of display adapter to another. To minimize
these difficulties several libraries came into existence. They were useful but were language
dependent. With Windows things improved to the extent that the Application Programming
Interface (API) functions could be called like any other library function. Moreover with the
introduction of device independence the programmer was not bothered to worry about the device
on which the programmer would finally run. It was Windows Graphical Device Interface (GDI) that
adjusted the drawing according to the capability of the device. Also, the same API functions could
be called easily through different languages. However the Windows API functions typically
needed several parameters to be passed during the call as shown in figure 2.1. Also, API being
merely a library of functions could not support the object-oriented programming paradigm. To

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

bring the benefits of object-oriented programming to Windows programming Microsoft created the
Microsoft Foundation Class (MFC) library. Likewise, Borland came up with Object Windows
Library (OWL). However thought these libraries were very powerful they were not usable across
languages. Thus, a good MFC class meant nothing for a Visual Basic programmer. Similarly, a
Visual Basic library function meant hardly anything for a VC++ programmer.

The .Net framework attempts to resolve these difficulties by providing a Common Language
Runtime (CLR) and a set of base classes that can be accessed through any .Net compliant
language.

Little Reuse

In procedural languages like C reuse was limited to calling the same library functions from
different programs. These functions however were not extensible. They were required to be use
on a "as is, where is" basis. Also structured programming languages did not model the real world
very well. For example, if a C program is used to create a window then there were no language
elements that could be identified with the window or its elements like toolbar, menu, status bar,
etc. In the procedural programming paradigm the whole emphasis was on dividing a job into
several smaller jobs and then implementing these jobs through the individual functions.
Importance was given to the operations rather the data on which these operations are performed.
While dealing with complex systems this was found to be an unrealistic programming model.
World is object-oriented and programmer being the part of the world should also deal with a
system that he is trying to program in the form of objects and their inter-relationship. Object-
oriented languages embrace these concepts and hence have become immensely popular
amongst programmers. C++ and Java are good examples of these. These languages promoted
reuse by letting you inherit features of one class into another and then providing additional
features in the new class. This was possible even if the source code of the first class was not
available. This reuse was a big step forward. However the reuse was restricted within the
language. Thus, a Java class was not of much use to a C++ programmer and vice-versa.
To promote language independent reuse Microsoft came up with a bold new technology called
Component Object Model (COM). COM was a binary specification and components built as per
this specification could be used by not only the conventional languages like C or C++ but also by
scripting languages like VBScript and JavaScript. To accommodate these wide range of
languages a lot of plumbing code was required to be built. Also, COM didn't support cross-
language inheritance or cross-language debugging. Instead of adopting a philosophy of letting all
kinds of languages to use COM components and requiring a lot of plumbing code to be written in

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

the process .Net adopts a different philosophy.

In .Net the capabilities of languages itself is raised in such a manner that they can use COM
components without being required to write lot of plumbing code.

Messy Runtime

DOS was a single tasking operating system, which could run only one program at a time in
memory. With the dramatic increase in the computing power it was unrealistic to expect that a
user will like to use the entire power to run only one program. Windows could utilize this
computing power by letting users run several programs at a time by creating a powerful runtime.
However this runtime had the following problems:

Poor error handling - Windows returned error codes which is not the object oriented way of
handling errors. It has now become a common norm that errors should be handled through
exceptions and nit through error codes.

Costly Inter Procedure Calls (IPC) - When multiple processes are running in memory Windows
runtime ensures that no process barges into the memory of the other. However there is often a
need to communicate between processes. This calls for marshalling (conversion of parameters
being passed to a function into a byte stream) and unmarshalling (conversion of byte stream into
data types). There is a severe overhead in this as lot of copying of parameters takes place. If this
is to be avoided then the second process can be made as a DLL and then made to run in the
same address space as the first. This has a disadvantage that if the DLL fires the process in
whose address space it is running also fires.

.Net overcomes this limitation by using a concept called Application Domains.

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

Changing World

In the last decade or so computing has moved from the confines of an organization to a model
where computing takes place in a distributed environment spread across multiple
branches/offices present at different geographical locations. Also, integration becomes a major
issue when your computing model has to work in tandem with that of your partners, customers
and suppliers. This involves complexities like different computers, different operating systems,
different languages used for development, etc. Let's elaborate on this.
Suppose we wish to develop an Internet application that allows businesses to communicate vital
information with each other across existing communication lines. Let's look at typical solution that
can be offered to this problem using Microsoft technologies. If the application is an n-tier
application then we would need HTML, DHTML & Java Script in the front-tier; VBScript, ASP,
MTS, C++, VB, COM in the middle-tier and SQL, ADO in the back-tier. Developers possessing
sufficient skill in all of these areas are few and costly. In short, a perfect recipe for development
nightmare.
Even if the developers are able to successfully develop the applications, they would be required
to spend hours battling component version conflicts (popularly known as DLL Hell) when the time
comes to install their products. Assured distribution nightmare, in short.
Sun's solution to this problem could be to use Java applets and servlets in the front-tier,
Enterprises Java Bean (EJB) or CORBA or RMI in the middle-tier, and JDBC and a suitable
database in the back-tier. The common theme here is every developer should learn Java
language. This is a far-fetched dream. Though an attempt to make every programmer a Java
programmer has met with more than a lukewarm success, the ground reality is that there would
be several languages in existence, each camp having its own faithful band of programmers. .Net
has understood this reality and hence lets you use language for your taste for carrying out the
development.

Deployment Nightmare

DLLs are created with a motive to share them between different applications. Hence while
installing them instead of placing them in any particular application's directory they are installed
either in Windows directory or in Windows\System directory. Thus whichever application wants to
use a DLL file it can load it from one of these directories. This, on the face appears to be pretty
straightforward. But when a new version of the DLL is released it should not be copied on top of
the earlier version. Otherwise the clients that were using the earlier DLL might break. Thus the
DLLs have to have different names if the two versions are to coexist. These versioning problems
are popularly known as DLL hell.

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

COM has overcome this versioning problem by storing two different versions of the component in
two different directories and then registering these components in the Windows registry using two
unique IDs (popularly known as globally unique id or GUID). However, the installation of a COM
component was a little unrealistic because the COM component used to get stored in one
directory, its CLSID used to be in registry and its interface (through which the functions of the
COM component can be accessed) used to be in the type library of the component. If any of
these used to go bad the component used to be rendered useless.

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

Article: Thinking in C#

C# (pronounced as 'C Sharp') is a new object-oriented language designed at Microsoft by Anders


Hejlsberg. This language would help programmers create secure, robust, portable, distributed
object-oriented applications for the internet. But that is hardly a definition that would impress a
programmer. What he would be most interested in knowing is how this language is going to make
a difference to his daily work and how is it different than existing popular languages like C++,
Visual Basic and Java. The answer is simple-it combines the power of C++ with productivity of
Visual Basic and elegance of Java. That's a tall promise. We need to examine this claim with a
thick lens.

• Power of C++ - C# brings with it object-oriented paradigm of C++. It implements the


same through encapsulation, inheritance and polymorphism.
• Productivity of Visual Basic - Promotes Rapid Application Development through
simpler GUI programming with easy drag & drop support. Properties & Events are part of
the language itself.
• Elegance of Java - No pointers (unless explicitly mentioned), fixed-size primary data
types, Unicode characters, Type-safety, No multiple-inheritance, Garbage collection,
Platform independence.

The C# language is disarmingly simple. C# is the first language that has been designed from
ground up with Internet in mind. Using C# we can create a whole gamut of applications including
Windows-based applications (WinForms), server-side applications (Dynamic Web Pages, Web
Services), client-side applications (Web Forms & Web Controls), enterprise applications
(ADO.NET), mobile applications, components (Assemblies), etc.

The First C# Program

Best way to learn a new language would be by writing programs and then comparing them
feature by feature with popular existing languages like C++, Visual Basic and Java. So let us
begin with the first program that displays a message "Hello C#". Here is the program…

namespace Simple
{
using System ;

class Class1
{
static void Main ( string[ ] args )
{
Console.WriteLine ( "Hello C#" ) ;
}
}
}

On execution, this program prints a message "Hello C#" on the screen. To create this program we
would use the Visual Studio.NET environment in the steps mentioned below:

a. Start Microsoft Visual Studio.NET 7.0 from Start | Program | Microsoft Visual
Studio.NET 7.0 menu option.
b. Create a new C# project from File | New | Project menu option. A New Project dialog as
shown in the following figure would appear.

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

c. From the New Project dialog box select project type as Visual C# Projects.
d. Select Console Application from the list of Templates.
e. Select a location where this project should get saved. Give name to the project - Simple.
Click on OK button.
f. A Class1.cs file would get created.
g. Type the program in Class1.cs file
h. To execute the program, programmers using Visual Studio.NET should use Ctrl + F5.
Those who do not have Visual Studio.NET should go to DOS prompt and execute the
command

C>csc Class1.cs.

Here csc stands for C Sharp Compiler. The output of this command would be an EXE file. To
execute the .EXE file just type its name on the command prompt. (From now onwards we would
build applications using Visual Studio.NET.)

Here we have used console application from several templates. As we go along we would use
other templates also.

The program execution starts from the Main( ) function. Since C# is a pure object-oriented
language it does not allow us to create global variables and functions. Instead, all variables and
functions should be defined inside a class. Hence it is necessary to define the Main( ) function in
some class, say Class1. Except for the line marked out in bold in the above program the rest of
the code shown in the program is generated by the Wizard.

A class is a blue-print from which specific objects can be created. A class is similar to a data type
and an object is similar to a variable. The way we can create several variables from an int type,
likewise we can create several objects from a class like Class1. The class, like structure in C,
allows us to create our own (user-defined) data types by combining intrinsic or other user-defined
data types. Unlike structures in C a class can hold data as well as functions. Thus a class
indicates what kind of data an object of its type can hold and what operations (like addition,
subtraction, display, etc.) can be performed on this data. In short, the class specifies what data
and what functions will be included in objects of that class. We would learn more about this in the
Chapter "Classes and Objects".

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

The void keyword before Main( ) specifies that this function does not return any value. We would
later discuss what static really means. But for now it is necessary and removing it would result in
an error. The string is a data type used to hold a string. The string[ ] represents an array of
strings. As you can see args, the argument of Main( ) has been declared to be of type string[ ]. It
can be used to store command-line arguments, if supplied by the user.

To send output to the screen we have used the WriteLine( ) function. To this function we can
pass strings, integers, floats, etc. Since WriteLine( ) belongs to the Console class we have to
use the form Console.WriteLine( ) to call it. .NET organizes its classes by grouping several
related classes in one namespace. The Console class belongs to the System namespace. To be
able to use the Console class in any program we need to import it from the namespace, which
has been done in our program through the statement using System. Like the Console class our
class is also enclosed in the Simple namespace. This namespace is generated by the Wizard
from the project name that we had specified while creating the project.

Remember that C# is a case-sensitive language. The naming convention used by .NET is that
class names should start with a capital letter. If a single class name contains multiple words, each
word will have its starting letter in capital. The same applies to function names as well. All
keywords are in small case.
Printing Command-Line Arguments

We can stretch the first program done above to add the ability of printing the command-line
arguments that may be supplied while executing the program. The enhance program is given
below:

namespace Simple
{
using System ;

class Class1
{
static void Main ( string[ ] args )
{
for ( int i = 0 ; i < args.Length ; i++ )
Console.WriteLine ( args [ i ] ) ;
}
}
}

The for loop walks through the args[ ] array printing each command-line argument in the
process. Command-line arguments can be supplied through the 'Start | Run' menu item by
following the program name with the arguments that we intend to provide. To find out the number
arguments supplied by the user we have accessed the Length property of the array. The Length
property returns the number of elements in the array, which is then used to govern the conditional
statement in the for loop.

Now that we have the capability to print messages on the screen let us now turn our attention to
the basic building blocks of a language, namely, Data types.

Data Types

The data types in C# can be divided into different groups. Every data type has a strictly defined
size and range. This size would remain same irrespective of the platform being used. These
groups are shown in the following tables:

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

Integers
Data
Signed/Unsigned Size Range
Type
sbyte signed 1 byte -128 to 127
byte unsigned 1 byte 0 to 255
short signed 2 bytes -32768 to 32767
ushort unsigned 2 bytes 0 to 65536
int signed 4 bytes -2147483648 to 2147483647
uint unsigned 4 bytes 0 to 4294967295
-9223372036854775808 to
long signed 8 bytes
9223372036854775807
ulong unsigned 8 bytes 0 to 18446744073709551615
Any whole number value can be an integer value. The data types in this group
cannot hold fractional values.
Floating Points
Data
Signed/Unsigned Size Range
Type
float signed 4 bytes 1.5 x 10 -45 to 3.4 x 10 38
double signed 8 bytes 5.0 x 10 -324 to 1.7 x 10308
The data types in this group can hold Floating-point numbers representing
decimal values with a fractional component.
Character
Data
Signed/Unsigned Size Range
Type
char unsigned 2 bytes
The data type in this group can hold a character with a 16-bit Unicode value.
Unicode defines fully international character set that can represent all of the
characters found in all human languages. It is the unification of dozens of
character sets such as Latin, Greek, Arabic, Cyrillic, Hebrew, Katakana, Hangul
and many more. For this purpose it requires 16 bits to represent each character.
Boolean
Data
Signed/Unsigned Size Range
Type
Bool NA 1 byte true or false
This type can hold logical values. It can have only one of the two possible
values, true or false.
Decimal
Data
Signed/Unsigned Size Range
Type
16
decimal signed 1.0 x 10 -28 to 7.9 x 10 28
bytes
This data type is a dedicated type for financial calculations. It represents higher
precision floating-point numbers. It allows us to specify currency amounts.

C# imposes some rules while using these data types. These rules are explained below with the
help of code snippets:

Rule 1: Before using any variable it must be initialized with a value.

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

int i ;
Console.WriteLine ( i ) ;

This would result in an error since before printing the value of i it has not been initialized. Unlike
C/C++ there is no concept of garbage values.

Rule 2: The variable can be initialized with a value that is within the range of its type.

short s = 40000 ;

This would result in an error. Here, since s is of 2 bytes it can store a maximum value of 32767.
Unlike C and C++ the value would not get wrapped to the other side of the range.

Rule 3: While initializing the destination type must be larger that the source type.

short s = 40 ;
byte b ;
b=s;

Here, the value of a short variable is being assigned to the variable of type byte. Since, size of a
short is larger than that of a byte this results in narrowing of the value. Narrowing conversions
are not supported implicitly by C#. To make this work we need to do an explicit conversion like,

b = ( byte ) s ;

C# supports implicit wider conversion. Hence the statement s = b would work.

Rule 4: sbyte and short are converted to an int type, whereas, byte and ushort are converted
to a uint type while performing arithmetic operations on them.

short s1 = 40, s2 ;
byte b = 6 ;
s2 = s1 + b ;

Here, s1 and b would be converted to an integer type before performing addition. The resultant
value would be an integer. Assigning an integer value to a short variable would result in an error.
To make this work we have to write s2 = ( short ) ( s1 + b ).

Character type can be converted into integers and manipulated with the integer operators such as
the addition and subtraction operators. For example,

char c = 'a' ;
int i ;
i=c;
i=c+1;

Rule 5: Boolean type is incompatible with rest of the data types.

int i = 40 ;
bool b = true ;
i=b;
b = ( int ) i ;

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

The bool type is returned by all relational operations such as a < b. The bool is also a type
required by the conditional expressions that govern the control statements such as if, while and
for. It solves the problem where programmers mistakenly use = instead of == resulting in
unexpected behaviour. This distorted type safety. For example, several years ago, a space bound
rocket crashed just minutes after launch costing NASA millions of dollars. Upon investigation, it
was discovered that the crash was a result of a software failure. Specifically the fault was traced
to a buggy line of C code in which the programmer had mistakenly used = at a place where ==
was needed. Let us see with an example how C# solves this problem.

int a = 10, b = 50 ;
if ( a = b )
a = 70 ;

This code would result in an error because the result of the assignment statement a = b is not a
bool value.

Control Statements

Statements like for, return, goto, break, and continue work in the same way in C# as they do in
C and C++. But there are differences in the way if, while, do..while and switch statements work.
Moreover an additional looping instruction called foreach has also been added in C#. Let us now
understand the improvements that have been made to the control instructions.

switch Statement

Unlike C and C++, control in a switch statement in C# is not permitted to "fall through" to the next
case if a case gets satisfied. For example:

switch ( grade )
{
case 'A' :
Console.WriteLine ( "In A" ) ;
case 'B' :
Console.WriteLine ( "In B" ) ;
case 'C' :
Console.WriteLine ( "In C" ) ;
case 'F' :
Console.WriteLine ( "In F" ) ;
}

This statement gives an error. This happens because of absence of the break statement. In C
and C++, if such a switch statement is written we do not get an error. Instead the cases present
after the one that gets satisfied are executed. In C#, if we want some other case to get executed
after the one that gets satisfied then we must explicitly use a goto statement as shown below:

switch ( grade )
{
case 'A' :
Console.WriteLine ( "In A" ) ;
goto s1:
case 'B' :
Console.WriteLine ( "In B" ) ;
break ;
case 'C' :

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

s1:
Console.WriteLine ( "In C" ) ;
break ;
case 'F' :
Console.WriteLine ( "In F" ) ;
break ;
}

If we want that the same code should get executed if any of the two cases is satisfied then we
can write the following code:

case 'a' :
case 'A' :
Console.WriteLine ( "In A" ) ;

In this example since the case 'a' is empty there is no need for a break statement in it. The
switch statement can check integer, character and string types.

foreach Loop

The foreach statement lets us iterate over elements in arrays. If we want to iterate through an int
array arr we can do so through the following statements:

int[ ] arr = { 1, 2, 3, 4, 5 } ;
foreach ( int i in arr )
{
Console.WriteLine ( i ) ;
}

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

Article: Registry

The registry is used to store information about Windows setup, user preferences, and installed
software and devices. All the COM components place their CLSIDS, ProgIDs, paths of the DLLs,
versions in the registry. This helps the clients to load the component from any directory. The
registry is a hierarchical structure whose top-level nodes represent the registry hives. To view or
modify the registry we execute the utility regedit through Start | Run Dialog.

The number of hives in the registry is fixed. There are seven of them. We cannot see all the
hives.

• HKEY_CLASSES_ROOT - Contains details of the types of files present on the system


and information about applications that are able to open those files. It also consists of
registration information for all COM components.
• HKEY_CURRENT_USER - Contains details of user preferences for the user currently
logged on to the machine.
• HKEY_LOCAL_MACHINE - Contains details of all software and hardware installed on the
machine.
• HKEY_USERS - Contains details of user preferences for all users.
• HKEY_CURRENT_CONFIG - Contains details of configuration of hardware devices on
the machine.
• HKEY_DYN_DATA - Contains information about volatile data.
• HKEY_PERFORMANCE_DATA - Contains information concerning the performance of
running applications.

Each root key consists of data as well as keys. The data is present as values. The value is
divided into 3 parts: name, type and data. The key may have a default value, which is unnamed.
The type of value may be formatted as one of the three data types namely, REG_SZ,
REG_DWORD, REG_BINARY.

• REG_SZ corresponds to a string.


• REG_DWORD corresponds to a uint.
• REG_BINARY corresponds to an array of bytes.

The .NET Framework offers two classes in the Microsoft.Win32 namespace: A RegistryKey
class and a Registry class. Microsoft.Win32 namespace contains classes related to those that
handle events raised by the operating system and those that manipulate the system registry.
These classes are not included in the System namespace because they are specific to Windows
operating system.

The RegistryKey class represents a Registry key. This class has methods to browse, to create
new keys and to read or modify the values in the keys.

The Registry class contains only seven public static fields, which expose the actual keys to the
programmer. These fields are read-only fields and cannot be modified. These fields expose the
instances of the root RegistryKeys found in the registry. The seven fields are CurrentUser,
LocalMachine, ClassesRoot, Users, PerformanceData, CurrentConfig, and DynData . This
class is never instantiated and it only provides us with instances of top-level registry key
instances.

Creating a Test Version Application.

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

In the following program we plan to write an application that keeps a count on the number of
times the application has executed as well as the amount of time the program spent in execution.
If the application crosses a specified limit, it becomes unavailable. Many softwares, especially the
ones that we download freely from the Net have an expiry period. When we run such softwares a
dialog is popped up which informs us that we can use the software only for a specific number of
days. And this count keeps reducing every day.

In our program we have kept a limit on number of days as well as time. The Logic used is as
follows:

When we run our application for the first time, we add a registry entry in the
HKEY_CURRENT_USER | Control Panel. Hence we have added a key for our application along
with two values, one for maintaining the number of executions and another for maintaining the
count on time.

Next time when we open the application it checks these values and accordingly allows or
disallows the program to execute. The limitation that we have kept in the program is that it should
work for a maximum of 5 hrs or can execute only 50 times.

To keep a count on time, we have added a timer control in our application. This is done by
dragging in the control from the toolbox. We have changed its name from timer1 to mytimer.

Every time we start the application a 'staring form' is displayed which indicates the time expired,
time remaining, number of times the application was executed, and remaining number of times it
can be executed.

Here we have added 9 labels, 4 for displaying the static text and four for displaying the time
expired, time left, executions completed, and executions remaining. We have named them as
texp, tleft, execom, and exerem respectively. The last label is used to display a message
besides the start button. The start button indicates that the actual application will start, the earlier
form is just a starting indication, and it does not start the real application. When we click the start

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

button, the timer starts and number of executions increases by one.

But before this we have to add in registry entries. We plan to add our key in the
HKEY_CURRENT_USER | Control Panel. We can add this somewhere else also. We have
done this in the constructor of the form.

We have added the following data members to the form

RegistryKey top, r, demo ;


int min, numexe, timercounts ;

In top we will have the RegistryKey instance of HKEY_CURRENT_USER key. In r we will have
instance of Control Panel key and in demo we will have the key of our application. min will
contain a count of minutes, numexe will contain a count of number of executions and
timercounts will contain a count on seconds.

public Form1( )
{
InitializeComponent ( ) ;
top = Registry.CurrentUser ;
r = top.OpenSubKey ( "Control Panel" , true ) ;
demo = r.OpenSubKey ( "softdemo" , true ) ;
if ( demo == null )
{
demo = r.CreateSubKey ( "softdemo" ) ;
demo.SetValue ( "Minutes", ( object ) min ) ;
demo.SetValue ( "Executions", ( object ) numexe ) ;
}
else
{
min = ( int ) demo.GetValue ( "Minutes" ) ;
numexe =(int) demo.GetValue ( "Executions" );
}
texp.Text = min / 60 + " hours " + min % 60 + " minutes" ;
int m = 300 - min ;
tleft.Text = m / 60 + " hours " + m % 60 + " minutes" ;
execomp.Text = numexe + " " ;
exerem.Text = 50 - numexe + " " ;
msg.Text = " Click Start Button To Start Application " ;

if ( numexe >= 50 || min >= 300 )


{
msg.Text = "Trail Version expired" ;
start.Enabled = false ;
}
}

Firstly we have collected the top-most RegistryKey in top using the Registry.CurrentUser field
of the Registry class. Next we have initialized r with the key of Control panel using the
OpenSubKey( ) method. Then we have initialized demo with the key of our application using the
same function. If we get a null in demo, it means that this is the first time the application is
running and no key is present. In this case we have added a new sub-key using the
CreateSubKey( ) method. To this key we have added two values Minutes and Executions and
have set both the data fields to 0 using the SetValue( ) method. The SetValue( ) method takes
the second parameter as an object and hence we have type-casted it.

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

If demo does not contain a null it means that the application is not running for the first time and
the key and its values already exist. In this case we have retrieved the values using the
GetValue( ) method. While retrieving the value we have to type cast it back in whichever data
type we have used amongst a string, an int or a byte array. Here we have used an int. Next we
have set all the text fields of the labels to the appropriate values by calculating the time in hours
and minutes from the extracted key values. If the extracted minutes happened to be more that
300 (5 hours) or the number of executions happened to be more that 50, we have disabled the
start button and flashed an appropriate message.

We have kept a count on time with the help of the timer. The timer starts when we click the Start
button:

private void start_Click ( object sender, System.EventArgs e )


{
numexe++ ;
demo.SetValue( "executions", ( object ) numexe ) ;
mytimer.Start ( ) ;
MessageBox.Show ( "Write Your Application Logic Here" ) ;
}

When we press 'Start' the number of executions is increased and the new value is set. We have
added the Tick( ) handler with a time interval of 1000 milliseconds. This means after every 1000
milliseconds (1 second) this event will be fired. We can change this value in the 'Properties'
window of the timer control. This is the place where we can write the logic of our actual
application.

private void mytimer_Tick ( object sender, System.EventArgs e )


{
if ( ++timercounts >= 60 )
{
min++ ;
texp.Text = min / 60 + "hours " + min % 60 + "minutes" ;
int m = 300 - min ;
tleft.Text = m / 60 + "hours " + m % 60 + "minutes" ;
demo.SetValue ( "Minutes", ( object ) min ) ;
timercounts = 0 ;
}
if ( min >= 300 )
{
mytimer.Stop ( ) ;
Dispose ( ) ;
}
}

Here we have first checked if timercounts is greater than 60 (1 min). If it is, we have increased
min by one and we have written the new value in the registry as well as in the text filed of the
labels accordingly. Next we have checked the min field. If it happens to be greater than 300 (5
hours), the timer should stop and the program should terminate. To do so, we have called the
Dispose( ) method. In this method we have disposed all the objects we created.

protected override void Dispose( bool disposing )


{
top.Close ( ) ;
r.Close ( ) ;

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

demo.Close ( ) ;
if ( disposing )
{
if ( components != null )
{
components.Dispose ( ) ;
}
}
base.Dispose ( disposing ) ;
if ( min >= 300 || numexe >= 50 )
MessageBox.Show ( "You can no more use this software, time elapsed!!!!" ,"Sorry" ) ;
}

Here we have checked the min and numexe values and if they exceed the specified limit we
displayed a dialog box with an appropriate message.

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

Article: DirectX - Direct Is Better

Hats off to the game developers of DOS era! They suffered so much and complained so little. To
be able to write a game they were required to know what colors are available on the PC, how to
produce them, how much memory does the PC have, what are the sound capabilities of the PC,
which video card is installed in the PC, which different graphics mode does it support, what are
the input devices attached to the machine, etc. But they were brave people. They acquired this
knowledge and used assembly language and later C to develop games that met user's taste and
demands.

One day all this changed. That was when Microsoft Windows operating systems came into being.
No longer were the programmers required to worry about the new and changing capabilities of
graphics cards, joysticks, graphics accelerators, etc. Now the game programmers were not
required to spend time in creating and understanding the hardware specifications of display
adapters. They could rely on Microsoft to do all that for them and package it for their use in the
operating system. This was a big step forward. Still the game programmers were not happy to
change from DOS to Windows as their game development platform. This was because though
Windows could make it easier to develop games it stifled the creativity of the game designer and
compromised the performance of the game by not letting the programmer have a direct access to
the device capabilities. No longer was the scrolling smooth, the animation crisp and the sound
explosive. So much so that many game developers simply abandoned the idea of using Windows
as their game development platform. They continued their game programming in DOS and simply
used Windows capability to shell out to DOS.

Such are the times that separate men from the boys. Microsoft didn't get disappointed with the
lukewarm response that Windows received from game programmers. Microsoft knew that their
strategy was right. They simply had to ensure that the performance of their model should be
improved to match the performance that the game programmers had become accustomed to in
DOS. Microsoft went back to the drawing board and came up with a Game Software Developer's
Kit (Game SDK). This was the first version of DirectX. It consisted of fast, low-level libraries that
did not impose constraints on the game design. It met and at times even exceeded the
performance of DOS. Lastly, DirectX ensured that the burden of hardware support shifted from
the developers to the hardware manufacturers. After all, the hardware manufacturers were
eminently capable of creating drivers for their products and it was their responsibility to make the
latest advance in their hardware accessible to the developers.

As the years have gone by DirectX too has evolved and has continuously increased its
capabilities. Today it boasts of network support, force-feedback support and 3D graphics
capabilities. So much so that it is no longer being used only for writing games, though that
remains its predominant use. It is now also being used to show off your latest products, to create
a virtual stereo to listen to the difference in types of sound systems that companies offer, to create
screen savers and to build applications like instant messenger and voice chat that allows users to
talk with one another on the internet.

What's Direct In DirectX

DirectX has been based on the philosophy of 'Directness'. There is no beating around the bush. It
understands that all said and done if DirectX doesn't provide speed and takes the approach "we
know what is best for you" there won't be many takers for it at the end of the day. It achieves its
directness through:

Speed

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

To achieve speed DirectX uses the hardware features where they are available and emulates
them where they are not available. For example, if hardware provides a operation like memory
swap DirectX uses this feature thereby allowing the developer to get maximum out of parallel
architecture that multimedia hardware can provide.

Reduced Latency

If we hit a key in a Windows application a message called WM_KEYDOWN is sent to the


message queue of the application. When its turn comes the message is picked up from the queue
and then processed by calling a suitable function. This process has been abstracted away from
the programmer and he is required to bother only about the functionality that must be provided in
the function that would get called when the key is pressed. This is all very good for normal
Windows application, but it is a strict no no for game programming. Imagine a typical situation in a
2-player game. If one user places a punch on your nose, you would want to square it off right
there. In this situation it would be unacceptable if Windows takes a long time to process your
keyboard message. DirectX attempts to reduce this latency between "thinking of doing" and
"actual doing".

Non-Interference

While building a library, one is often tempted to do things in a way one thinks is right and best.
This can be dangerous and counter-productive. For example, if DirectX evolves a communication
model that works same for a car-racing game and for a Chinese-checker game it would be
inappropriate because the communication requirements of these games are different. So DirectX
doesn't try to generalize things and provide automatic models for different gaming operations.
Instead, it concentrates on the basics and seeks to enrich Windows by providing a set of low-level
tools for building better games and multimedia applications. It does the basic operations well and
leaves it to the imagination and innovativeness of game developers to exploit these features for
their gaming product. Fair enough!

Components Of DirectX

DirectX made its debut as a Game SDK. But this SDK had a life span of only one version. There
are a lot of 'DirectSomethings' in existence today. The chart Figure 1.1 shows their names and
the subsequent discussion explains their purpose.

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

DirectX Components

DirectX Graphics

This component includes various functions that are used for handling graphics. This component is
further divided into DirectDraw (2D Graphics) and Direct3D (internally uses DirectDraw). The
DirectX Graphics component also includes Direct3DX utility library which helps in simplifying
complex mathematical operations useful to Direct3D.

DirectInput

This component supports variety of input devices like keyboard, mouse, joystick, etc. It also
provides force-feedback effect in input devices like motor mounted joystick by generating push or
resistance. Force-feedback technology helps make the gaming environment more realistic. For
example, if we are flying an aircraft in a game and if the aircraft crashes then due to force-
feedback we would feel the jerkiness of the explosion. (push effect) . Or if we are driving a car
with the help of a force-feedback joystick, the more we push the joystick the more the car
accelerates. If the car collides with another car/obstacle then the joystick will try to resist our
action of pushing to simulate an obstacle. DirectInput removes delay in receiving input data by
bypassing the Windows messaging architecture.

DirectX Audio

This component consists of DirectSound and DirectMusic. DirectSound is used to generate


sounds like car doors slamming, horns honking and birds chirping thereby making games more
realistic. It also removes delay in generating sound effects. DirectMusic is used to compose
music at runtime.

DirectPlay

This component facilitates multi-player gaming on the network or Internet. It provides functionality

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

needed to organize and launch a multi-player game. This component can also be used to create
messaging applications similar to MSN Messenger Service.

DirectShow

This component is used to playback multimedia streams like MPEG, AVI, WAV, QuickTime, etc,
from local files or Internet servers. Using this component we can create variety of effects that are
seen in PowerPoint and many more such applications.

DirectSetup

This component enables us to distribute DirectX runtime with our application. With this
component our application can be packaged into a nice setup program. When it is installed all the
libraries and support files are available when the user needs them.

Article: C# - Shared Assemblies

In the article on 'Assemblies' we saw how to build a private assembly. We shall extend that
discussion and see how to build and use shared assemblies this time. We will convert the same
assembly we made last time into a shared assembly. Recall that a private assembly is private to
an application and every application using it has its own copy of the assembly. There is no need
for the private assembly to be unique. A shared assembly on the other hand is available to all
clients and hence must be unique.

To be uniquely identified, a shared assembly must have a strong name. The combination of a file
name, a public key, a version number and culture gives an assembly a strong name, which is
guaranteed to be unique. To understand these terms we must first know what is a public and
private key.

Public Key Cryptography

Public and private keys are nothing but algorithms used for encryption and decryption of data.
The main principle used in public / private encryption / decryption is as follows:

• If something is encrypted using a public key, it can be decrypted using the corresponding
private key, but not with the public key. This also works the other way round too, i.e. if
something is encrypted using a private key it can be decrypted using the corresponding
public key, but not the private key.

Public and private keys are always created in pairs. The public key is made available to
everybody and the private key is kept safe and secure.

How it works on Assemblies?

First a public-private key pair is generated at random for the assembly using the sn utility. How to
generate the keys using the sn utility is discussed later. We then provide these keys to the
compiler. The compiler takes a cryptographic hash of the names and contents of the files in the
assembly. This hash is taken using a very simple algorithm. This cryptographic hash is then
encrypted using the private key for the assembly by the compiler, and placed in the manifest.

The compiler also creates the strong name and writes it in the manifest. As said earlier a strong
name consists of a combination of a file name, a public key, a version number and culture. So
along with the strong name the public key also gets written in the manifest. The strong name
does not contain the private key. This ensures that the private key is not written in the manifest

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

and hence not made available to everybody. So in all two things are written inside the manifest,
the strong name and the encrypted hash of the names and contents of the files. This is called
signing of assembly.

Whenever an application wants to load an assembly, the runtime decrypts the hash of the files
using the assembly's public key. The public key is available as it is stored in the manifest as part
of the strong name. Then the runtime reads the names and files of the assembly and calculates
the hash for itself. These two hashes are then checked, if they match, the assembly is loaded or
else its not.

Any changes made to the files in the assembly after it is installed will make the application not
work because the calculated hash won't match with the decrypted hash and the runtime will not
load the assembly. If somebody tries to change the manifest, the .NET runtime will again detect a
problem and refuse to load the assembly.

All the shared assemblies available on a system are stored in a folder called the Global
Assembly Cache. This store is located in the '<drive>:\Windows\Assembly' folder.

Using the sn utility

We plan to convert the same DLL i.e. fontassembly.dll into a shared assembly. To convert it into
shared assembly we have to first use the sn utility (strong name utility). This utility generates a
public / private key pair. The public key created using this utility will be used to define a strong
name.

To create the key pair we must type the following on Command Prompt

C:\CSharp\fontassembly>sn -k mykey.snk

On executing the utility a file mykey.snk gets created. This file contains the public and private
keys.

We must now use this file in our project. To do so open the 'AssemblyInfo.cs' file of the project. In
this file we would have to set the AssemblyKeyFile attribute. The attribute must be set to an
absolute path to the key file. Following are the changes ( shown in bold ) to be made in
'AssemblyInfo.cs'

[ assembly: AssemblyDelaySign ( false ) ]


[ assembly: AssemblyKeyFile ("mykey.snk") ]
[ assembly: AssemblyKeyName ( "" ) ]

We also have to change the version number of our assembly as shown below

[ assembly: AssemblyVersion ("1.0.1.1") ]

The reason behind this will be clear when we discuss versioning in the next article. On rebuilding
this, the assembly along with the strong name associated with it gets created and also the
encrypted hash is written in the manifest. This is known as signing of the assembly.

Installing the Shared Assembly

After signing the assembly, it's possible to install the assembly in the global Cache. To install a
shared assembly in the global cache we have to use the Global Assembly Cache utility tool
called the gacutil tool. At the command prompt we have to use it with a /i option. Here /i stands
for install. This what we must type at the command prompt

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

C:\CSharp\fontassembly\bin\Debug>gacutil /i fontassembly.dll
Microsoft (R) .NET Global Assembly Cache Utility. Version 1.0.2914.16
Copyright (C) Microsoft Corp. 1998-2001. All rights reserved.

Assembly successfully added to the cache

We can now open the Global assembly cache and we will find that our assembly gets added to it
as shown in following figure.

Using the Shared Assembly

We will use the same client we made last time for using 'fontassembly.dll'. To do so first we have
to be sure of two things: We must delete the private 'fontassembly.dll' version we created last time
from the directory of the client and secondly we must remove its reference by right clicking on
fontassembly under 'References' in the 'Solution Explorer' window and selecting 'Remove'.

To use the shared assembly we will have to again add the reference of the shared assembly in
the same way as for the private assembly. But this time the assembly does not get copied into the
local directory because the CopyLocal property of the reference is automatically set to False by
the compiler. This can be seen in the 'Properties' Window of the assembly.

On compiling the client we get the same results. We can now use the same DLL in any client we
want and every time the assembly installed in the Global cache will be used.

Structure of an Assembly

So now lets look at how the assembly looks like. The assembly is made up of metadata , IL code
and resources. The Metadata consists of type metadata and assembly metadata.

Assembly Metadata describes the assembly and is called the Manifest. A manifest contain:

a. The identity of the assembly, consisting of its name, version and culture.

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

An assembly has a four part version number e.g. 1.0.1.1. The parts are

<Major> . <Minor> . <Build> . <Revision>

The use of these numbers is dependent on the configuration of our application. If the new version
created is compatible with the older version we must not change the major or minor numbers. On
the other hand if the versions are incompatible we must change the major and minor numbers.
The build number is the number of days since Jan-1, 2000, and revision is the number of seconds
since midnight local time. Culture is

b. Names of all the files in the assembly.


c. Details of all the types defined in the assembly.
d. Whether all the types defined in the assembly are visible to other assemblies or private to
one.
e. A hash of all files in the assembly
f. Names and hashes of other assemblies that an assembly in turn will need to reference
when run
g. Details of any security permissions that clients need to have in order to be able to run the
assembly

Type metadata consists of metadata describing the exported types and methods. To view the
assembly and manifest Microsoft has provided us with the ILDASM tool.

The ILDASM Tool

The ILDASM, the MSIL disassembler, is used to view assemblies. We can run this tool by starting
ildasm from the command line, with the assembly as argument or by selecting the 'File / Open'
menu.

This is how the ildasm window looks after opening our 'fontassembly.dll' in it:

The tool shows the Manifest, Namespace, Class and Method in the assembly. It can also show
Interfaces, Value types, Static methods, Fields, Static Fields, Events and Properties if present.

Article: C# - Versioning

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

Continuing the analysis of Assemblies from the last article, we shall see how you use the new
features to solve versioning problems. With DLLs, a new version would always overwrite the older
version breaking the clients using the older version. Assemblies bypass this problem.

We never do versioning on private assemblies. Every client has its own copy of the private
assembly and installing a newer version would mean overwriting the existing version. This would
not affect or break clients using the older version because they would still have their copy of the
older version in their local directories.

Versioning is always done on assemblies with strong names i.e. shared assemblies. We can
install multiple versions of the same assembly in the Global Cache simultaneously. The older
versions do not get overwritten and hence clients using the older version do not fails. If we want
we can also redirect old clients to start using the new version. This is all done with the help of
configuration files.

Last time we had created an assembly and stored it in 'fontassembly.dll'. What we plan to do here
is to create a new version of 'fontassembly.dll'.
To do so we would have to create a new copy of the code and make the following change in
'Class1.cs' file.

Font myfont = new Font ( fname, size, FontStyle.Italic ) ;

And the following in 'AssemblyInfo.cs' file.

[ assembly: AssemblyVersion ( "1.1.1.1" ) ]

On rebuilding this, the assembly along with a strong name associated with it gets generated. Next
we have to install this version in the Global assembly cache. This is done using the gacutil tool.
After installing it in the Global assembly cache we find that both the versions of 'fontassembly.dll'
(1.0.1.1 and 1.1.1.1) stand installed.

Figure 1 : Global Assembly List

Now client applications can be created that use any of the two versions installed. We just have to
add a reference of the assembly we want to use.But this leaves us with one question. What about
already existing clients who want to shift to a newer version without being recompiled? The
answer is redirection.

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

We can specify redirection in a configuration file of the client. We will have to first create a
configuration file for that. With the configuration file we can specify that the binding should
happen to a different version of a shared assembly without rebuilding the client application. To
achieve this .NET provides us with a .NET Admin Tool which is a MMC Snap-in called
'mscorcfg.msc'. It is present in the C:\WINNT\Microsoft.NET\Framework\v1.0.2914 directory.

Figure 2 : .Net Admin Tool

To create a configuration file we will have to right click on 'Applications' on the left side, choose
'Add' and select 'fontclient.exe'. The .NET Admin Tool shows all the dependencies of the selected
assembly. Also, we here we can alter and configure the dependencies of of the assembly from
the dependency list. The list shows assemblies our client depends on. The highlighted entry in the
following figure is the version of 'fontassembly.dll' that our client is using presently.

Figure 3 : Default Assembly Versions

We plan to request for a new version. To do so we have to right click on 'Configured Assemblies'
and select 'Add'. Next we have to select 'Choose an assembly from the assembly cache' and click
'Choose Assembly'. Then select 'fontassembly.dll' with the new version and click 'Select'. On
selecting 'Finish' we get the 'Properties' sheet. In this sheet we will have to specify the old and
new version of 'fontassembly.dll'.

Now we can find an application configuration file 'fontclient.exe.config' in the directory of the
'fontclient.exe'. The 'fontclient.exe.config' file that gets created is in XML format is as shown below

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

<?xml version="1.0"?>
<configuration>
<runtime>
<assemblyBinding xmlns="urn:schemas-
microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity
name="fontassembly"
publicKeyToken =
"a97ce0a468973397" />
<bindingRedirect oldVersion="1.0.1.1"
newVersion="1.1.1.1" />
</dependentAssembly>
</assemblyBinding>
</runtime>
</configuration>

When we run the client with this configuration file the redirected version 1.1.1.1 is used instead of
the older version.

Article: C# - Events And Delegates - I

Each action the user makes such as clicking the mouse button, selecting a menu item, pushing a
button, etc. raises an event. Events notify that something has happened, as a result, some action
should take place. The action is performed in a method called an event handler. All the event
handlers are called with the help of delegates. Hence to understand events and event handlers
we must first know what delegates are.

Delegates

We normally pass a value or a reference of an object to a method. Situations may arise where we
may need to pass an address of some method to another method. This was done previously with
the help of function pointers. This approach is not type safe and certainly not object-oriented.

C#'s alternative for function pointers is delegates. Here, the word delegate means a
representation of a function. A delegate is implemented as an object that stores address of
method in it. The class of this object is called a delegate class and is derived from
System.MulticastDelegate class.

To store the address of a method,

bool fun ( string )


{
}

in a delegate we have to carry out two steps:

a. Declare a delegate class


b. Create a delegate object and store the address of the method in it

Declaring A Delegate Class

Here is a single delegate class declaration

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

public delegate bool del1 ( string ) ;

When the compiler encounters this statement it creates a class named del1 and derives it from
the System.MulticastDelegate class. The compiler also inserts a two-argument constructor in
the del1 class. Note that we are never required to define a delegate class.

Later when an object of the delegate class del1 is created, it can hold address of a method that
receives a string and returns a bool.

Creating A Delegate Object

To store address of the fun( ) method inside a delegate object need to first create a delegate
object. This is how it can be done.

del1 f = new del1 ( fun ) ;

Here f is a reference to an object of del1. The address of the fun( ) method is passed to the
constructor of the delegate class which is created by the compiler. The constructor stores this
address in the delegate object. To call the wrapped method we can write the following statement:

bool b = f ( "Hi" ) ;

Here f delegates (represents) fun( ) in true sense.

Delegates are very flexible. It does not matter whether the method to be wrapped by the delegate
is a static method or an instance method. Also, these methods can belong to any class. Consider
the following program:

using System ;
namespace Sample
{
public delegate void click( ) ;

public class MyForm


{
public click c1 ;
public void mouseclick( )
{
c1( ) ;
}
}

class MyForm1 : MyForm


{
public MyForm1( )
{
c1 = new click ( MyForm1_click ) ;
mouseclick( ) ;

c1 = new click ( button_click ) ;


mouseclick( ) ;
}

static void Main ( string[ ] args )


{

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

MyForm1 f = new MyForm1( ) ;


}

public void MyForm1_click( )


{
Console.WriteLine ( "Form clicked" ) ;
}

public static void button_click( )


{
Console.WriteLine ( "Button clicked" ) ;
}
}
}

In the above program we have declared a delegate class called click. Later when an object of
this class is created it can hold address of any method that does not accept or return anything.

We have created two classes in the program: a MyForm class and a MyForm1 class derived
from MyForm. The MyForm class contains a reference c1 of the type click and a method called
mouseclick( ).

Besides the zero argument constructor and Main( ), the MyForm1 class contains an instance
method called MyForm1_click( ) and a static method called button_click( ). Both
MyForm1_click( ) and button_click( ) methods are eligible to be wrapped inside the delegate
object, because prototypes of both the methods match the prototype mentioned in the delegate
declaration.

In Main( ) we have created an object of the MyForm1 class resulting in the constructor being
called. In the constructor we have stored the address of the MyForm1_click( ) method in the
reference c1. Thus, c1 delegates (represents) the method MyForm1_click( ). Next we have
called the mouseclick( ) method which in turn calls the MyForm1_click( ) method via c1.

The next statement in the constructor makes c1 to refer to the static method and hence a call to
the mouseclick( ) method results in calling the static method.

This program was a little odd but it would help you to understand the event-handling model of
WinForms programming in C#.

Multiple Methods In A Delegate

A delegate can wrap even more than one method. For this, it maintains a linked list. The delegate
then points to the head of such a linked list. This means that when such a delegate is invoked it
calls all the methods that form the linked list.

Hence, instead of the statements

c1 = new click ( MyForm1_click ) ;


mouseclick( ) ;
c1 = new click ( button_click ) ;
mouseclick( ) ;

we can simply write

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

c1 += new click ( MyForm1_click ) ;


c1 += new click ( button_click ) ;
mouseclick( ) ;

The delegate c1 inside the mouseclick( ) method would now call both the methods. Here we are
simply adding both the methods in a list and hence both would be called. Rest of the program
remains same.

Events

As said earlier, the Windows GUI programming requires that the program must respond to
events. An event in C# is a multicast delegate having a predefined prototype. The prototype is
such that every event (actually a multicast delegate) would, by convention return a void and
always accept two parameters. The first parameter is always a reference to an object of
System.Object class and the second parameter is always a reference to an object of the
System.EventArgs class or a class derived from it. The EventArgs object contains information
about the event.

The object that raises an event is called an 'event raiser' and the object that receives an event is
called an 'event receiver'. Whenever an event is raised a method is called that handles the event
(hence called an event handler). The event raiser class always declares the event and the
receiver class must have an event handler to handle that event. The first parameter collected by
the event handler is always a reference to an event raiser object. The addresses of event
handlers are stored inside the events (remember that events are actually delegates) and hence
they also must have the same signature as the event. Such kind of a delegate is declared using
the keyword event.

Article: C# - Events And Delegates - II

Continued from last week...

To understand events, consider the following program:

using System ;
namespace Sample
{
public class mouseeventargs
{
public int x, y ;
public mouseeventargs ( int x1, int y1 )
{
x = x1 ;
y = y1 ;
}
}

public delegate void click ( object m, mouseeventargs e ) ;

public class MyForm


{
public event click c1 ;
public void mouseclick( )
{

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

mouseeventargs m = new mouseeventargs ( 10, 20 ) ;


c1 ( this, m ) ;
}
}
class MyForm1 : MyForm
{
public MyForm1( )
{
c1 += new click ( button_click ) ;
mouseclick( ) ;
}

static void Main ( string[ ] args )


{
MyForm1 f = new MyForm1( ) ;
}

public void button_click ( object m, mouseeventargs e )


{
Console.WriteLine ( "Mouse Coordinates: " + e.x + " " + e.y ) ;
Console.WriteLine ( "Type is: " + m.GetType( ).ToString( ) ) ;
}
}
}

The output of the program would be

Mouse Coordinates: 10 20
Type is: Sample.MyForm1

In this program we have declared 3 classes-mouseeventargs, MyForm and MyForm1 derived


from MyForm. The mouseevntargs class corresponds to the EventArgs class. This class
contains two int variables x and y and a constructor to initialize them. We have declared a
multicast delegate click whose signature is same as the event handler button_click( ). The
MyForm class here is an event raiser class and hence contains an event as a data member
called c1 of the type click. It also contains a method called mouseclick( ). In this method we
have created an object of the mouseeventargs class. In the statement,

c1 ( this, m ) ;

c1 represents (is a delegate for) button_click( ). this contains the reference of MyForm object
(event raiser) and m is a reference of the mouseeventargs object. In the MyForm1 class, we
have defined the method button_click( ) (i.e. event handler). When the compiler encounters the
statement

c1 += new click (button_click)

it creates an event object (delegate object) that wraps up button_click( ) method. So whenever
the c1 event is raised (or called, as in this program), the method button _click( ) will get
executed.

Now back to WinForms. WinForms event handling model follows the same arrangement that we
discussed above. The difference is that Event programming in WinForms is very easy and we
need not think about these underlying concepts every time. The Wizard automatically generates

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

code for us and we have to just write logic in the event handlers.

Let's take a look at what the wizard generates for us every time we add an event handler to our
form. Create a 'Windows Application' which should display a message box when the user clicks
on the form. The following code would get generated.

using System ;
using System.Windows.Forms ;

namespace SampleClick
{
public class Form1 : System.Windows.Forms.Form
{
public Form1( )
{
InitializeComponent( ) ;
}

#region Windows Form Designer generated code


private void InitializeComponent( )
{
this.Click += new System.EventHandler ( this.Form1_Click ) ;
}
#endregion

static void Main( )


{
Application.Run ( new Form1( ) ) ;
}

private void Form1_Click ( object sender, System.EventArgs e )


{
MessageBox.Show ( "Hello C#" ) ;
}
}
}

We have erased the comments and some extra code added by the wizard for the sake of clarity.
We just have to type the code which is given in bold letters above and compile the program. On
executing the program and clicking on the form we get the output as shown in Figure 1.

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

Figure 1

Here, Click is a reference to an event of the type System.EventHandler and is already defined
in the System.Windows.Form class. Realize that System.EventHandler is a delegate used to
wrap an event handler. A delegate that dispatches an event is called an 'event delegate'. The
event handler Form1_Click( ) is wrapped inside the Click event. This method is written in the
Form1 class and it accepts two references. One of them is of object type and contains reference
of the event raiser (Form1 here) and the other is of type EventArgs.

Here we have not written any statement to explicitly raise the event Click( ). Whenever the user
clicks on the form the .NET runtime raises this event for us. .NET runtime then informs the base
class, Form about this event. The Form class would call the event handler using the statement
like

Click ( reference of sender, reference of EventArgs ) ;

Here, Click represents (is a delegate for) Form1_Click( ) event handler. And so, this statement
would call the Form1_Click( ) handler.

Article: C# - Properties And Indexers - I

Bashing Structured paradigm and glorifying OO has been the computing industry's favourite past
time for almost a decade now. OO programming has also grown old now. Today is the era of
modern OO languages, which take the OO paradigm further. Properties, indexers and events are
first class citizens of modern OO languages like C#.

Nothing great if C# supports encapsulation, inheritance and polymorphism. It being an OO


language this was expected of it. It being a modern OO language, it supports features like
properties, events, indexers, delegates etc. Of these this article would cover properties and
indexers.

Properties

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

Properties of a class are actually methods that work like data members. We have already used
the Length property of the System.Array and System.String class in an earlier article. The
properties are used to store and retrieve the values to and from the data members of the class.
For example, to store and retrieve the length data member of the string class the Length property
is used. Conventionally the data members are given names starting with a lower case letter and
the corresponding properties are given names starting with a capital letter.

Manipulating data using properties is done through two special methods known as accessors.
There can be two accessors: a get accessor and a set accessor. The following code shows both
of them.

using System ;
namespace properties
{
public class sample
{
int length ;
public int Length
{
get
{
return length ;
}
set
{
length = value ;
}
}
}

class Class1
{
static void Main ( string[ ] args )
{
sample m = new sample( ) ;

m.Length = 10 ;
int len = m.Length ;
Console.WriteLine ( "Length: " + len ) ;
}
}
}

Here we intend to access and modify the length data member of the sample class. Since it is of
the type int we have used public int Length to declare the property to be of the type int. As a
result, the get accessor would return an int type and the set accessor would collect the int type.
The get accessor never accepts any value and the set accessor never returns any value. The
value collected by the set accessor is stored in an implicit parameter called value. value is a
keyword and would always have a type corresponding to the property. We should be careful not
to give any data member a name value. The statement m.Length = 10 would invoke the set
accessor automatically. The statement int len = m.Length would invoke the get accessor
automatically.

In general the get accessor is invoked when we want to retrieve the value of the property,
whereas the set accessor is invoked when we assign a value to the property. We cannot explicitly

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

call the accessors using the get and set keywords.

If only get accessor is present the property is called a read only property. If only set accessor is
present then the property is called a write-only property. If both accessors are present, the
property is said to be a read-write property. If we write a statement,

m.Length = m.Length + 20

both the get and set accessors would get called. When the addition operation is performed the
get accessor would get called. The get accessor will return the value of length. Next 20 would be
added to it. Now using the set accessor, the resulting value would be assigned to length.

A Few Subtleties

Let us now look at a few subtleties associated with accessors:

a. The advantage of using properties as against public data member is that if we want, we
can perform some functionality in the accessor body. For example, we can check range
for the length variable in the set accessor as shown in the following code snippet.

set
{
if ( value > 10 )
length = value ;
}

b. If we derive a class from a base class which has a public property declared in it, the
object of the derived class can also access the property of the base class. If the property
of the base class is declared as virtual the derived class can override the base class
property with its own version of the property.
c. Properties can also be declared abstract. If we declare the property as abstract, it is
necessary to declare the class containing the property as abstract. Since we cannot
create the objects of the abstract class, it becomes necessary to derive a class from it
and implement the property. For example, in the following program the class dimensions
has one abstract property Height.

public abstract class dimensions


{
protected int height ;

public abstract int Height


{
get ;
set ;
}
}

To declare the property abstract we have to write the get and set keywords without any accessor
body. The derived class must implement the property as shown below.

public class window : dimensions


{
public override int Height
{

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

get
{
return height ;
}
set
{
height = value ;
}
}
}

d. The static modifier can be used to create properties that belong to a class and not to an
individual object. We can write static properties for static data members only. To access
these properties we have to use the class name instead of an object. For example,

using System ;
namespace sample
{
public class window
{
static int height ;
public static int Height
{
get
{
return height ;
}
set
{
height = value ;
}
}
}
class Class1
{
static void Main ( string[ ] args )
{
window.Height = 10 ;
Console.WriteLine ( "Window height: " + window.Height ) ;
}
}
}

e. A class can contain multiple properties.

Article: Properties And Indexers- II

Continued from last week...

Indexers

An Indexer is a special type of property. If a class contains an array as a data member, an


indexer lets us access the array within the class using an object as though the object itself were
an array. This is done using the [ ] operator. For example, consider a class myclass which has an

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

int array as a data member and we create an object a of that class. Here we can access the
elements of the array by using the expressions a[0], a[1], a[2] and so on. The following code
snippet shows how to declare an indexer:

public int this [ int index ]


{
get
{
// code
}
set
{
// code
}
}

Like properties we use the get and set accessors in indexers. The difference between a property
and an indexer is that an indexer is nameless. This means it does not have a name like Height,
Length, etc. instead the this keyword is used to declare an indexer. The this reference refers to
the object we are indexing. The first int in the indexer declaration specifies type of the array. The
second int within the square brackets specifies the type of argument we would be using to index
into an array. The following example shows how we can make an object behave like an array:

using System ;
namespace sample
{
public class array
{
float[ ] arr = new float [ ] { 12.5f, 34.3f, 5.2f, 6.1f, 7.5f, 88.8f, 22.9f } ;

public float this [ int index ]


{
get
{
return arr [ index ] ;
}
set
{
arr [ index ] = value ;
}
}
}

class Class1
{
static void Main ( string [ ] args )
{
array a = new array( ) ;
a [ 3 ] = 43.2f ;
Console.WriteLine ( a [ 3 ] ) ;
}
}
}

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

Here arr is a float array and it belongs to the same class in which we have declared the indexer.
When we write the statement a [ 3 ] = 43.2f the set accessor gets called. The index 3 would get
collected in the variable index and 43.2f would get collected in the variable value. When we write
the statement,

Console.WriteLine ( a [ 3 ] ) ;

the get accessor gets called. The index 3 would get collected in the variable index and the
element at fourth place would be returned.

We can also declare an indexer for a multi-dimensional array. In the following program we have
used two indexers one for 1D array and another for 2D array. Such indexers are known as
overloaded indexers.

using System;
namespace sample
{
public class array
{
int [ ] arr1 = new int [ ] { 12, 34, 5, 6, 7, 88, 22 } ;

int [ , ] arr2 = new int [ , ] {


{ 12, 34, 5, 6 },
{ 7, 88, 22, 2 }
};
public int this [ int index ]
{
get
{
return arr1 [ index ] ;
}
set
{
arr1 [ index ] = value ;
}
}

public int this [ int index1, int index2 ]


{
get
{
return arr2 [ index1,index2 ] ;
}
set
{
arr2 [ index1,index2 ] = value ;
}
}
}

class Class1
{
static void Main ( string[ ] args )
{

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

array a = new array( ) ;


a [ 3 ] = 43 ;
a [ 0, 2 ] = 89 ;
}
}
}

The two int variables specified within brackets in the statement,

public int this [ int index1, int index2 ]

Specify the two indexes used to access an element of the 2D array. When we write i [ 3 ] = 43 ,
the set accessor with one argument gets called and when we write i [ 0, 2 ] = 89, the set
accessor with two arguments gets called. It is not possible to write indexers for jagged arrays
because a statement such as public int this [ int index1] [ int index2 ] is an error.

Lastly, indexers can not be declared as static. Indexers work in the same way as properties when
declared as virtual.

Article: C# - Arrays And Strings - I

Arrays and Strings are perhaps as old as programming languages themselves. They have been
around for so long that they are almost taken for granted. Don't make this mistake while learning
C#. In C# they are different and more powerful. That's bound to happen when a language is
developed from ground up without being required to shoulder the responsibility of backward
compatibility…

An array is a collection of similar elements stored in adjacent memory locations. These similar
elements could be all ints, all floats, all chars, etc. For example,

int[ ] arr1 = { 1, 2, 3 } ;
float[ ] arr2 = { 1.5f, 2.5f, 3.5f } ;
char[ ] arr3 = { 'a', 'b', 'c' } ;

All elements of an array must be of the same type, i.e. we cannot have an array of 10 numbers, of
which 5 are ints and 5 are floats. Arrays in C# are reference types and are implemented as
objects. They are derived from the abstract class System.Array. The following code shows how
to declare references to an int array:

int[ ] a ; // declare an int array reference


int[ ] a1, a2 ; // declare two array references

Here a, a1, a2 are references to an int array. Thus we are not declaring an array. Instead, we are
declaring a reference to it. This merely sets aside space for reference to an array. Once we have
declared an array reference, we can construct an array through the statement:

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

a = new int [ 5 ] ;

Following figure shows how the array and reference would appear in memory:

To initialize an array we need to write the following statement:

int[ ] arr1 = new int[ ] { 3, 5, 7, 9, 1 } ;

Or

int[ ] arr1 = { 3, 5, 7, 9, 1 } ;

Here the array gets allocated on the heap and all its elements store a value. By default, all the
elements of this array are initialized with a value 0. We can also create an array of objects. This is
explained with an example,

sample[ ] s = new sample [ 5 ] ;

Here s is a reference to an array of references. The array gets created on the heap. Each
element of the array in itself is a reference to the sample object. Hence, each reference would
hold address of an object and not its value. By default, all the elements are initialized with a null
reference. The in-memory view of the array is shown below:

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

To assign the array element with the addresses of the objects we need to write the following
statements:

s [ 0 ] = new sample ( 1 ) ;
s [ 1 ] = new sample ( 2 ) ;
s [ 2 ] = new sample ( 3 ) ;
s [ 3 ] = new sample ( 4 ) ;
s [ 4 ] = new sample ( 5 ) ;

Or

sample s[ ] = {
new sample ( 1 ),
new sample ( 2 ),
new sample ( 3 ),
new sample ( 4 ),
new sample ( 5 ),
}

Like C and C++, C# also uses a zero-based scheme to access array elements. This means that
the first element in the array is considered to be at 0th position.

Multidimensional Arrays

In C# multidimensional arrays are of two types - Rectangular and Jagged. C# has a different
syntax for both.

Rectangular Arrays

In rectangular arrays every row of the array is of the same length. This means if we have a two-

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

dimensional array, all the rows will have same number of elements. This property is similar to
arrays in C or C++. The following code snippet will give you an idea about rectangular arrays:

int [ , ] arr1 = new int [ , ] { { 3, 5, 7, 9 }, { 11, 13, 15, 17 } } ;

Or

int [ , ] arr1 = { { 2, 4, 6, 8 }, {10, 12, 14, 16 } } ;

To print the elements of the rectangular array we need to write the following code:

foreach ( int i in arr1 )


Console.Write ( i + " " ) ;

The foreach loop allows us to iterate through each item in an array. The foreach loop always
travels through all elements of one row before moving to the next row. Using foreach we can
never travel through a 2-D array column by column.

Jagged Array

A jagged array is an array of several 1D arrays each of different length. We cannot create the
jagged array in the same way as we created the rectangular array. Suppose we are required to
create a jagged array containing 2 rows where first row contains four integers and the second row
contains 2 integers. We may try to define this array as follows:

int [ , ] arr1 = new int [ , ] { { 3, 5, 7, 1 }, { 11, 13 } } ;

Or

int [ , ] arr1 = { { 3, 5, 7, 1 }, { 11, 13 } } ;

Both these definitions are wrong, because the number of elements in each row is different and
the complier never keeps track of how many elements are present in each row. Hence later on it
would not be feasible for it to access the correct element when we use an array access
expression, like arr [ 1, 2 ]. The correct way to initialize the jagged array is as follows:

int[ ] [ ] arr1 = new int [ 2 ] [ ] ;


arr1 [ 0 ] = new int [ 3 ] { 3 , 5, 7, 1 } ;
arr1 [ 1 ] = new int [ 2 ] { 11, 13 } ;

The in-memory view of this jagged array is as follows:

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

The way to create a 3D jagged array is as follows:

int[ ] [ ] [ ] arr = new int [ 2 ] [ ] [ ] ;


arr [ 0 ] = new int [ 3 ] [ ] ;
arr [ 0 ] [ 0 ] = new int [ 3 ] ;
arr [ 0 ] [ 1 ] = new int [ 4 ] ;
arr [ 0 ] [ 2 ] = new int [ 5] ;

Here the 3D array consists of two 2D arrays. The first 2D array would consist of three 1D arrays,
and finally all the three 1D arrays have different number of elements.

From the above discussion it is clear that in a rectangular array all indices are within one set of
brackets. for a jagged array each element is within its own bracket. For a 2D rectangular array we
have to write int [ , ] whereas, for a 2-D jagged array we have to write int[ ][ ].

Article: C# - Arrays And Strings - II

Continued from last week...

The System.Array type

The System.Array class automatically becomes the base class of any type of array. Hence we
can store the reference to an array into the reference to the System.Array class. Unlike in C or
C++, the .NET runtime performs bounds checking on all arrays and throws a
System.IndexOutOfRangeException when the bounds of array are exceeded.

The array class provides methods for creating, manipulating, searching, and sorting arrays. The
following programs illustrate usage of some of the System.Array methods.

using System ;
class onedarray
{
static void Main ( string[ ] args )
{
int[ ] arr1 = new int [ 5 ] { 1, 4, 7, 8, 9 } ;
int[ ] arr2 = new int [ 10 ] ;

arr1.CopyTo ( arr2, 0 ) ;
Console.WriteLine ( "Elements of arr2: " ) ;
foreach ( int i in arr2 )
Console.Write ( i + " " ) ;

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

Console.WriteLine( ) ;

arr2.SetValue ( 5, 0 ) ;
Console.WriteLine ( "Elements of arr2: " ) ;
foreach ( int i in arr2 )
Console.Write ( i + " " ) ;
Console.WriteLine( ) ;

Console.WriteLine ( "Number of elements in arr1:" + arr1.Length ) ;


Console.WriteLine ( "Number of elements in arr2:" + arr2.Length ) ;

Array.Copy ( arr1, 2, arr2, 6, 2 ) ;


Console.WriteLine ( "Elements of arr2: " ) ;
foreach ( int i in arr2 )
Console.Write ( i + " " ) ;
Console.WriteLine( ) ;

Array.Reverse ( arr2 ) ;
Console.WriteLine ( "Elements of arr2: " ) ;
foreach ( int i in arr2 )
Console.Write ( i + " ") ;
Console.WriteLine( ) ;

Array.Sort ( arr2 ) ;
Console.WriteLine ( "Elements of arr2: " ) ;
foreach ( int i in arr2 )
Console.Write ( i + " " ) ;
Console.WriteLine( ) ;

Console.WriteLine ( "Index of 8 is " + Array.IndexOf ( arr2, 8 ) ) ;

Array.Clear ( arr2, 3, 3 ) ;
Console.WriteLine ( "Elements of arr2: " ) ;
foreach ( int i in arr2 )
Console.Write ( i + " " ) ;
Console.WriteLine( ) ;
}
}

In this program we have created two one-dimensional int arrays called arr1 and arr2. We have
then initialized arr1 with 5 elements and left arr2 uninitialized. The compiler will, hence, initialize
arr2 with zeros (i.e. the default value for int types). The CopyTo( ) method is used to copy
elements from arr1 to arr2 starting from index 0. Using the foreach loop we have printed the
elements in arr2. The output would be,

Elements of arr2:
1478900000

Since we have copied the first five elements from arr1 into arr2 the rest of the elements remain
zero. The SetValue( ) method sets a value ( mentioned as the first parameter ) in an array at a
specified index ( specified by the second parameter). Here we have set the 0th element in arr2 to
value 5. After setting the value we get the output as follows:

Elements of arr2:
5478900000

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

Length is a property that specifies the total number of elements in an array. Properties are similar
to methods and are used to manipulate data. The Length of arr1 in our program is 5, whereas,
the Length of arr2 is 10. The Copy( ), Reverse( ), Sort( ), and Clear( ) methods are static
methods of the System.Array class. The Copy( ) method is used to copy a group of elements
from one array to another. This method has two overloaded versions, which are as follows:

public static void Copy ( Array, Array, int )

and

public static void Copy ( Array, int, Array, int, int )

The first version accepts a reference to the source array, a reference to the destination array and
number of elements to be copied. The second version accepts a reference to the source array,
the index in the source array from where copying should begin, a reference to the destination
array, the index in destination array from where elements should be stored and lastly the number
of elements to be copied. We have used the second version in our program. We have specified
that copying should start from element at index 2 in arr1. The elements should be copied from the
6th index in arr2 and in all 2 elements should be copied. After this operation the output is as
follows:

Elements of arr2:
5478907800

The Reverse( ) method reverses the elements of an array. It has one more overloaded version
that accepts a reference of an array to be reversed, the index from where the reverse operation
should begin and the number of elements to be reversed starting from the index specified as the
second parameter. The result of this operation is shown below.

Elements of arr2:
0087098745

The Sort( ) method sorts the array in an ascending order. If we want the array to be sorted in the
descending order we would have to sort it and then reverse it. After sorting the array we would
get the following result:

Elements of arr2:
0004577889

The IndexOf( ) method returns the index of a given element in an array. In our program we have
printed the index of element 8, which happens to be 7. If 8 occurs more than once in the array
then the index of the first would be returned. The Clear( ) method clears all the elements in an
array from an index specified as the first parameter. We also have to specify the number of
elements to be cleared as the second parameter. If the elements are of value types they get
reinitialized to zeros, whereas, if they are of reference types they get reinitialized to null. The
result is as follows:

Elements of arr2:
0000007889

Let us now see how to apply the functions provided by the System.Array class on a rectangular
2D array.

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

using System ;
class rectarray
{
static void Main ( string[ ] args )
{
int [ , ] arr1 = new int [ 2, 3 ] { { 1, 2, 3 }, { 4, 5, 6 } } ;
int [ , ] arr2 = new int [ 2, 3 ] ;

Console.WriteLine ( " Elements of arr1: " ) ;


for ( int i = 0 ; i <= arr1.GetUpperBound ( 0 ) ; i++ )
{
for ( int j = 0 ; j <= arr1.GetUpperBound ( 1 ) ; j++ )
Console.Write ( arr1 [ i, j ] + " " ) ;
Console.WriteLine( ) ;
}

Console.WriteLine ( "Number of elements in arr1: " + arr1.Length ) ;

Array.Copy ( arr1, 2, arr2, 2, 3 ) ;


Console.WriteLine ( " Elements of arr2: " ) ;
foreach ( int i in arr2 )
Console.Write ( i + " " ) ;
arr2.SetValue ( 5, 0, 1 ) ;
Console.WriteLine ( " Elements of arr2: " ) ;
foreach ( int i in arr2 )
Console.Write ( i + " " ) ;
Array.Clear ( arr2, 0, arr2.Length ) ;
Console.WriteLine ( " Elements of arr2: " ) ;
foreach ( int i in arr2 )
Console.Write ( i ) ;
}
}

In the above program we have created two rectangular 2D arrays arr1 and arr2 both having 2
rows and 3 columns. We have initialized arr1 with 6 elements and left arr2 uninitialized. Hence,
the compiler will initialize arr2 with zeros. To print the elements in a matrix format we have used
two nested for loops instead of foreach. The GetUpperBound( ) method gives index of the last
row if 0 is specified as its parameter, hence we would get 1. If 1 is specified it would return us the
index of the last column, hence we would get 2. The output after this loop is as follows:

Elements of arr1:
123
456

The Length property has a value 6 as there are totally 6 elements in arr1. The Copy( ) method
works in the same way for a 2D array as it works for a 1D array. After the copy operation we
would get the output as shown below.

Elements of arr2:
003450

The SetValue( ) method that operates on a 2D array accepts the value to be set followed by two
ints specifying indices for each dimension in the array. Likewise, the System.Array class
provides an overloaded version for a 3D array, which accepts 3 indices. For an array with

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

dimensions more than 3, an array has to be created, filled with indices and passed to the
SetValue( ) method as the second parameter.

Let us now see how the methods in System.Array can be applied to a jagged 2D array.

using System ;
class jaggedarray
{
static void Main ( string[ ] args )
{
int [ ][ ] arr1 = new int [ 2 ] [ ] ;
arr1 [ 0 ] = new int [ 3 ] { 1, 2, 3 } ;
arr1 [ 1 ] = new int [ 2 ] { 4, 5 } ;

Console.WriteLine ( "Elements of arr1: " ) ;


for ( int i = 0 ; i < arr1.Length ; i++ )
{
for ( int j = 0 ; j < arr1[ i ].Length ; j++ )
Console.Write ( arr1 [ i ] [ j ] ) ;
Console.WriteLine( ) ;
}
}
}

In this program we have created a jagged two-dimensional array called arr1. arr1[0] has 3
elements while arr1[1] has 2 elements. We have printed the entire array using two nested for
loops. We cannot use a foreach loop on jagged arrays because the number of elements in each
1D array of a jagged array is not same. Now as a jagged array is considered to be an array of 1D
arrays, all the methods that we called on 1D arrays can be called on each 1D array that make up
a jagged array.

Article: C# - Arrays And Strings


- III

Continued from last week...

Strings

The string type is a predefined data type in C# and is an alias of the System.String class.
Hence they can be used interchangeably. Instances of the string type represent Unicode
character strings. The following statement shows how to assign a value to a string object:

string s = "Hello" ;

Here a reference s gets created on the stack while the object referred to by s gets created on the
heap. C# supports two types of string variables, quoted and @-quoted. Quoted strings are
normal strings that support escape sequences. If we do not want the compiler to process escape
sequences we can use an @-quoted string. These strings are formed by prefixing the string with
an '@' symbol. The main advantage of an @-quoted string is that, it simplifies the expression of
path names. For example,

string s2 = @"C:\Articles\text.txt" ;

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

If @ symbol is not prefixed to this string then, its necessary to replace each '\' with '\\'. But the
string shown below cannot be prefixed by the @ symbol if we want that the escape sequence
should be processed.

string s1 = "hi \t there" ;

Whenever the compiler sees a '\t', it prints out a tab. Hence the output would become,

hi there

When we use an assignment operation between two reference variables, the reference to the first
object gets copied into the other reference variable. But this is not the case with strings. In spite
of being a reference type an assignment operation on two string variables results in creation of a
new object. The value of the right-hand side string object gets copied into the new object and the
reference to this new object gets assigned to the reference variable on the left-hand side of the
assignment operator. This is shown in the following example.

using System;
namespace sample
{
class Class1
{
static void Main ( string[ ] args )
{
string s1 = "Good Morning" ;
string s2 ;
s2 = s1 ;
s1 = "Wake Up" ;
Console.WriteLine ( s1 ) ;
Console.WriteLine ( s2 ) ;
}
}
}

The output of the program would be,

Wake up
Good Morning

In this program we have created two string references - s1 and s2. We have initialized s1 with a
reference to an object containing "Good Morning" and kept s2 uninitialized. Then we have
assigned s1 to s2. Normally both being references only the reference should have assigned to
s1. But this does not happen. Instead a new object gets created that holds the same value
contained in the object referred by s1.

Like System.Array, System.String class too defines various methods to perform routine
operations on strings. The following programs illustrate use of the System.String methods.

using System ;
namespace sample
{
class Class1
{

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

static void Main ( string[ ] args )


{
string s1 = "kicit" ;
string s2 = "Nagpur" ;
Console.WriteLine ( "Char at 3rd position: " + s1 [ 2 ] ) ;

string s3 = string.Concat ( s1, s2 ) ;


Console.WriteLine ( s3 ) ;
Console.WriteLine ( "Length of s3: " + s3.Length ) ;

s3 = s3.Replace ( 'p', 'P' ) ;


Console.WriteLine ( s3 ) ;

s3 = string.Copy ( s2 ) ;
Console.WriteLine ( s3 ) ;

int c = s2.CompareTo ( s3 ) ;
if ( c < 0 )
Console.WriteLine ( "s2 is less than s3" ) ;
if ( c == 0 )
Console.WriteLine ( "s2 is equal to s3" ) ;
if ( c > 0 )
Console.WriteLine ( "s2 is greater than s3" ) ;
if ( s1 == s3 )
Console.WriteLine ( "s1 is equal to s3" ) ;
else
Console.WriteLine ( "s1 is not equal to s3" ) ;
s3 = s1.ToUpper( ) ;
Console.WriteLine ( s3 ) ;

s3 = s2.Insert ( 6, "Mumbai" ) ;
Console.WriteLine ( s3 ) ;

s3 = s2.Remove ( 0, 1 ) ;
Console.WriteLine ( s3 ) ;

int fin = s1.IndexOf ( 'i' ) ;


Console.WriteLine ( "First index of i in s1: " + fin ) ;

int lin = s1.LastIndexOf ( 'i' ) ;


Console.WriteLine ( "Last index of i in s1: " + lin ) ;

string sub = s1.Substring ( fin, lin ) ;


Console.WriteLine ( "Substring: " + sub ) ;

int i = 10 ;
float f = 9.8f ;
s3 = string.Format ( "Value of i : {0} \nValue of f : {1}", i, f ) ;
Console.WriteLine ( s3 ) ;
}
}
}

In this program we have created two string variables s1 and s2 and initialized them to "kicit" and
"Nagpur" respectively. The [ ] operator accesses individual characters of a string. Hence to
access the 3rd character we have to write s1[ 2 ] which in the string s1 happens to be character

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

'c'.

The Concat( ) method is a static method which concatenates two strings and returns a new
object which gets stored in s3. Hence the object referred to by s3 would contain "kicitNagpur".
The Length property of a string returns the number of characters in a string. The length of s3 in
our program is 11. The Replace( ) method replaces all the instances of a character ( mentioned
as the first parameter) with the character given as the second parameter. Here we have replaced
'p' with a 'P' in string referred to by s3.

The Copy( ) method is a static method that copies all the characters from one string object to
another. If the destination string is smaller in length, its length is increased automatically.

The CompareTo( ) method compares two strings alphabetically. This means a string with a
starting alphabet 'a' will always be lesser than a string with starting alphabet as 'b'. This method
returns a negative integer if the string object that has called the CompareTo( ) method contains a
string which is lesser than the string contained in the object whose reference is passed as the
method's parameter. It returns a positive number if the string objects are interchanged. It returns
zero when both strings are equal.

In the same way the == operator compares two strings and returns a bool - true if the strings are
equal and false if they are not.

The ToUpper( ) method creates a new object, stores in it the converted upper case string and
returns the address of this object. This address is collected in s3. Note that s1 is not affected
here. Hence we can draw a conclusion that the object which we use to call the methods to
manipulates the string, does not affect the object.

The Insert( ) method inserts a string specified as the second parameter at the index specified as
the first parameter. Here too s1 does not get affected and the returned string is collected in s3.
So we get "NagpurMumbai" in s3.

In the Remove( ) method two arguments are passed. The first parameter is an index from where
we wish to remove elements and the second parameter is the total number of elements to be
removed. We have passed 0 and 1 meaning we wish to remove only the 0th element from s3. So
the string s3 would now contain "agpur".

The IndexOf( ) method returns the index of first occurrence of a given character in the string.
Similarly, LastIndexOf( ) method returns the index of last occurrence of a given character in the
string. In our program the first index of 'i' happens to be 1 whereas the last index is 3.

The Substring( ) method returns a new string which starts at an index passed as the first
parameter and ends at an index passed as the second parameter to the method.

The Format( ) method replaces the format specifiers (such as {0}, {1}, etc.) into string
representations. This is a static method that returns the formatted string.

An important point to note is that the == operator is case insensitive. The Compare( ) and
CompareTo( ) methods are two different methods in the string class. Compare( ) is a static
method while CompareTo( ) is not. The Compare( ) method can be made case insensitive by
passing true as the last parameter. Here's a code snippet that illustrates this.

string str1 = "hello" ;`


string str2 = "HELLO" ;
bool chk1 = ( str1 == str2 ) ; //returns false
int chk2 = ( String.Compare ( str1, str2, true ) ) ; // returns 0

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

A Few Subtleties

Till now we have printed values using the WriteLine( ) method. What about taking the input from
the user? The Console class provides a method ReadLine( ) that accepts a complete line
entered (including spaces) by the user on the console. Then what about integers and floats? The
same ReadLine( ) method can be used to accept numbers too. But it returns numbers in the form
of a string object. The following program demonstrates how these numbers can be converted
back to their numeric values:

using System ;
namespace sample
{
class Class1
{
static void Main ( string[ ] args )
{
Console.WriteLine ( "Enter an integer: " ) ;
string s = Console.ReadLine( ) ;
int i = int.Parse ( s ) ;

Console.WriteLine ( "Enter a float: " ) ;


s = Console.ReadLine( ) ;
float f = float.Parse ( s ) ;

float t = f + i ;
Console.WriteLine ( t ) ;
}
}
}

In this program firstly we have used the ReadLine( ) method to accept an integer from the
console. Then using the int data type (which is an alias of Int32 structure defined by .NET) we
have called a static method Parse( ) of the Int32 structure. This method converts a string to an
integer. Likewise, to convert a string to a float we have called the static method Parse( ) of the
structure Single (of which the float data type is an alias).

The numeric values can also be converted to strings. The following code snippet demonstrates
how integers and floats can be converted to a string:

int i = 10 ;
float f = 3.14f ;

Console.WriteLine ( "Integer to String : " + i.ToString( ) ) ;


Console.WriteLine ( "Float to String: " + f.ToString( ) ) ;

Here ToString( ) method is a non-static method of the structures Int32 and Single.

There is one more way in which we can convert numbers to strings. This is as follows:

string s = string.Format ( "Value of i: {0} \nValue of f: {1}", i, f ) ;


Console.WriteLine ( s ) ;

Here the Format( ) method is a static method of the String class.

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

Article: C# - Management By Exception - I

Exception Handling

Errors. Innocent errors. Silly errors. Fatal errors. Not so fatal errors. Performing errors is
programmer's birthright. A typical programmer spends as much time in fixing errors as in
programming. Different mechanisms have evolved to tackle these errors. Exception handling is
the latest in the list.

What is common amongst different programmers using widely varying languages? Their ability to
create errors in the programs. Programmers of all kind are error prone. We can categorize the
errors, that they perform, into 3 broad categories:

(a) Grammatical/Syntax errors


(b) Linker errors
(c) Run-time errors

Syntax errors occur only when syntax goes wrong. If the syntax goes wrong then it's the compiler,
which reports the errors to us. Unless we correct these errors we cannot build the executable file
of our program. Linker error occurs when we try to access some library function and for some
reason or the other the function cannot be found. Most dangerous of these errors are the runtime
errors. Runtime errors mean errors which occur at the time of execution of the program. Such
errors are known as exceptions. Tackling these errors is the programmer's job. The reasons why
exceptions occur are numerous. Some of the more common reasons are:

(a) Falling short of memory


(b) Dividing a value by zero
(c) Inability to open a file
(d) Exceeding the bounds of an array
(e) Attempting to initialize an object to an impossible value

When such exceptions occur, the programmer has to decide a strategy according to which he
would handle the exceptions. The strategies could be, displaying the error messages on the
screen, or displaying a dialog box in case of a GUI (Graphic User Interface, for example,
Windows) environment, or requesting the user to supply better data or simply terminating the
program execution.

In non-object oriented programming languages exceptions are dealt by following the function calls
with error checks on return values to find whether the function did its job properly or not. In C
programs a function usually returns an error value if an error occurs during execution of that
function. For example, file-opening functions return a NULL indicating their inability to open a file
successfully. Hence, each time we call these functions we can check for the return value. This is
shown for some fictitious functions fun1( ), fun2( ) and fun3( ) in the following code:

if ( func1( ) == ERROR_VALUE )
// handle the error
else
// do normal things

if ( func2( ) == NULL )
// handle the error
else
// do normal things

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

if ( func3( ) == -1 )
// handle the error
else
// do normal things

There are three problems with this approach:

(a) Every time we call a function we must check its return value through a pair of if and else.
Easier said than done!
Surrounding every function call with a pair of if and else results in increase in code size. Also,
too many if - elses
make the listing lose its readability.
(b) This approach cannot be used to report errors in the constructor of a class, as the constructor
cannot return a value.
(c) It becomes difficult to monitor the return values in case of deeply nested function calls.
Especially so, if the functions
belong to a third-party library.

C# uses a more systematic approach to tackle exceptions. The .NET CLR checks for the runtime
errors and raises exceptions to inform the program that an error has occurred. It also handles
these exceptions if the program has not handled it. In C# the exceptions are in the form of objects
of exception classes. All exception classes are derived from the System.Exception class. An
exception object cannot be "thrown" or "caught" unless their classes are inherited from the
System.Exception class. When we say an exception is thrown, it means that the CLR creates an
object of the class on heap and passes its reference to the program. There are several standard
exceptions provided by the .NET framework. We can also create user-defined exceptions. The
exception thrown by the code written in one .NET compliant language can be caught in another
.NET compliant language.

We can handle exceptions in C# using the following:

a. The try block followed by one or more catch blocks.


b. The try-catch blocks followed by finally block.

Let us understand each of them.

The try-catch Blocks

The try block contains code expected to raise an exception. The code in the try block executes
until a statement which raises an exception is encountered. When an exception is encountered,
the program flow shifts to the catch block. The catch block handles the exception by executing
the code written in it. For example,

using System;

namespace Sample
{
class Class1
{
static void Main ( string [ ] args )
{
int a, b = 0 ;
try
{

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

a = 10 / b ;
}
catch ( DivideByZeroException e )
{
Console.WriteLine ( e ) ;
}
Console.WriteLine ( "Remaining program" ) ;
}
}
}

Here a 'divide by zero' exception is raised. The CLR creates an object of


DivideByZeroException class and passes it to the catch block that accepts a reference to the
DivideByZeroException object. We have then printed the exception by passing the reference e
to the WriteLine( ) method. The output of the above program would be:

System.DivideByZeroException: Attempted to divide by zero.


at Exceptiontest.Class1.Main(String[] args) in c:\csharp\programs\Exceptiontest\class1.cs:line 51
Remaining program

As shown in the output, passing e to the WriteLine( ) prints the name of the exception class,
exception message, the filename and the method name in which exception is thrown, and the line
number at which the exception is thrown.

If we handle the exception, firstly the catch block gets executed and then the control goes to the
statement following the catch block. The control never returns to the try block. On the contrary if
we do not handle the exception the execution of the program would terminate abnormally as soon
as the exception is thrown.

We can write more than one catch blocks to handle different exceptions. This is shown in the
following example:

int b = 2 ;
int [ ] a = new int [ 5 ] ;
try
{
int i = 10 / b ;
a [ 10 ] = 9 ;
}
catch ( DivideByZeroException e )
{
Console.WriteLine ( "Divide by zero error" ) ;
}
catch ( IndexOutOfRangeException e )
{
Console.WriteLine ( "Index out of bounds" ) ;
}

Here, the two catch blocks are written to handle the 'divide by zero' and 'index out of bounds'
exceptions. The DivideByZeroException and IndexOutOfRangeException classes represent
these exceptions respectively. Since b contains a non-zero value, divide by zero exception would
not get thrown. So, the first catch block would not get executed. The statement a [ 10 ] = 9 is
exceeding the array bounds and so the second catch block would get executed.

In the catch block we have displayed our own message because the default messages are

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

difficult to understand. In this code two exceptions are being handled. If any one of them is raised,
the suitable catch block would get executed.

Instead of writing a catch block for every possible exception we can write a catch block that
accepts pointer to an object of the System.Exception class. It is the base class of all exception
classes and hence address of any type of exception object can be collected in it. This is shown in
the following example:

int b = 2 ;
int[ ] a = new int [ 5 ] ;
try
{
int i = 10 / b ;
a [ 10 ] = 9 ;
}
catch ( Exception e )
{
Console.WriteLine ( e ) ;
}
Article: C# - Management By Exception - II

Continued from last week...

The try-catch-finally Blocks

The finally block is used to perform clean up operations before the program ends. The finally
block is guaranteed to get executed regardless of whether an exception is thrown. So instead of
writing the clean up code in both the try block (if the exception is not thrown) and catch block (if
the exception is thrown) we should write the code in the finally block. This prevents duplication of
code. The finally block must always be associated with the try block. The code written in the
finally block gets executed after the catch block if the catch block is present and the execution
of the program continues. The following code snippet shows how to use a finally block.

using System;

namespace Sample
{
class Class1
{
static void Main ( string [ ] args )
{
int b = 2 ;
int[ ] a = new int [ 5 ] ;
try
{
int i = 10 / b ;
a [ 10 ] = 9 ;
}
catch ( DivideByZeroException e )
{
Console.WriteLine ( "Divide by zero error" ) ;
}
catch ( IndexOutOfRangeException e )
{

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

Console.WriteLine ( "Index out of bounds" ) ;


}
finally
{
Console.WriteLine ( "finally" ) ;
}
Console.WriteLine ( "Remaining program" ) ;
}
}
}

The output of the program would be:

index out of bounds


finally
Remaining program

If the catch block is absent the exception is handled by the CLR, then the code in the finally
block is executed and the execution of the program is terminated.

The throw Statement

The throw statement is used to throw an exception explicitly. For example, consider the following
program:

using System ;
namespace Sample
{
public class Class1
{
static void Main ( string[ ] args )
{
myclass m = new myclass( ) ;
try
{
m.fun ( 20 ) ;
}
catch ( Exception e )
{
Console.WriteLine ( e ) ;
}
}
}
class myclass
{
public void fun ( int i )
{
if ( i > 10 )
throw new Exception ( "Value out of range" ) ;
else
Console.WriteLine ( i ) ;
}
}
}

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

In Main( ) we have created an object m of the class myclass. Using this object we have called
the fun( ) method of the class from within the try block. We have passed 20 to this method. Since
20 is greater than 10, an exception would be raised. So far we were handling the exception in the
method itself by enclosing the statements that were expected to raise an exception in the try
block followed by the catch block. Instead of enclosing the statements within the try block we can
enclose the method call itself in the try block. This is what is done in this program. The method
call in Main( ) has been enclosed within the try block and hence the exception is handled in the
corresponding catch block.

If the value received in fun( ) is greater than 10, we have thrown an exception explicitly by
creating an object of the System.Exception class. (We can also create an exception object of a
particular class such as IndexOutOfRangeException.)

User-Defined Exceptions

While programming you may encounter situations when the existing predefined exceptions fall
short in fulfilling our need. At such times we need to define our own exception classes and throw
user-defined exceptions if the rules are violated. Our exception class should be derived from the
System.Exception class. This is shown in the following program:

using System ;
namespace Bank
{
class customer
{
string name ;
int accno ;
int balance ;

public customer ( string n, int a, int b )


{
name = n ;
accno = a ;
balance = b ;
}

public void withdraw ( int amt )


{
if ( balance - amt <= 100 )
throw new bankexception ( accno, balance ) ;
balance -= amt ;
}

public int getbalance( )


{
return balance ;
}
}

class bankexception : Exception


{
int acc ;
int bal ;

public bankexception ( int a, int b )


{

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

acc = a ;
bal = b ;
}

public void inform( )


{
Console.WriteLine ( "Account Number: " + acc + "Balance left: " + bal ) ;
}
}
public class Class1
{
static void Main ( string[ ] args )
{
customer c = new customer ( "Rahul", 2453, 500 ) ;
try
{
c.withdraw ( 450 ) ;
}
catch ( bankexception e )
{
Console.WriteLine ( "Transaction Failed " ) ;
e.inform( ) ;
}
}
}
}

In this program we have declared a class called customer. In this class we have a string data
member name, and two int data members, accno and balance. We have two methods in this
class-withdraw( ) and getbalance( ). The withdraw( ) method deducts an amount, passed as a
parameter, from balance and the getbalance( ) method returns the balance.

Now we wish to apply the rule that any customer should not have a balance less than Rs. 100 in
his/her account. This means an exception must be thrown whenever the customer tries to
withdraw money which results in the balance to drop below Rs. 100. To tackle this we have
written a user-defined exception class called bankexception having two int data members acc
and bal. This class must be derived from the System.Exception class. This class has a two-
argument constructor which accepts two ints. In the withdraw( ) method we have checked
whether the balance after deduction drops below 100 or not. If it does we have raised an
exception called bankexception. This exception is caught in the catch block which then
proceeds to display a suitable message by calling the inform( ) method.

If the condition in the withdraw( ) method is not satisfied then the balance is appropriately
updated.

.NET Exception Classes

There are a number of standard exception classes provided by .NET Framework, all of which
inherit from the System.Exception class. Given below is the list of some common exception
classes.

Exception Class Cause


Failure to access a type member, such as a
AccessException
method or a data member.
ArgumentException An argument to a method was invalid.

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

A null argument was passed to a method that


ArgumentNullException
doesn't accept it.
ArithmeticException Arithmetic over flow or underflow has occurred.
An attempt to store the wrong type of object in
ArrayTypeMismatchException
an array.
BadImageFormatException Image is in the wrong format.
DivideByZeroException An attempt was made to divide by zero.
FormatException The format of an argument is wrong.
IndexOutOfRangeException An array index is out of bounds.
An attempt was made to cast a class to an
InvalidCastExpression
invalid class.
MissingMemberException An invalid version of a DLL was accessed.
FileNotFoundException A file referenced is not found.
NotFiniteNumberException A number is not valid.
Indicates that a method is not implemented by
NotSupportedException
a class.
NullReferenceException Attempt to use an unassigned reference.
OutOfMemoryException Not enough memory to continue execution.
StackOverflowException A stack has overflown

Article: C# - Collection Classes - I

Collection Classes

Use of an appropriate Data Structure at appropriate place goes a long way in building efficient
programs. If you use an array in place of a linked list or vice-versa, the program is likely to fire in
some situation. But while writing a C# program the last thing on our mind is how to build a linked
list. There are more important things to attend to. We can use the .NET Collection Classes to
manage data structures. .NET provides the System.Collections namespace that contains
various interfaces and classes representing the collections of objects. For example, lists, queues,
arrays, hashtables and dictionaries. Let us discuss these classes and interfaces one by one.

The ArrayList Class

The ArrayList class is similar to the Array class except that its size can grow dynamically.
Following code snippet shows how to use the methods of an ArrayList class.

ArrayList arr = new ArrayList( ) ;

arr.Add ( 'a' ) ;
arr.Add ( 43 ) ;
arr.Add ( 6.7 ) ;
arr.Add ( "Rahul" ) ;

arr.Insert ( 1, "Deepti" ) ;

for ( int i = 0 ; i < arr.Count ; i++ )


Console.WriteLine ( arr [ i ] ) ;

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

Since the Add( ) method takes a parameter of type object we can store values of any type in one
array.

Just like the Array class, the ArrayList class contains various methods to perform functions like
adding, inserting, removing, copying, etc. By default, the capacity-number of elements the array
list can hold-is of 16 elements. If the number of elements exceeds 16 then the capacity of the
array list automatically gets doubled by allocating new area of memory. If we want, we can
increase or decrease the capacity of the array list using the Capacity property of ArrayList class.
The Capacity property indicates the number of elements the ArrayList object is capable of
holding. If we increase the capacity by saying arr.Capacity = 32 the array list arr would
automatically get reallocated.

The BitArray Class

The BitArray class represents an array of bool values. Each element of the BitArray contains
either true or false. The BitArray class contains several overloaded constructors, except the
zero-argument constructor. Following statements show how an object of the BitArray can be
instantiated.

int[ ] a = { 1, 2, 3 } ;
BitArray b1 = new BitArray ( a ) ;
BitArray b2 = new BitArray ( 5 ) ;
BitArray b3 = new BitArray ( 5, true ) ;

If we pass reference to another array as an argument to the BitArray constructor the bit values of
every element of that array get copied as the elements of the BitArray. For example, the bit
values (1 or 0) of the element 1 would become first 32 elements (1 being a 32-bit number) in the
array b1. Either true or false would get stored in b1 depending upon whether the bit is 1 or 0.
The array b2 would get created with 5 elements and by default all the elements would be set to
false. The array b3 would contain 5 elements where all the elements would be set to the bool
value true. Following code would display the elements of array b1.

for ( int i = 0 ; i < b1.Count ; i++ )


Console.WriteLine ( "{0} ", b1 [ i ] ) ;

The BitArray class contains several methods using which we can perform the bitwise operations
on the array elements. For example, Not( ), Or( ), Xor( ), etc. Following code snippet shows how
to use these methods.

int[ ] a1 = { -10, -10 } ;


int[ ] a2 = { 10, 10 } ;

BitArray b1 = new BitArray ( a1 ) ;


BitArray b2 = new BitArray ( a2 ) ;

b1.And ( b2 ) ;
b1.Or ( b2 ) ;
b1.Xor ( b2 ) ;

The functions performing bitwise operations need another BitArray using whose elements the
bitwise operation is performed. Hence, we have instantiated two BitArrays b1 and b2 by passing
the references of the int arrays. The elements of b1 would get ANDed, ORed and XORed with
the elements of b2. Note that the arrays using which b1 and b2 are created must have same
number of elements.

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

We can change the values of the elements of a BitArray using the Set( ) or Setall( ) methods as
shown below:

b1.Set ( 1, true ) ;
b1.SetAll ( true ) ;

The Set( ) method sets the specified element to the specified bool value, whereas, the SetAll( )
method sets all the elements to the specified bool value.

The Queue Class

The Queue class is a collection of objects, which are stored and retrieved in 'First In First Out'
manner. We can use the Queue class to develop an application that can receive the messages
and display them on the basis of the date of receipt.

The following program demonstrates how to implement the Queue class.

using System ;
using System.Collections ;

namespace collect
{
class Class1
{
static void Main ( string[ ] args )
{
Queue q = new Queue( ) ;

q.Enqueue ( "Message1" ) ;
q.Enqueue ( "Message2" ) ;
q.Enqueue ( "Message3" ) ;
q.Enqueue ( "Message4" ) ;

Console.WriteLine ( "First message: {0}", q.Dequeue( ) ) ;

Console.WriteLine ( "The element at the head is {0}", q.Peek( ) ) ;

IEnumerator e = q.GetEnumerator( ) ;
while ( e.MoveNext( ) )
Console.WriteLine ( e.Current ) ;
}
}
}

We have used the Enqueue( ) method of the Queue class to add the elements at the end of the
queue. We have added few messages in the queue. The Dequeue( ) method returns the element
at the head of the queue and removes it. If we want to get the element at the head but do not
want to remove it from the queue, we can use the Peek( ) method. Unlike the classes ArrayList
and BitArray, the Queue class does not provide an indexer. Hence, we cannot use [ ] operator to
access the queue elements. So, to access the queue elements we have used an interface called
IEnumerator provided by the Collections namespace. The Queue class implements this
interface. We have used the GetEnumerator( ) method of Queue class to obtain an
IEnumerator reference e. Using this reference we have iterated through the queue. The Current
property of the IEnumerator interface returns the element at the current position. The reference e
can be used only to iterate through the collection, not to modify it. Other classes of the

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

Collections namespace like ArrayList and BitArray also implement the IEnumerator interface.
So, we can use it to enumerate these arrays also.

To check whether a particular element exists in the queue or not, we can use the Contains( )
method as shown below:

bool b = q.Contains ( "Message3" ) ;


Console.WriteLine ( b ) ;

The Contains( ) method returns true if the element 'Message3' exists in the queue, otherwise it
returns false.

The Queue object is not thread safe. It means that two different threads can access one Queue
object at the same time, which can prove dangerous. To avoid such a situation the Queue class
provides a static method Synchronized( ) that returns a synchronized wrapper around the
specified object. Following statements show how to use the Synchronized( ) method.

Queue q = new Queue( ) ;


Queue sq = Queue.Synchronized ( q ) ;

We can now safely use sq to perform various operations on the queue.

Article: C# - Collection Classes - II

Continued from last week...

The Stack Class

Since the Collections namespace provides Queue class, it is obvious that it would also provide
Stack class. Needless to say that the Stack class provides 'Last In First Out' way to store and
retrieve the elements. The following program shows how to use this class:

using System ;
using System.Collections ;

namespace collect
{
class Class1
{
static void Main ( string[ ] args )
{
Stack st = new Stack( ) ;

st.Push ( 10 ) ;
st.Push ( 11 ) ;
st.Push ( 12 ) ;
st.Push ( 13 ) ;

Console.WriteLine ( "Element popped: {0}", st.Pop( ) ) ;

IEnumerator e = st.GetEnumerator ( ) ;
while ( e.MoveNext( ) )
Console.WriteLine ( e.Current ) ;

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

}
}
}

The Stack class provides the Push( ) and Pop( ) methods to store and retrieve the stack
elements. The Pop( ) method returns the element at the top of the stack and then removes it. We
have displayed the stack elements using the IEnumerator interface. We can use the Peek( )
method to obtain the element at the top without removing it from stack.

The Hashtable Class

In a hash table we can store pairs of values and associated keys. The values are organised on
the basis of the keys. These keys can be used to get the respective values from the hash table.
.NET has encapsulated the functionality of hash table in a class called Hashtable. Following
program illustrates how we can initialise and use the Hashtable class.

using System ;
using System.Collections ;

namespace collect
{
class Class1
{
static void Main ( string[ ] args )
{
Hashtable h = new Hashtable( ) ;
h.Add ( "mo", "Monday" ) ;
h.Add ( "tu", "Tuesday" ) ;
h.Add ( "we", "Wednesday" ) ;
h.Add ( "th", "Thursday" ) ;
h.Add ( "fr", "Friday" ) ;
h.Add ( "sa", "Saturday" ) ;
h.Add ( "su", "Sunday" ) ;

IDictionaryEnumerator e = h.GetEnumerator( ) ;
while ( e.MoveNext( ) )
Console.WriteLine ( e.Key + "\t" + e.Value ) ;

Console.WriteLine ( "The Keys are : " ) ;


ICollection k = h.Keys ;
foreach ( object i in k )
Console.WriteLine ( i ) ;

Console.WriteLine ( "The Values are : " ) ;


ICollection v = h.Values ;
foreach ( object i in v )
Console.WriteLine ( i ) ;
}
}
}

The Hashtable class provides the Add( ) function to store the key and its value. Note that the key
value pairs may not get stored in the hash table in the same sequence in which they are added.
In which order they would get stored depends upon the hashing function used by the Hashtable
class. The GetEnumerator( ) method of the Hashtable class returns the reference of the

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

IDictionaryEnumerator interface. We have displayed the value and the respective keys using
the Value and Key properties of the IDictionaryEnumerator interface.

We can use the ICollection interface to iterate through the keys and values. The sequence in
which the values would get displayed is unspecified. The Hashtable class contains properties
Keys and Values that return the reference of the ICollection interface

To remove an item from the hash table we can use the Remove( ) function. The Remove( )
method removes the value from the hash table using the specified key. We can access the value
of the specified key simply by using the indexer as shown below:

h [ "su" ] = "Sun" ;
h [ "mo" ] = "Mon" ;
Console.WriteLine ( h [ "fr" ] ) ;

The SortedList Class

Like Hashtable, the SortedList class maintains pairs of keys and values. The difference between
the two is that in the SortedList class, the values are sorted by keys and are accessible by key
as well as by index.Consider the following program:

namespace Sample
{
class Class1
{
static void Main ( string[ ] args )
{
SortedList s = new SortedList ( ) ;
s.Add ( "Maharastra ", "Mumbai" ) ;
s.Add ( "Karnataka ", "Bangalore" ) ;
s.Add ( "Andhra Pradesh", "Hyderabad" ) ;
s.Add ( "Tamilnadu ", "chennai" ) ;
s.Add ( "Bihar ", "Patna" ) ;
s.Add ( "Rajastan ", "Jaipur" ) ;
s.Add ( "Orissa ", "Bhubaneshwar" ) ;

Console.WriteLine ( "Elements in the SotredList: " ) ;


IDictionaryEnumerator e = s.GetEnumerator ( ) ;
while ( e.MoveNext( ) )
Console.WriteLine ( e.Key + "\t" + e.Value ) ;
s.Remove ( "TamilNadu" ) ;

Console.WriteLine ( "The Keys are : " ) ;


ICollection k = s.Keys ;
foreach ( object i in k )
Console.WriteLine ( i + " " ) ;
Console.WriteLine ( "The Values are : " ) ;
ICollection v = s.Values ;
foreach ( object i in v )
Console.WriteLine ( i + " " ) ;
Console.WriteLine ( "Value at 3rd Index 3: " + s.GetByIndex ( 3 ) ) ;
Console.WriteLine ( "Key at 3rd Index: " + s.GetKey ( 3 ) ) ;

Console.WriteLine ( "The Index of key Bihar" + s.IndexOfKey ( "Bihar" ) ) ;


Console.WriteLine ( "The Index of value Jaipur" + s.IndexOfValue ( "Jaipur" ) ) ;

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

}
}
}

Like Hashtable, the SortedList class also uses IDictionaryEnumerator interface to iterate
through the list elements. To get the list of keys and values we have used the Keys and the
Values properties respectively. The Remove( ) method deletes the value of the specified key.
The methods GetByIndex( ) and GetKey( ) return the value and key respectively at the specified
index. We can get the index of a key by using the IndexOfKey( ) method. To get the index of the
value we can use the IndexOfValue( ) method.

Article: C# - Collection Classes - III

Continued from last week...

The IComparer Interface

The IComparer interface provides methods to compare two objects. Most of the classes
implement this interface so that the user can easily compare two objects of the class.

Let us create a program that shows how to implement the IComparer interface. In this program
we would write a class emp maintaining the information of employees. Another class mysort
would implement the IComparer interface. Here is the program…

using System ;
using System.Collections ;

namespace icomb
{
class emp
{
public string name ;
public int id ;
public float balance ;
public emp ( int i, string n, float b )
{
id = i ;
name = n ;
balance = b ;
}
public new string ToString( )
{
return id + " " + name + " " + balance ;
}
}
public class mysort : IComparer
{
public int Compare ( object a, object b )
{
int i1 = ( ( emp ) a ).id ;
int i2 = ( ( emp ) b ).id ;
string n1 = ( ( emp ) a ).name ;
string n2 = ( ( emp ) b ).name ;

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

if ( i1 == i2 )
{
return n1.CompareTo ( n2 ) ;
}
if ( i1 < i2 )
return -1 ;
return 1 ;
}
}
public class Class1
{
public static int Main ( string[ ] args )
{
emp[ ] e =
{
new emp ( 2, "Sanjay", 3450 ),
new emp ( 1, "Rahul", 2500 ) ,
new emp ( 10, "Kavita", 10000 ),
new emp ( 9, "Mohit", 25000),
new emp ( 6, "Sapna", 2500),
};

mysort s = new mysort( ) ;


Array.Sort ( e, s ) ;
foreach ( emp s1 in e )
Console.WriteLine ( s1.ToString( ) ) ;
return 0 ;
}
}
}

Here, we have firstly instantiated an array e of type emp and then an object of type mysort. In
the mysort class we have defined the Compare( ) method of the IComparer interface and
written our own sorting logic in it. Next, to sort the array e we have called the Sort( ) method of
the Array class. To the Sort( ) method we have to pass the array to be sorted and reference to
the IComparer interface. The Sort( ) method calls the Compare( ) method. The Compare( )
method returns 0, 1 or -1 indicating whether the objects being compared are equal or one is
smaller than the other. In our case, since the mysort class is derived from IComparer we have
passed reference to the mysort's object. Hence, the Compare( ) method of mysort class gets
called.

Once the array is sorted we have displayed the array elements. We have overridden the
ToString( ) method in the emp class. This is because we wanted to display the sorted elements
using the statement s1.ToString( ). Had we not overridden this method in emp class, ToString( )
of the base class would have got called, which we do not want. In the ToString( ) of emp class
we have concatenated the values of the data members in a string and returned it.

Other Collection Classes

In addition to the collection classes that we have used in this chapter there are several more
classes offered by the Collections namespace. These are listed along with the purpose of each
in following table.

Class Purpose
CaseInsensitiveComparer Compares two objects of same type. If objects are strings,

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

comparison is case-insensitive
Creates a hash code using a hashing algorithm that ignores
CaseInsensitiveHashCodeProvider
the case of strings
Provides the abstract base class for creating custom
CollectionBase
collections
Compares two objects. If objects are strings, comparisons
Comparer
are case-sensitive
Provides the abstract base class for creating collection
DictionaryBase class that uses collection of key-value
pairs
Provides the abstract base class for creating read-only
ReadOnlyCollectionBase
collections

Similarly, the Collections namespace contains few more interfaces other than those we have
covered in this article. They are listed in following table along with the purpose of each.

Interface Purpose
IDictionary Provides a collection of key-value pairs
IDictionaryEnumerator Enumerates the elements of a key-value collection
Provides the enumerator, which supports a simple iteration through a
IEnumerable collection. It is implemented by all
enumerator interfaces
IHashCodeProvider Supplies a hash code for an object, using a custom hash function

Article: C# - Multithreading - I

Every application running under Windows constitutes a process. Each process can contain one or
more threads of execution. A thread constitutes a part of execution through a program's code and
a set of resource (like stack, register state, etc.) assigned by the operating system. When we
execute a Win32 application it starts as a single thread but can spawn several additional threads.
There is a scheduler program in the operating system kernel that divides the CPU time among
active threads. As a result, all the threads appear to run simultaneously. Threads are popularly
used for performing tasks in the background while processing user input in the foreground.
However, usage of threads is not restricted to running tasks in the background. They can also be
used for creating windows or other foreground processing. Though writing multithreaded
programs is difficult, if used properly threads can dramatically improve an application's
performance. Threads are basically asynchronous by nature. It takes time for the programmers to
get used to this behavior.

Let us now create an application where we can put multithreading to work. The application should
display the list of files present in 'C' drive in the form shown in Figure 1.

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

Figure 1

The listing should begin when we click on the 'Start' button and it should stop when we click on
the 'Stop' button. When we click on the 'Start' button, an event handler should get called. Another
event handler should get called when we click on the 'Stop' button. If we do not run the event
handler or the 'Start' button in a separate thread we would not be able to click the 'Stop' button
unless control returns from the 'Start' button's event handler. A clear cut case where
multithreading would make sense.

Let us now proceed with creating the program. Create a form shown in Figure 1

Insert three buttons and a label in the form. The label would display file names. On clicking the
'Start' button an event handler would get called that would start a new thread to display the files
on the disk in the label. After starting the thread the event handler would end. The process of
displaying the files would continue and there would be no restriction on us to click the 'Stop'
button. This is because the event handler written for the 'Start' button in the main thread would
end and the main thread would be ready to receive other events. At the same time the new thread
would be getting time slots for processing.

To build such an application create a 'Windows application' and insert three buttons: 'Start', 'Stop'
and 'Close' having names as start, stop and close respectively in the form. Also add a Label
control having name file to the form. Add the event handlers for all the three buttons. Firstly we
would see the start_Click( ) handler. This handler is given below:

private void start_Click ( object sender, System.EventArgs e )


{
string path = @"c:\" ;
search s = new search ( file, path ) ;
ThreadStart ts = new ThreadStart ( s.searchfiles ) ;
t = new Thread ( ts ) ;
t.Start( ) ;
}

Here, we have first created an object of the user-defined search class. We would see this class
later. We have passed the reference of the label and the directory path to the constructor. Next,
we have created a new thread. To start another thread we have created an object of the Thread
class first. This object's reference is stored in t. The reference t (of type Thread) should be added
as a data member of the form class. While creating a thread, we must specify which function
should get executed when the thread gets started. We have specified that the searchfiles( )
method of the search class should get executed. For this, we have to wrap its address in a
delegate and pass it to the constructor of the Thread class. We have used a predefined .NET
delegate class called ThreadStart and created a delegate object ts. The delegate ts is passed to
the constructor of the Thread class. So whenever the thread is started, the method wrapped
inside ts would start executing. To start a thread we have called Start( ) method of the Thread

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

class. As soon as the 'Start' button is clicked, the label control starts displaying all the filenames.
To be able to use this class we must write the statement using System.Threading in our
program.

The search class is given below:

class search
{
Label file ;
DirectoryInfo dir ;

public search ( Label l, string p )


{
file = l ;
dir = new DirectoryInfo ( p ) ;
}

public void searchfiles( )


{
FileSystemInfo[ ] f = dir.GetFileSystemInfos( ) ;
foreach ( FileSystemInfo i in f )
{
if ( i.Attributes == FileAttributes.Directory )
{
dir = new DirectoryInfo ( i.FullName ) ;
searchfiles( ) ;
}
else
file.Text = i.FullName ;
}
}
}

The method searchfiles( ) present in this class would be called from the new thread. The
prototype of the ThreadStart delegate is such that it can hold addresses of those methods that
return a void and do not accept anything. So we cannot pass any parameters to the
searchfiles( ) method. Hence the parameters that we need in this method have been added as
data members of the search class and have been initialized using the constructor of the search
class. The reference of label and directory path passed to the constructor from the start_Click( )
method are stored in the file and dir data members of type Label and DirectoryInfo classes
respectively.

In the searchfiles( ) method we have created an array f of the FileSystemInfo class. Then by
using the GetFileSystemInfos( ) method, we have collected all the files and directories, present
under the directory referenced by dir in the array. The FileSystemInfo class serves as the base
class for the DirectoryInfo class and the FileInfo class. To use these classes we must add the
statement using System.IO at the beginning of our program.

Just like the File and FileInfo classes, .NET provides the Directory and DirectoryInfo classes.
Both the Directory and DirectoryInfo classes represent a folder in a file system. The Directory
class contains only static methods and is never instantiated. The DirectoryInfo class on the
other hand can be instantiated. The hierarchy of these classes is shown in the Figure 2.

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

Figure 2

The FileSystemInfo class can hold the reference of any file system object, be it a file or a
directory. After storing the reference of the array in f, we have iterated through the array using the
foreach loop and checked whether each file system object is a file or a directory. This is done by
comparing the Attribute property of the FileSystemInfo object with the Directory member of the
FileAttribute enumeration. If the object turns out to be a directory, we have created a new
DirectoryInfo object, stored its reference in dir and recursively called the searchfiles( ) method.
If the file system object turns out to be a file, we have displayed its name in the label present in
the form.

To interrupt the process of displaying the files before all the files are displayed we have to click on
the 'Stop' button. It is possible for us to click on the 'Stop' button because the execution of the
searchfiles( ) method is taking place in a different thread. On clicking the 'Stop' button, the
handler stop_Click( ) gets called. The code for the handler is shown below.

private void stop_Click ( object sender, System.EventArgs e )


{
t.Abort( ) ;
}

The Abort( ) method of the Thread class terminates a thread.

If we wish to terminate the application, we have to click on the 'Close' button; the handler for the
'Close' button gets called that disposes the form. The handler is shown below.

private void close_Click ( object sender, System.EventArgs e )


{
Dispose( ) ;
}
Article: C# - Multithreading - II

Continued from last week...

Synchronization

Software development is a team effort. Unless team members cooperate with one another,
synchronize their work with the rest of the team, the team can't go far. Similarly if in a program

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

there are several threads running, unless their activities are synchronized with one another the
disaster is not far away. For example, if a program instantiates two threads and if both the threads
use the same resource and both of them change it simultaneously, the situation would become
dangerous.

To give you a more concrete example, suppose in a program there is a list of names that is to be
sorted. We can also add new names to the list. Suppose we write one thread to sort the list and
another thread to add a name to the list. Now if the sort thread has executed half way and if we
try to add a new name in the list, the name may get added at the end but the result of the sort
would be wrong.

In such cases we must make sure that if one thread is handling the list, the other should not work
with it. This is achieved using synchronization.

Synchronization provides a lock on the object that is going to be shared amongst threads and
makes a thread wait until the other thread finishes the job with the resource or object. Hence we
can say that synchronization 'locks' the object or shared resource and prevents another thread
from using it.

C# provides us with a lock keyword to lock the shared object or resource. Whatever is written
inside the parenthesis following the lock keyword gets locked for the current thread and no other
thread is permitted to access that resource or object. To understand these concepts more
thoroughly consider the following program.

In this program the form consists of three buttons: 'Add', 'Sort' and 'Close' having names add,
sort and close respectively and a list box control having the name list. The design of the form is
shown in following figure.

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

Clicking the 'Add' button would start a thread to add a new name to the list, whereas, clicking the
'Sort' button would start another thread that would sort the list. The list box control would always
display the names stored in an ArrayList object whose reference is added as a data member of
the form class.

We have initialized the array list object in the constructor of the form class with names contained
in a file. The code to do so is shown in the following snippet:

public Form1( )
{
InitializeComponent( ) ;
arr = new ArrayList( ) ;
FileInfo f = new FileInfo ( "data.txt" ) ;
StreamReader r = f.OpenText( ) ;
string s ;

while ( ( s = r.ReadLine( ) ) != null )


{
arr.Add ( s ) ;
list.Items.Add ( s ) ;
}
r.Close( ) ;
}

Here in the constructor we have initialized the array list object arr with names present in the
'data.txt' file. This file should be present in the 'synchronize' project folder. The methods that the
threads would start are written inside a class called mythread. The declaration of the mythread
class is given below.

class mythread
{
ListBox list ;
ArrayList arr ;
string name ;

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

public mythread ( ListBox l, ArrayList a )


{
list = l ;
arr = a ;
}

public mythread ( ListBox l, ArrayList a, string n )


{
list = l ;
arr = a ;
name = n ;
}

public void add( )


{
lock ( arr )
{
arr.Add ( name ) ;
list.Items.Clear( ) ;
foreach ( string i in arr )
list.Items.Add ( i ) ;
}
}
public void sort( )
{
lock ( arr )
{
arr.Sort( ) ;
list.Items.Clear( ) ;
foreach ( string i in arr )
list.Items.Add ( i ) ;
}
}
}

In this program we cannot pass parameters to the sort( ) and add( ) methods because they are
wrapped by the ThreadStart delegate. Hence we have added the parameters that we need in the
methods as data members of the class and initialized these parameters using constructors.
Hence this class contains two constructors. The two-argument constructor is used for initializing
parameters for the sort( ) method, whereas, the three-argument constructor is used for initializing
parameters for the add( ) method.

We have locked the ArrayList object in this program, as it is used by both the threads. In the
add( ) method after locking the arr object we have added the new name to the list by using the
Add( ) method. Next we have deleted all the items of the list box by calling the Clear( ) method
and then displayed all the names again including the new name. In the sort( ) method too we
have first locked the object arr and then sorted the array using the Sort( ) method of the
ArrayList class. The sorted list is then displayed in the list box.

We have called the add( ) and sort( ) methods in the corresponding handlers. The handler for the
'Add' button is shown below.

private void add_Click ( object sender, System.EventArgs e )


{

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

string n = name.Text ;
name.Text = "" ;

mythread m = new mythread ( list, arr, n ) ;


ThreadStart ts = new ThreadStart ( m.add ) ;
Thread t = new Thread ( ts ) ;
t.Start( ) ;
}

Here firstly we have collected the name to be added in n and then cleared the text box. Then we
have created an object of the mythread class passing three arguments to the constructor. Next
we have started a new thread which would call the add( ) method.

The handler for the 'Sort' button is shown below.

private void sort_Click ( object sender, System.EventArgs e )


{
mythread m = new mythread ( list, arr ) ;
ThreadStart ts = new ThreadStart ( m.sort ) ;
Thread t = new Thread ( ts ) ;
t.Start( ) ;
}

Here we have created an object of the mythread class passing two parameters to its constructor.
We have then created a new thread that would call the sort( ) method.

From the close_Click( ) handler we have only called Dispose( ) method to close the form
window.

void close_Click ( Object *sender, EventArgs *e )


{
Dispose( ) ;
}
Article: C# - Multithreading - III

Continued from last week...

Monitor

Suppose a situation arises where we want to use the output of one thread as the input to another.
Here we would have to use synchronization again. The need of synchronization would be clear in
the following example.

In this program we plan to create one thread that would generate information of shapes like
coordinates, pen color, etc. randomly and another thread that would draw shapes using this
information. Unless the generate thread generates some shapes, the draw thread would not
have anything to draw. Hence the draw thread would have to wait for the generate thread to
complete its execution because the output of the generate thread (shapes) would be used by the
draw thread as input.

On the other hand the generate thread must also wait for the draw thread to draw the shapes it
previously generated. If the generate thread does not wait for the draw thread, it would overwrite
its own data before the data is used by the draw thread.

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

Such a situation calls for alternate execution of both the threads and each thread must wait for
the other thread. Both threads would share the same resource. The generate thread would use
the resource to fill in shapes and the draw thread would use the resource to read the shapes.
Hence the resource must not be used by both the threads at the same time. For such a
sophisticated control over resources, we should use a monitor. A Monitor lets us decide when to
enter and exit the synchronization. The class that represents a monitor in .NET is
System.Threading.Monitor. Let us see how to use this class in our program.

In this program we plan to generate shapes like lines, rectangles and ellipses and then draw them
on the form. To accomplish this we have used two methods namely generate( ) and draw( ).
These two methods would be called from two different threads. We have to make sure that in
spite of them being in different threads, they should execute alternately.

We have also created a structure called info that would store information about a shape including
the shape number, its coordinates and the pen with which the shape would be drawn. The
structure declaration is shown in the following snippet:

struct info
{
public int shapeno ;
public int x1, y1, x2, y2 ;
public Pen p ;
};

Next we have defined a class called shapes. The shapes class consists of four data members:
They are as follows:

info[ ] n ;
Random r ;
bool flag ;
Form1 f ;

The array n would be used to store the pointer to an array containing the shapes. The reference r
would be used to generate random numbers. The bool data member flag would be used for
controlling the alternate execution of the threads. The reference f would hold the address of the
form.

A one-argument constructor is used to initialize these data members. This is how we need to
initialize the data members:

public shapes ( Form1 ff )


{
n = new info [ 10 ] ;
r = new Random( ) ;
flag = false ;
f = ff ;
}

We have defined two methods called generate( ) and draw( ) in the shapes class: Along with
these methods the shapes class also contains the generatedata( ) and drawdata( ) methods.
Let us discuss them one by one. The generate( ) method is given below:

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

public void generate( )


{
Monitor.Enter ( n ) ;

if ( flag )
Monitor.Wait ( n ) ;
Size sz = f.ClientSize ;
for ( int i = 0 ; i < 10 ; i++ )
{
n [ i ].shapeno = r.Next ( 3 ) ;
n [ i ].x1 = r.Next ( sz.Width ) ;
n [ i ].y1 = r.Next ( sz.Height ) ;
n [ i ].x2 = r.Next ( sz.Height - n [ i ].y1 ) ;
n [ i ].y2 = r.Next ( sz.Width - n [ i ].x1 ) ;
Color c = Color.FromArgb ( r.Next ( 255 ), r.Next ( 255 ), r.Next ( 255 ) ) ;
n [ i ].p = new Pen ( c, 3 ) ;
Thread.Sleep ( 10 ) ;
}
MessageBox.Show ( "Generate" ) ;

flag = true ;
Monitor.Pulse ( n ) ;
Monitor.Exit ( n ) ;
}

In the generate( ) method we have generated the shape number, coordinates and pen color
randomly. After initializing every element of the array we have halted the thread with the help of
the Sleep( ) method for 10 milliseconds to ensure proper generation of random numbers. We
have done this in a loop to fill the 10 elements of the array n. After this we have indicated the user
about the generation of random shapes with the help of a message box.

When this operation is taking place, the array n should not be used by the draw( ) method in the
other thread. Hence before starting the operation we have locked this object by passing it to the
Enter( ) method of the Monitor class. This is equivalent to writing a lock statement, passing n to
it and putting the whole code in a block. Then we checked that if flag is set to true or not. If it is
true, it means that another thread having draw( ) method is using the resource n and so, the
thread should wait. This is achieved by using the Wait( ) method. A waiting thread can always be
activated using the Pulse( ) method. So until the thread is activated it would wait.

If flag is set to false, the control skips past the Wait( ) method call and the remaining code gets
executed which generates the shapes and initializes the array. Before exiting, the method sets
the flag to true and sends a pulse to any other waiting thread. The Exit( ) method marks the end
of the area controlled by the monitor.

The draw( ) method is shown in the following code snippet:

public void draw( )


{
Monitor.Enter ( n ) ;

if ( !flag )
Monitor.Wait ( n ) ;

Graphics g = f.CreateGraphics( ) ;

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

Thread.Sleep ( 100 ) ;
for ( int i = 0 ; i < 10 ; i++ )
{
switch ( n [ i ].shapeno )
{
case 0 :
g.DrawLine ( n [ i ].p, n [ i ].x1, n [ i ].y1, n [ i ].x2, n [ i ].y2 ) ;
break ;

case 1 :
g.DrawRectangle ( n [ i ].p, n [ i ].x1, n [ i ].y1, n [ i ].x2, n [ i ].y2 ) ;
break ;

case 2 :
g.DrawEllipse ( n [ i ].p, n [ i ].x1, n [ i ].y1, n [ i ].x2, n [ i ].y2 ) ;
break ;
}
}

MessageBox.Show ( "Draw" ) ;
flag = false ;
Monitor.Pulse ( n ) ;
Monitor.Exit ( n ) ;
}

In this method we have simply drawn the shapes using the information present in the array n with
the help of an object of the Graphics class. We have first checked the shape number and then
drawn the shape accordingly. Here too we have used the Monitor.Enter( ) method to lock the
array n. In this method we have checked whether the flag is set to false or not. If it is set to false,
the thread would wait. Until the thread is activated by the executing thread, it would wait. If the
flag is set to true, the control skips past the Wait( ) method call and the remaining code gets
executed and draws the shapes. Before exiting, the method sets the flag to false.

Now you can imagine what must be happening if both the methods are executed simultaneously
on two different threads. Before initializing the threads, we have set the flag to false. This makes
the thread in which the draw( ) method is executing to go in a wait state. The generate( ) method
on the other hand skips the Wait( ) method call and gets executed. Before the control comes out
of the generate( ) method, it sends a pulse which activates the thread in which draw( ) is called
and sets the flag to true. Hence now the draw( ) method starts executing. Next time when the
generate( ) method gets called, it goes into a wait state. This approach ensures that both the
methods in spite of being in different threads, execute alternately.

To see this effect we have called the generate( ) and draw( ) methods ten times. The generate( )
and draw( ) methods have been called from the generatedata( ) and drawdata( ) methods
respectively. Theses methods would be called from two different threads. The generatedata( )
and drawdata( ) methods are shown below:

public void generatedata( )


{
int i = 0 ;
while ( i != 10 )
{
i++ ;
generate( ) ;
}

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

public void drawdata( )


{
int i = 0 ;
while ( i != 10 )
{
i++ ;
draw( ) ;
}
}

We have initiated the threads when the user clicks the mouse button in the form. The handler for
the MouseDown event is shown below:

private void Form1_MouseDown ( object sender, System.Windows.Forms.MouseEventArgs e )


{
shapes s = new shapes ( this ) ;

ThreadStart ts1 = new ThreadStart ( s.generatedata ) ;


Thread t1 = new Thread ( ts1 ) ;
t1.Start( ) ;

ThreadStart ts2 = new ThreadStart ( s.drawdata ) ;


Thread t2 = new Thread ( ts2 ) ;
t2.Start( ) ;
}

Now if we run the program and click on the form we would get the "Generate" and "Draw"
messages alternately. Following figure would make the functioning of this program clearer.

A point to note! Instead of using the if statement and making the thread wait until the other thread
sends a pulse to it, we may think of using a while loop checking the flag every time. But this is
not the correct way. The processor time would be wasted if we go on checking the flag manually.
Hence to save processor time, it is always right to use the Wait( ) method and send a pulse to it
every time.

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

Article: C# - Reflections

Discovering Types Using Reflection

Every managed application in .NET is deployed as an assembly and every assembly defines
certain types. These types are revealed in the form of metadata. We can find the types - methods,
fields, properties, and events defined in an assembly using reflection. .NET has provided the
System.Reflection namespace containing various classes and methods for accessing the
metadata. Interesting thing is we can use reflection to find out the types at run-time. While
working in Visual Studio.NET we unknowingly use reflection many times. Visual Studio.NET uses
reflection to display types in IntelliSense. Similarly, .NET framework uses reflection to obtain
information at run-time about the assemblies that it loads.

Using classes of System.Reflection namespace we can

• Obtain information about assemblies, modules and types they contain


• Obtain information about custom attributes

Retrieving Information about Assemblies, Modules and Types

Here is a simple program that shows how to obtain information about an assembly and modules.
It also displays the contained types of the assembly. To execute this program we must declare the
namespace System.Reflection in the program. Here we have displayed information of the
assembly “System.Drawing.dll”.

static void Main ( string[] args )


{
Assembly a = Assembly.LoadFrom ( "C:\\System.Drawing.dll" ) ;
AssemblyName n = a.GetName( ) ;
Console.WriteLine ( "Name of assembly: {0}", n.Name ) ;

Version v = n.Version ;
Console.WriteLine ( "Assembly Version: {0}.{1}.{2}.{3}", v.Major, v.Minor, v.Build, v.Revision ) ;

Console.WriteLine ( "Modules: " ) ;


Module[ ] ma = a.GetModules( ) ;
foreach ( Module m in ma )
Console.WriteLine ( m.Name ) ;
Console.WriteLine ( "Exported Types: " ) ;
Type[ ] t = a.GetExportedTypes( ) ;
foreach ( Type type in t )
Console.WriteLine ( type.Name ) ;
}

To reflect on an assembly System.Reflection namespace contains a class named Assembly.


Before calling any methods of the Assembly class we must load the assembly. We have done
this by calling the static method of the Assembly class called LoadFrom( ). To the LoadFrom( )
method we need to pass URL of the assembly. Once the assembly is loaded, we can obtain
information like assembly name, version, modules in assembly, types exported by the assembly,
etc. The GetName( ) method of Assembly class returns reference to an object of the
AssemblyName class. Using this object we can get still more information about the assembly.
We have used the Version property of the AssemblyName class to get the version of the
assembly. The GetModules( ) method of the Assembly class returns an array of Module objects
representing modules in the assembly. We have then obtained the module name by using the

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

Name property of the Module class. We can get the list of exported types of the assembly by
calling the GetExportedTypes( ) method. This method returns an array of objects of class Type.
If we use the GetTypes( ) method instead of GetExportedTypes( ) method we will get list of all
the types, not just exported types.

Here we have used the object of Type class to store the information of a type in the assembly.
The System.Type class resides at the center of the reflection system. It implements the
System.IReflect interface. This interface allows querying of fields, methods, properties, etc.
This Type class provides hoards of methods that can be used to create a utility like WinCV. (The
WinCV utility is used to view all the members declared in a class). We would now take a look at
how the Type class can be used. Here instead of browsing a predefined type, we would browse a
user-defined type test. Here is the declaration of the test class.

public class test


{
int i ;
int prop ;
public int Prop
{
get
{
return prop ;
}
set
{
prop = value ;
}
}
public test( )
{
}
public test ( int x )
{
i=x;
}
public int myfunc ( int x )
{
Console.WriteLine ( "In myfunc " + x ) ;
return 2 * x ;
}
}

In this class we have declared a data member int i, a property called Prop, a zero-argument
constructor, a one-argument constructor and a method called myfunc( ) that accepts an int and
returns an int. Let us now retrieve information about this class.

static void Main ( string[ ] args )


{
Type t = typeof ( test ) ;

Console.WriteLine ( "Type of class: " + t ) ;


Console.WriteLine ( "Namespace: " + t.Namespace ) ;

Console.WriteLine ( ) ;

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

ConstructorInfo [ ] ci = t.GetConstructors( ) ;
Console.WriteLine ( "Constructors are:" ) ;
foreach ( ConstructorInfo c in ci )
Console.WriteLine ( c ) ;

Console.WriteLine ( ) ;

PropertyInfo [ ] pi = t.GetProperties( ) ;
Console.WriteLine ( "Properties are:" ) ;
foreach ( PropertyInfo p in pi )
Console.WriteLine ( p ) ;

Console.WriteLine( ) ;

MethodInfo [ ] mi = t.GetMethods( ) ;
Console.WriteLine ( "Methods are:" ) ;
foreach ( MethodInfo m in mi )
{
if ( t == m.DeclaringType )
{
Console.WriteLine ( "Name: " + m.Name ) ;
ParameterInfo [ ] pif = m.GetParameters( ) ;
foreach ( ParameterInfo p in pif )
{
Console.WriteLine ( "Type: " + p.ParameterType ) ;
Console.WriteLine ( "Parameter Name: " + p.Name ) ;
Console.WriteLine( ) ;
}
}
}
}

Here we have first extracted the type of the class in a reference t of the Type class using the
typeof operator. Then we have displayed this name on the console. The Namespace property of
the Type class returns the name of the namespace in which the type is defined.

The Type class consists of methods such as GetConstructors( ), and GetProperties( ). These
methods return a reference to an array of references of types ConstructorInfo and PropertyInfo
respectively. These classes are declared in the System.Reflection namespace. In our program
we have called the GetConstructors( ) and the GetProperties( ) methods using the reference t
of type Type and collected the reference to arrays of type ConstructorInfo[] and PropertyInfo[]
in ci and pi respectively. Hence the returned values would contain information about the
constructors and properties of the test class. We have then used a foreach loop on the arrays
and displayed this information.

On similar lines we have called the GetMethods( ) method. This method returns a reference to
an array of references to the MethodInfo class objects. We have collected this returned
reference in mi. Next we have used a foreach loop on the array. Here we have first checked if
the method in the array belongs to the declaring class (test) or not. The property DeclaringType
is used to check the condition. This is done because we wish to display only those methods that
are defined in the test class and not the methods that are inherited in the test class from base
class (object class). We have then extracted the name of the method using the Name property of
the MethodInfo class and then displayed it. The GetParameters( ) method returns a reference to
an array of references to the ParameterInfo type that contains all the parameters that the method
accepts. Here we have collected this in an array called pif. Next we have used the
ParameterType and Name property of the ParameterInfo class to extract the type and name of

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

the parameters.

The get and set accessors, we know, are methods and hence they too are returned by the
GetMethods( ) method.

On similar lines the Type class has methods like GetEvents( ), GetFields( ), GetInterfaces( )
and GetMembers( ). These methods return arrays of types EventInfo[], FieldInfo[],
InterfaceInfo[] and MemberInfo[] respectively. On the other hand, methods such as
GetConstructor( ), GetEvent( ), etc. return a reference to a single object of the corresponding
type.

Retrieving Information about Custom Attributes

Attribute is a new feature of .NET., which add some declarative information about a type in
metadata. We can write our own attribute that are called as custom attributes. Using the
MemberInfo class of the Reflection namespace we can read this additional information of a type
written in metadata via custom attributes. Following code snippet shows how to read the custom
attribute Readme.

MemberInfo i = typeof ( Readme ) ;


object[ ] a = i.GetCustomAttributes ( false ) ;

foreach ( CodeRevisionAttribute att in a )


// use att to access various properties
Article: C# - File Input/Output - I

Perhaps the only thing that works faster than the computer is computing jargon. It moves very-
very fast. Often yesterday's rage is no longer today’s in–thing. Some jargon however has stuck
around for long. GIGO (garbage in and garbage out) for instance. It has been a ground since the
early days of computing. It has even matured over the years. Today GIGO happens automatically
through a process called serialisation…. A sure shot sign of man's progress!

.NET offers two classes for file operations—the File class and the FileInfo class. Both these
classes are defined in the System.IO namespace hence we need to write the statement using
System.IO in the program that uses File or FileInfo class.

The File class is derived from the Object class. It contains only static methods. We are not
allowed to create an object of the File class. The FileInfo class is derived from FileSystemInfo
class. The FileSystemInfo class is derived from the MarshalByRefObject class which in turn is
derived from the Object class. We can create an object of the FileInfo class. The hierarchy of
these classes is shown in Figure 1.

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

Figure 1

Let us now understand the objective of creating two classes for file operations. The static
functions of the File class can be called to perform various file operations without creating an
object. This avoids the overhead of creating objects. So, if we wish to carry out single operation
on the file, we can use the File class.

As against this, to call the member functions of the FileInfo class it is necessary to create an
object. This is because FileInfo class contains non-static member functions. So, if we wish to
carry out multiple operations on the file (with the preservation of state of the object) we can use
the FileInfo class. When we create a FileInfo object, all the relevant information of the file like
size, attributes, authentication permissions are stored in the data members. This information can
then be used by other functions while carrying out multiple operations. If we use the File class for
carrying out multiple operations then this information will have to be read each time we perform a
new operation.

Also, at times we are required to pass the file information to another application. In such a case it
is necessary to create a FileInfo object and then pass its state to other application (this process
is known as marshalling). Marshalling of object is possible only if the class is derived from the
MarshalByRefObject class. Since the object of the File class cannot be created, it has not been
inherited from MarshalByRefObject class.

Reading And Writing To A Text File

In the following program we will perform reading and writing operations on a text file. We plan to
write a few strings to a text file and then read them back from it.

namespace fileoperation
{
using System ;
using System.IO ;

class Class1
{
static void Main ( string[ ] args )
{
string str1 = "The .NET Revolution" ;
string str2 = "Long live C# " ;
string str3 = "Targeting the internet" ;
StreamWriter sw = new StreamWriter ( "C:\\file2.txt", false ) ;
sw.WriteLine ( str1 ) ;
sw.WriteLine ( str2 ) ;
sw.WriteLine ( str3 ) ;
sw.Close( ) ;
StreamReader sr = new StreamReader ( @"C:\file2.txt" ) ;
// @ ensures that we don't have to use C:\\
string str ;
do
{
str = sr.ReadLine( ) ;
Console.WriteLine( str ) ;
} while ( str != null ) ;
sr.Close( ) ;
}
}

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

To understand this program we must first know what a Stream is. A stream is a sequence of
bytes traveling from source to destination or traveling over a communication link. Two basic types
of streams that exist are Input stream and Output stream. An input stream is used for read
operations while an output stream is used for write operations.

Here we have created a new StreamWriter object and have passed false to the constructor of
the StreamWriter class along with the path. Here false specifies that if the file exists, it should be
overwritten. If we pass a true and if the file exists, it would be appended. In either case if the file
does not exist, a new file is created. The WriteLine( ) method of the StreamWriter class is
overloaded to write out entities like objects, bools, ints, etc. to a file.

Next, we have used a StreamReader class to perform the reading operation. Its ReadLine( )
method reads a line of characters from the current stream and returns the data as a string. This
process is repeated till the end of file is reached. The hierarchy of these I/O classes is shown in
Figure 2.

Figure 2

Article: C# - File Input/Output - II

Continued from last week...

Serialization

Serialization is the process of writing objects on a persistent storage media such as a file on the
disk. At a later time we may restore these objects by using the process of deserialization.

In the following program we have created a menu 'File' having the 'New', 'Open', 'Save',
'Generate' and 'Exit' menu items with names filenew, open, save, generate and exit
respectively.

When we select the 'Generate' menu item, shapes like line, rectangle, and ellipse should get
generated at random and in random colors as well as at random positions. On selecting the
'Save' menu item these shapes should be saved in a file. We must be able to load this file and
display the shapes again through the 'Open' menu item. When we click the 'New' menu item the
earlier shapes should vanish and the form should get cleared.

While saving the shapes, we should not save the image of the shapes. Instead we should save
the relevant information of the shapes using which we should be able to regenerate them again

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

when the file is loaded. This means that we must write the object containing the information about
the shape in the file while saving it and load it back while opening the file. This is done using
serialization and deserialization.

To make all these activities happen we need to add handlers for these menu items. Before we
add code to these menu handlers let us insert four new classes.

The first amongst these is the abstract class called shapes, which is shown below.

[Serializable]
abstract class shapes
{
protected int r, g, b ;

public shapes( )
{
Random rd = new Random( ) ;

r = rd.Next ( 255 ) ;
g = rd.Next ( 255 ) ;
b = rd.Next ( 255 ) ;

Thread.Sleep ( 5 ) ;
}
public abstract void draw ( Graphics g ) ;
}

In this class we have declared three data members r, g, and b representing red, green and blue
components to store the color of the shapes. We have also declared an abstract method in this
class called draw( ). The classes derived from shapes class would have to implement the
draw( ) method to be able to create their objects.

In the constructor we have generated random numbers using an object of the Random class.
The Next( ) method of the Random class generates a positive random number less than the
number passed to it. Using this method we have initialized the r, g and b data members.

The Thread.Sleep( ) method is used to halt the execution for a specified amount of time. In our
case it is 5 milliseconds. This is necessary because the Next( ) function uses a thread
mechanism to generate a random number. Hence, before the Next( ) method returns a random
number, the control moves on to the next statement in the constructor. So, unless we halt the
execution of the current thread for 5 milliseconds, r, g, b would not be set up properly. Thus, the
shape may not get drawn in a proper color.

The statement [Serializable] written before the class declaration is known as an attribute.
Attributes are attached to classes, methods, data member or any such entities. Attributes are
discussed at the end of this article. For the time being it is enough to understand that any class
that is attached with this attribute indicates that all the data members of the class can be
serialized i.e. can be written in a file, except for the data members that are marked with
[NonSerialized] attribute. We have not marked any data members as [NonSerialized] hence all
data members of the class would get written in a file.

The other three classes that we would add are line, rectangle and ellipse. These classes would
inherit the shapes class. The following code shows the declaration of the line class.

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

[Serializable]
class line : shapes
{
int x1, y1 ;
int x2, y2 ;

public line ( int i, int j, int k, int l )


{
x1 = i ;
y1 = j ;
x2 = k ;
y2 = l ;
}

public override void draw ( Graphics gg )


{
Color c = Color.FromArgb ( r, g, b ) ;
Pen p = new Pen ( c, 4 ) ;
gg.DrawLine ( p, x1, y1, x2, y2 ) ;
}
}

In this class we have declared four ints that are used to store the coordinates of the line. It also
consists of a constructor used to initialize these data members. We have implemented the
draw( ) method in this class that contains the logic to draw the line. We have attached the
[Serializable] attribute to this class also indicating that objects of this class can be serialized. On
similar lines the other two classes, rectangle and ellipse, are declared as follows:

[Serializable]
class rectangle : shapes
{
int x1, y1 ;
int width, height ;

public rectangle ( int x, int y, int h, int w )


{
x1 = x ;
y1 = y ;
height = h ;
width = w ;
}
public override void draw ( Graphics gg )
{
Color c = Color.FromArgb ( r, g, b ) ;
Pen p = new Pen ( c, 4 ) ;
gg.DrawRectangle ( p, x1, y1, width, height ) ;
}
}

[Serializable]
class ellipse : shapes
{
int x1, y1 ;
int width, height ;

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

public ellipse ( int x, int y, int h, int w )


{
x1 = x ;
y1 = y ;
height = h ;
width = w ;
}
public override void draw ( Graphics gg )
{
Color c = Color.FromArgb ( r, g, b ) ;
Pen p = new Pen ( c, 4 ) ;
gg.DrawEllipse ( p, x1, y1, width, height ) ;
}
}

After declaring the classes we need to add handlers for the menu items. The handler for the
'Generate' menu item is as shown below.

private void generate_Click ( object sender, System.EventArgs e )


{
Size sz = ClientSize ;
Random rd = new Random( ) ;

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


{
int x1 = rd.Next ( sz.Width ) ;
int y1 = rd.Next ( sz.Height ) ;
int x2 = rd.Next ( sz.Height - y1 ) ;
int y2 = rd.Next ( sz.Width - x1 ) ;

int shapeno = rd.Next ( 3 ) ;


switch ( shapeno )
{
case 0:
s.Add ( new line ( x1, y1, x2, y2 ) ) ;
break ;
case 1:
s.Add ( new rectangle ( x1, y1, x2, y2 ) ) ;
break ;
case 2:
s.Add ( new ellipse ( x1, y1, x2, y2 ) ) ;
break ;
}
}
Invalidate( ) ;
}

When we click the 'Generate' menu item this handler gets called. In this handler an object of the
Random class is created. We have used the Next( ) method of this class to not only decide
which shape should be generated but also the coordinates of this shape. The coordinates of the
shapes to be generated should not be greater than the coordinates of the form. Hence the
coordinates are generated using the Size of the form, which is available in the ClientSize
property of the form. Using these coordinates we have created ten random objects of rectangle,
ellipse or line class. While creating these objects the constructors of the respective classes get
called. Since all these classes are derived from the shapes class, firstly the base class

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

constructor gets called. This constructor selects a random color.

The references of objects of line, rectangle and ellipse are stored in a collection class called
ArrayList. The object of the ArrayList class is added as a data member of the form class by
writing the following statement,

ArrayList s = new ArrayList( ) ;

Using the Add( ) method we have stored all the objects of the line, ellipse and rectangle class in
the array list. Next we have called the Invalidate( ) method, which results in the Form1_Paint( )
event handler getting called. This event handler is shown below.

private void Form1_Paint ( object sender, System.Windows.Forms.PaintEventArgs e )


{
Graphics g = e.Graphics ;
foreach ( shapes t in s )
t.draw ( g ) ;
}

Here we do not know in what order the references of line, ellipse and rectangle classes are
stored in the array list. Hence we have extracted references from the array s one by one into a
reference t of type shapes. As the line, rectangle and ellipse classes are derived from shapes,
it is perfectly legitimate for a reference of shapes such as t to hold a reference of the derived
class. Using this reference we have called the draw( ) method. To this method we have also
passed an object of the Graphics class. Depending upon which (line, rectangle or ellipse)
reference is present in t, the draw( ) method of the appropriate class gets called and the
corresponding shape gets drawn. This was the reason behind deriving all the three classes from
a common class shapes. After clicking the 'Generate' menu the form appears as shown in the
following figure.

Article: C# - File Input/Output - III

Continued from last week...

If we wish to save the file we can click on 'Save' menu item. When we do so, save_Click( )
handler gets called. The handler is shown below:

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

private void save_Click ( object sender, System.EventArgs e )


{
SaveFileDialog sd = new SaveFileDialog( ) ;
sd.Filter = "dat files ( *.dat ) | *.dat" ;

if ( sd.ShowDialog( ) == DialogResult.OK )
{
FileInfo f = new FileInfo ( sd.FileName ) ;
Stream st = f.Open ( FileMode.Create, FileAccess.ReadWrite ) ;

foreach ( shapes t in s )
b.Serialize ( st, t ) ;
st.Close( ) ;
}
}

Here we have created an object of the SaveFileDialog class and used a "*.dat" filter for it. When
we type in a file name and click OK, a FileInfo object gets created with the selected filename.
The Open( ) function returns a Stream object associated with the file. We have collected it in a
Stream reference. Then we have used a BinaryFormatter object to serialize the objects. This
binary formatter is added as a data member of the form class as shown below:

BinaryFormatter b = new BinaryFormatter( ) ;

BinaryFormatter serializes and deserializes an object, in binary format. The Serialize( ) method
of this class serializes the object to the given stream. After serializing all the elements of the
array, we have closed the stream using the Close( ) method.

When we click 'Open' menu, the open_Click( ) event handler gets called. This handler is given
below:

private void open_Click ( object sender, System.EventArgs e )


{
OpenFileDialog od = new OpenFileDialog( ) ;
od.Filter = "dat files ( *.dat )|*.dat" ;

if ( od.ShowDialog( ) == DialogResult.OK )
{
FileInfo f =new FileInfo ( od.FileName ) ;
Stream st = f.Open ( FileMode.Open ) ;

while ( st.Position != st.Length )


s.Add ( b.Deserialize ( st ) ) ;

st.Close( ) ;
}
Invalidate( ) ;
}

Here firstly we have created an object of the OpenFileDialog class and displayed the dialog
using the ShowDialog( ) method. In this method too we have created a FileInfo object and
collected the corresponding Stream object of the specified file. Next we have used a while loop
to deserialize the objects until the end of stream is reached. The Deserialize( ) method
deserializes the specified stream into an object. We have collected these objects into our array by
using the Add( ) method, closed the stream and called Invalidate( ) function for painting these

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

shapes.

When we click 'New' menu item the following handler gets called:

private void filenew_Click ( object sender, System.EventArgs e )


{
s.Clear( ) ;
Invalidate( ) ;
}

Here we have cleared the array list by deleting all the elements in it using the Clear( ) method.
After this we have called Invalidate( ). This time the method Form1_Paint( ) draws nothing as
the array is empty, thereby resulting in a clean form.

On clicking the 'Exit' menu item the Dispose( ) method gets called and the form is disposed.

private void exit_Click ( object sender, System.EventArgs e )


{
Dispose( ) ;
}

Attributes

Attributes add extra information to a class, a method, data members, properties or any element to
which they are attached. The element to which we can attach an attribute is called the target of
the attribute. Attributes are attached using brackets and are written just before declaring the
target. For example, to mark any data member as non-serializable in the above program we
would use the [NonSerialized] attribute.

In our program, suppose we add a static data member called count to the shapes class to keep
a count of shapes generated. We would increment this data member in the constructor. Since
there is no need to serialize count we can declare it as non-serializable by attaching an attribute
[NonSerialized] with it. This ensures that when objects of the shapes class are written in a file,
all the data members of every object except count would get written in a file. This is how the
class declaration would look like:

[Serializable]
abstract class shapes
{
protected int r, g, b ;

[NonSerialized]
static int count ;

public shapes( )
{
Random rd = new Random( ) ;

r = rd.Next ( 255 ) ;
g = rd.Next ( 255 ) ;
b = rd.Next ( 255 ) ;

count++ ;

Thread.Sleep ( 5 ) ;

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

}
public abstract void draw ( Graphics g ) ;
}

Also, if we want to mark an int variable as dead or not in use, we have to mark it with an
Obsolete attribute:

[ Obsolete ]
int i ;

This marks i as obsolete and any use of i will result in an error. This example is not very practical
but it helps to understand what attributes are and how to attach an attribute to some element.

Attributes are aliases for their corresponding classes defining them. For example, Obsolete is an
alias for the System.ObsoleteAttribute class. All the functionality of the attribute is written in the
class. Some attributes accept parameters that are supplied inside pair of parenthesis immediately
after the name of the attribute. In the same way we have many predefined attributes in .NET
programming. .NET also allows us to write our own custom attributes.

Article: C# - Visual Inheritance

In Visual Studio 6.0, to display a dialog box, we derive a class from a pre-defined MFC class. The
event handlers and variables associated with controls get added to this user-defined class. All the
information about controls get stored in a separate '.rc' file. The compiler creates and displays
controls using information stored in the '.rc' file. Visual Studio 6.0 IDE provides facilities for adding
controls, variables for controls and handlers. So far so good. Now, consider a situation where an
extensive user interface on a dialog comprising of several controls exists and we want to reuse
this user interface in other application. What we would try is to inherit the dialog class creating the
user interface to create a new class. Major problem with this is that although we get access to the
base dialog class members, we don't get controls placed on the new dialog. This is because IDE
of Visual Studio 6.0 has no means to access the '.rc' file and render the controls according to the
information stored in it. So, our next step would be to copy all the controls from existing dialog
template and to paste them on the new dialog. Now we get the controls and the variables and
event handlers. But the problem here is that the code that associates controls with their variables
and handlers remains missing. So, reusing an existing user interface is far more different and
difficult than reusing an existing class.

Through 'Inheritance' we create a new class by using an existing class. Through 'Visual
Inheritance' we create a new form by using an existing form. When we inherit a form from an
existing form we also inherit controls, their properties, events and methods. So, the user interface
that is already created can be reused in a new application thereby reducing the repetitive
designing of controls. This makes Visual Inheritance a powerful weapon in this era of Rapid
Application Development. We can use visual inheritance in cases where we need to use the
same set of controls again and again.

Visual Studio.NET has incorporated visual inheritance as a part of .NET framework. Visual
inheritance is so called because it gives the visual expression of the inherited control objects.
Using Visual inheritance is a two step process:

- Creating Base Form


- Creating Derived Form

These steps are explained below.

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

Creating Base Form

Carry out the following steps to create a Base Form.

1. Create a Windows Application named 'baseform'.


2. Add a button having label as "Click" and Name as b. Also add a text box having Name as t. By
default, these variables get added
as private data members. Change the access modifiers to public through the Modifiers
property. If we change the Modifiers
property of a control to protected or public we would be able to change its properties in the
derived form. The controls marked as
private in the base form will be visible on derived form but will not be accessible through its
Name. This seems relevant because in
OOP inheritance also only protected and public members of a base class are visible to its
derived classes. In any case, we would
not be able to delete the derived controls from the form.
3. Add the Click event handler for the button and add following statement in it.

MessageBox.Show ( t.Text ) ;

4. Now since our form stands ready we can build it into a class library so that we can export the
form. Note that we cannot import a
form from an exe file. To build the project in a class library, right click the solution name in
Solution Explorer and select
Properties. The 'baseform Property Pages' would get displayed. Select the Output Type as
Class Library.

Now build the project to create 'baseform.dll'. This assembly contains the baseform.Form1 class
that we can inherit.

Creating Derived Form

1. Create another Windows Application named 'derivedform'.


2. Right click the solution name in Solution Explorer and select 'Add | Add Inherited Form' menu
option. The 'Add New Item' dialog
box gets displayed.
3. Select the 'Inherited Form' from the 'Templates' list and provide a name of your choice in the
'Name' text box. We have kept the
default name 'Form2.cs'.
4. The 'Inheritance Picker' dialog would get displayed. This dialog allows us to select an assembly
that contains the form we want to
inherit. For this, click the 'Browse' button. A dialog would appear from where we can select the
'baseform.dll' file and click the 'Open'
button.
5. Clicking the 'Open' button dismisses the dialog and displays the forms exported by the
assembly (an assembly can export any
number of forms) in 'Specify the component to inherit from' list control.
6. Select the form name from the 'Specify the component to inherit from' list control and click the
'OK' button. As soon as we click the
'OK' button, a new form derived from the 'baseform' gets displayed in the design editor. The file
'Form2.cs' also gets displayed in the
Solution Explorer as shown in Figure 1.

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

Figure 1

Figure 1 also displays reference of 'baseform.dll' being added in the 'References' tree in the
Solution Explorer. The derived form
displays the derived controls being added to the base form. These controls are accompanied
by a small icon at the top left corner to
distinguish between the derived controls and the new controls.
7. Open the 'Form1.cs' file. Change form name in Application.Run( ) method to Form2 as
shown below.

Application.Run ( new Form2( ) ) ;

This ensures that when we would execute the application, the new form, i.e. Form2, would get
displayed. If we enter the text in the
textbox and click the button the text would get displayed in a message box.

Let us now see how the whole thing works. To begin with the statement Application.Run ( new
Form2( ) ) gets executed. Here we are creating an object of the Form2 class which is derived
from the baseform.Form1 class. When we create an object of derived class, base class's
constructor gets called. So, in our case constructor of the baseform.Form1 class would get
called. This class is accessible to us since a reference to the 'baseform.dll' assembly is already
being added to our project. The compiler adds a call to the InitializeComponent( ) method in the
constructor of every form class. The InitializeComponent( ) method contains the code for
creating and customizing the controls. Once this method gets executed and controls get created,
the control returns to the constructor of the Form2 class. This constructor again calls the
InitializeComponent( ) method. This time the InitializeComponent( ) method of the Form2
class gets called. This is the reason why derived form contains the derived controls (initialized by
InitializeComponent( ) method of the baseform.Form1 class) and the new controls (initialized
by InitializeComponent( ) method of the Form2 class).

We have already added the Click event handler for the 'Click' button. We can override this
handler in the Form2 class and add our code in it. Now if we click the button, firstly, event handler
of the base class gets executed and then the overridden handler gets executed. This is because,
the InitializeComponent( ) method of the baseform.Form1 class gets executed first, wherein,
an address of the Click event handler defined in the baseform.Form1 class gets stored in the
Click delegate. Next the InitializeComponent( ) method of the Form2 class gets executed. In it,

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

the address of the Click event handler defined in the Form2 class gets added to the Click
delegate.

Article: C# - Structures And Enums - I

We have seen how to use classes in our programs. Whenever we needed to group dissimilar
data along with some functionality we used classes. Structures are similar to classes because
they too contain dissimilar data along with methods. A structure is defined using a struct
keyword. Consider the following example:

using System ;
namespace sample
{
struct employee
{
string name ;
int age ;
float sal ;

public employee ( string n, int a, float s )


{
name = n ;
age = a ;
sal = s ;
}

public void showdata( )


{
Console.WriteLine ( "Name: " + name ) ;
Console.WriteLine ( "Age: " + age ) ;
Console.WriteLine ( "Salary: " + sal ) ;
}
}

class Class1
{
static void Main ( string[ ] args )
{
employee e1 = new employee ( "Amit", 35, 25000 ) ;
e1.showdata( ) ;
}
}
}

In this program we have declared a structure called employee. This structure holds one string,
and two ints. It also consists of a three-argument constructor and a showdata( ) method. In
Main( ) we have declared a variable called e1 of the type employee. Here unlike C, we must not
write the struct keyword while defining structure variables. Note that even though we have used
new, space for employee gets allocated on the stack.

Structures vs Classes

In the previous example we could have replaced the struct keyword with class. This may give a

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

feeling that both structures and classes are alike. But in reality there are a lot of differences
between the two. They are listed below.

(a) We cannot add our own zero-argument constructor to the structure.


(b) The structures are implicitly sealed. Hence structures cannot be inherited.
(c) Being sealed, structures cannot be marked with an abstract modifier.
(d) Since structures cannot be inherited, its members cannot have protected access modifier.
Also there cannot be virtual functions in
structures.
(e) Structure members cannot be initialized at the point of declaration. For example,

struct mypoint
{
int i = 10 ;
int j = 20 ;
}

This results in an error. However if the data member is static we are permitted to initialize it.
(f) Structures are value types, whereas, classes are reference types.

The type of variable (value or reference) decides the storage and behavior of variables in the
.NET environment. This has a direct bearing on the programming efficiency.

Value Types and Reference Types

In C# variables are either value types or of reference types. The difference between the value
type and reference type is that the data of value type gets stored on the stack and that of the
reference type gets stored on the heap. The variables of the value types directly contain the data,
whereas, reference types contain references (or addresses) of the data. This is shown in
following figure.

Figure 1

To demonstrate the working of value type and reference type we would write two programs. The
following program shows a value type at work:

using System ;
namespace sample
{
struct mystruct
{
public int i ;
}

class Class1
{
static void Main ( string[ ] args )
{
mystruct x = new mystruct( ) ;
x.i = 9 ;

mystruct y ;
y=x;

y.i = 5 ;

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

Console.WriteLine ( x.i ) ;
Console.WriteLine ( y.i ) ;
}
}
}

The output of this program would be 9 5. Let us now understand how this program works. The
statement,

mystruct x = new mystruct( ) ;

creates a new structure variable x, which refers directly to the data. We have stored 9 in x. The
statement mystruct y ; too creates a structure variable y, which refers directly to the data. The
statement y = x assigns the value of x to y. Hence y would now hold 9 in it. Then the statement
y.i = 5 assigns the value 5 to y. Now y would hold 5 and x would continue to hold 9 in it. Thus
whenever we assign a structure variable to another structure variable the full contents of right-
hand side structure variable get copied in the left-hand side variable.

The difference between

mystruct x = new mystruct( ) ; and mystruct y ;

is that for x a default zero-argument constructor would get called, whereas, for y no constructor
would be called. The default zero-argument constructor sets the data members to their default
values. Since no constructor gets called for y its members do not get initialized. In such a case
we must take care to initialize the variables before their usage. In both the cases discussed
above memory is allocated on the stack.

Now let us see a reference type at work.

using System ;
namespace sample
{
class myclass
{
public int i ;
}
class Class1
{
static void Main ( string[ ] args )
{
myclass x = new myclass( ) ;
x.i = 9 ;

myclass y ;
y=x;

y.i = 5 ;
Console.WriteLine ( x.i ) ;
Console.WriteLine ( y.i ) ;
}
}
}

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

The output of this program would be 5 5. The statement,

myclass x = new myclass( ) ;

creates a variable x on the stack and creates an object on the heap. This object would be used to
hold the data. Here x is called a reference which refers (or points) to the object. In other words x
holds an address of the object. Through the statement x.i = 9 we have assigned the value 9 to
the object referred to by x. Then we have created a reference y through the statement myclass y
;. Since y is not assigned a value it would hold null in it. The statement y = x assigns the
reference stored in x to y. Hence y would now start referring to the same object referred by x.
The statement y.i = 5 ; would replace 9 from the object. Hence the output would be 5 5.

Article: C# - Structures And Enums - II

Continued from last week...

When To Use What

So when do we use structures and when do we use classes? This depends on the situation. For
example, if we wish to group together a few dissimilar data types, we must use structures
because being a value type it gets allocated on the stack. Memory allocation on a stack is always
faster than allocation on the heap.

On the other hand, if the structure is big then whenever we pass the structure variable as a
parameter or assign it to another structure variable, the full contents of the structure variable gets
copied. As against this for a class only the reference is copied. It is more efficient to copy a 4-byte
reference than copying the whole structure.

Data Types Revisited

C# data types are divided into value types and reference types. Value types contain structures,
and enumerations, whereas, references types are complex types such as classes, interfaces,
delegates and arrays. Then where do the primitive data types (int, float, char etc.) stand?
Actually primitive data types are structures. This is because C# compiler maps primitive data
types to a set of predefined structures defined by .NET base class library. For example, the
keywords int, float, etc. are simply aliases of the predefined struct types present in the System
namespace, as shown in following table.

Keyword Aliased type


sbyte System.Sbyte
byte System.Byte
short System.Int16
ushort System.Uint16
int System.Int32
uint System.UInt32
long System.Int64
ulong System.UInt64
char System.Char
float System.Single

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

double System.Double
bool System.Boolean
decimal System.Decimal

The primitive data types being structures, they can call functions defined in those structures. For
example to convert an integer to a string we can write the following code:

int n = 10 ;
string s = n.ToString( ) ;

C# supports two more primitive data types: object and string. They are of reference types and
are mapped to the System.Object class and System.String class respectively.

User-defined structures and classes by default get derived from the System.Object class. Even
all .NET classes and structures are derived from the System.Object class. Enumerated data
types and arrays too get mapped to the .NET base classes in some way or the other. Even
though the structures cannot have virtual functions they can have override methods. This is
because structures are derived from the System.Object class. Using the override methods we
can override the virtual methods of the System.Object class.

Boxing And Unboxing

C# provides the flexibility to use value types as reference types (objects) as and when required.
Whenever a value type is converted into a reference type it is known as boxing. On the other
hand when a reference type is converted into a value type it is known as unboxing. For example,

int i = 10 ;
object o = i ; // boxing
i = ( int ) o ; // unboxing

This is a simple example where we have first "boxed" an int into an object (reference type) and
then extracted the value back into an int variable. Note that boxing will always be implicit,
whereas, unboxing is explicit. This is because while unboxing we extract the value from an object
type and hence we are never aware of its actual type i.e. whether it is an int, float, char, etc. So
we explicitly have to determine the type we want back. On the other hand while boxing, we need
not bother about the type and just box it into the object. This is because all value types are
inherited from the object class.

Where do we need to use boxing? Boxing generally occurs while passing arguments to a method.
If we pass a value type to a method that was expecting a reference type, the compiler boxes the
value type into an object or System.Object. Consider the following example:

int i = 12 ;
myclass c1 = new myclass ( 10 ) ;
Console.WriteLine ( "The value is {0} {1}", i, c1 ) ;

Here we have passed three arguments to the WriteLine( ) method. This includes a string, an int
and a class type. The WriteLine( ) method has been written to accept a string followed by a
params array of object class. The declaration of WriteLine( ) is as follows:

WriteLine ( string s, params object[ ] o ) ;

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

The notations {0} and {1} represent the positions of the arguments in the list being printed. All the
arguments except the first are collected in the params array of object class. Hence there is no
restriction on number of parameters being printed in the list.

In the WriteLine( ) method we have passed an int variable when the method is expecting an
object. Hence the compiler converts the int variable (value type) into an object (reference type)
using boxing and collects it as the first element of the params array of objects. Then we have
passed an object of the class myclass which would be collected as the second element of the
array. This object being a reference type it would not get boxed. Recall that every reference and a
value type is derived from the object or System.Object class. So whatever is passed to
WriteLine( ) method can be collected as an object. Hence the Console class does not have
overloads of the WriteLine( ) method for an int, float, char, and so on.

Enumerations

An enumeration (enum) is a special form of value type, which inherits from the System.Enum
class. An enum consists of some underlying data types. The underlying type must be one of the
built-in signed or unsigned integer types (such as short, int, or long). These data types are
static and have constant values. Each field is assigned a specific value of the underlying type by
the programmer or the compiler. We can access the enum members using the enum name
followed by a dot. All members in an enum are public members. Following example illustrates its
usage.

using System ;
namespace sample
{
enum color
{
red, blue, green
}
class Class1
{
static void Main ( string[ ] args )
{
Console.WriteLine ( " {0} ", color.red ) ;
}
}
}

The output of the program would be red. If we want to see the value we must write the following
statement:

Console.WriteLine ( ( int ) color.red ) ;

Here the output would be 0. We can also change the underlying data type (which is int by default)
as in the following program. We have also provided an initial value to one of the members of the
enum.

using System ;
namespace sample
{
enum color : byte
{
red, blue = 8, green

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

}
class Class1
{
static void Main ( string[ ] args )
{
Console.WriteLine ( color.green ) ;
}
}
}

The output of the program would be green. But here we have to be careful that we should not
use a value, which is out of range, for example assigning a value like 500 to red in this program
will result in error since we have declared that the enum is of type byte. Using,
Console.WriteLine ( ( byte ) color.green ) instead of Console.WriteLine ( color.green ) in
Main( ) would give the output as 9. All members towards the right of blue will be initialized to a
value equivalent to blue's value plus the number of places it is far from blue. green is one place
right from blue, its value will be 8 + 1 i.e. 9. This is not true for members on the left hand side. So
in this case red will be initialized to 0 by the compiler. However we can initialize all the members
with different values. Any uninitialized member will be initialized to a value according to its
position from the last initialized one. This would be evident from the following program.

using System ;
namespace sample
{
enum color
{
red = 8, blue, green = 7, yellow, brown
}
class Class1
{
static void Main ( string[ ] args )
{
Console.WriteLine ( ( int ) color.red + " " + ( int ) color.yellow ) ;
}
}
}

The output of this program would be 8 8.

There are a few more important points to note regarding enums:


1. We can give same values to two enum members.
2. An enum cannot have a circular definition. For example,

enum color
{
red = yellow, blue, green, yellow, brown
}

The compiler will first try to give red yellow's value. But yellow's value depends on red's value.
Hence yellow has no value yet and will be assigned a value later. This is circular dependency
and is not allowed.

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

3. The value of enum members cannot be changed.


4. An enum cannot have two members with the same name.
5. We cannot inherit from enums.

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

Article: C# - Creating Collection Classes

Creating efficient data structures has always been a nightmare of programmers. But while writing
a C# program the last thing on our mind is how to build a data structure. .NET Foundation Class
Library contains a namespace called System.Collections that provides classes to manage data
structures like arrays, lists and maps. It also provides interfaces to enumerate and compare the
elements of collections. Let us first discuss in brief the classes available for maintaining the
above-mentioned data structures.

The ArrayList class is similar to the Array class except that its size can grow dynamically. Like
the Array class, the ArrayList class contains various methods to perform functions like adding,
inserting, removing, copying, etc. The Queue and Stack classes provide the 'First In First Out'
and 'Last In First Out' type of collection respectively. The base class library provides a class
called BitArray that allows us to create an unusual array-array of bits. If we provide an int array,
the bits array gets created with the bit values of every element of the array. The Hashtable and
SortedList classes manage a collection of key-value pairs. The difference between the
Hashtable and SortedList class is that in the SortedList class, the values are sorted by keys
and are accessible by key as well as by index.

Using these classes is straightforward and is dealt with in enough details in several popular C#
books. We simple have to instantiate an object of the relevant collection class and call its
methods. The difficult programming is involved when we have to provide collection support to our
class. Let us see what 'collection support' means.

A collection is a set of same type of objects that are grouped together and that is able to supply a
reference to an enumerator. An enumerator is an object that iterates through its associated
collection. It can be thought of as a movable pointer pointing to any element in the collection. In
order to provide an enumerator, a class must implement the IEnumerable interface. If a class
implements IEnumerable interface, we can use an object of the class in foreach statement. We
would now see an example that shows how to provide enumeration support to our class.

We would write a class sample having an int array named arr as a data member. The sample
class would implement the IEnumerable interface so that we can enumerate through the array
arr using the foreach statement. Here is the code.

using System ;
using System.Collections ;

class sample : IEnumerable


{
int[ ] arr = { 10, 11, 12, 13, 14 } ;

class myenumerator : IEnumerator


{
int c ;
sample s ;

public myenumerator ( sample ss )


{
c = -1 ;
s = ss ;
}

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

public object Current


{
get
{
return s.arr [ c ] ;
}
}

public bool MoveNext( )


{
if ( c < s.arr.Length - 1 )
{
c++ ;
return true ;
}
else
return false ;
}
public void Reset( )
{
c = -1 ;
}
}

public IEnumerator GetEnumerator( )


{
return new myenumerator ( this ) ;
}
}

The IEnumerable interface declares only one method GetEnumerator( ). The GetEnumerator( )
method returns reference to the enumerator object. We have to write our own enumerator so that
it would enumerate our collection. To create an enumerator we have to write a class that
implements the IEnumerator interface. Here our enumerator class is myenumerator.

In the GetEnumerator( ) method we have created an object of myenumerator class and passed
to its constructor the this reference. This is necessary because, we have to access arr in the
methods of myenumerator class. We have implemented the methods of IEnumerator interface-
MoveNext( ) and Reset( ) and a property called Current.

Let us now understand how an enumerator works. When an enumerator object is initialised, it
does not point to any element of the collection. We must call the MoveNext( ) method that moves
the enumerator to the first element of the collection. We can retrieve this element by calling the
Current property. We can do whatever we want with this element. Then we must move to the
next element by calling the MoveNext( ) method again. If we want to enumerate the collection
again we can call the Reset( ) method that returns before the beginning of collection.

Our implementation of MoveNext( ), Reset( ) and Current does the same. Now, we can use the
foreach statement on an object of the class sample as shown below.

sample s = new sample( ) ;


foreach ( int i in s )
Console.WriteLine ( i ) ;

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

The foreach statement works like this.

IEnumerator e = s.GetEnumerator( ) ;
while ( e.MoveNext( ) )
Console.WriteLine ( e.Current ) ;

The foreach statement would terminate when the MoveNext( ) method would return false.

Note that it is necessary to design a separate class implementing the IEnumerator interface
rather than implementing it in the collection class itself. If we implement the IEnumerator
interface in the collection class, we would face problem when enumerating same object again.

Article: C# - Event Driven Programming With WinForm

Windows applications that we create fall under two major categories-managed and unmanaged.
Unmanaged Windows applications can be created using Microsoft Foundation Classes (MFC).
Managed application run under Common Language Runtime (CLR) and are created using .NET
Framework Class Library. These applications are called WinForm applications. WinForms
(Windows Forms) create graphical user interface (GUI) for Windows applications. A form is a top-
level window of an application. It can be a window, a dialog or a multiple document interface
(MDI) window.

Creating WinForms has many advantages over creating applications using MFC. In unmanaged
Windows-based programs, we need to apply certain styles to the window only when it is created.
WinForms eliminate this quirk. If we apply styles that are meant to be applied at creation time,
.NET destroys the previous window and creates a new one with new styles.

.NET Framework Class Library is richer than MFC. At the same time, the classes remain same for
all the .NET compliant languages. All the classes that are used to create and design a WinForm
are encapsulated in System.Windows.Forms namespace. For example, the
System.Windows.Forms.Form class is used to create the form,
System.Windows.Forms.Button class is used to create a button and so on. To create a GUI, we
place components and controls on the form and so, a form acts as a container of components
and controls. To create the GUI we drag and drop the controls from Toolbox and change their
properties to suit our requirements. When we drag the control on form and change properties,
Visual Studio.NET generates suitable code for us. However, only adding controls to create a user
interface is not enough. Our application must also respond when the user interacts with the
application. User can interact with the application by moving the mouse, clicking the mouse
button, pressing a key, clicking on a button, etc. Whenever user interacts with the GUI, events are
generated. Events are notifications sent to the container, which can then respond to it. For
example, when we click a button, an event is generated notifying that user has clicked the button.
In response, we can display a message box or do something else. This job is done in methods
called 'event handlers'. When a particular event is generated, corresponding event handler gets
called to process the event. For calling the event handlers .NET takes help of events and
delegates.

An event in C# is a multicast delegate having a predefined prototype. The prototype is such that
every event returns a void and always accepts two parameters. The first parameter is always a
reference to an object of System.Object class and the second parameter is always a reference
to an object of the System.EventArgs class or a class derived from it. The EventArgs object
contains information about the event. The object that raises an event is called an 'event raiser'
and the object that receives an event is called an 'event receiver'. The event raiser class always
declares the event and the receiver class must have an event handler to handle that event. The
first parameter collected by the event handler is always a reference to an event raiser object. The

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

addresses of event handlers are stored inside the events (remember that events are actually
delegates) and hence they also must have the same signature as the event. Such kind of a
delegate is declared using the keyword event. To understand events, consider the following
program.

using System ;
namespace Sample
{
public class mouseeventargs
{
public int x, y ;
public mouseeventargs ( int x1, int y1 )
{
x = x1 ;
y = y1 ;
}
}

public delegate void click ( object m, mouseeventargs e ) ;

public class MyForm


{
public event click c1 ;
public void mouseclick( )
{
mouseeventargs m = new mouseeventargs ( 10, 20 ) ;
c1 ( this, m ) ;
}
}
class MyForm1 : MyForm
{
public MyForm1( )
{
c1 += new click ( button_click ) ;
mouseclick( ) ;
}
public void button_click ( object m, mouseeventargs e )
{
Console.WriteLine ( "Mouse Coordinates: " + e.x + " " + e.y ) ;
Console.WriteLine ( "Type is: " + m.GetType( ).ToString( ) ) ;
}
static void Main ( string[ ] args )
{
MyForm1 f = new MyForm1( ) ;
}
}
}

In this program we have declared 3 classes-mouseeventargs, MyForm and MyForm1 derived


from MyForm. The mouseeventargs class corresponds to the EventArgs class. This class
contains two int variables x and y and a constructor to initialize them. We have declared a
multicast delegate click whose signature is same as the event handler button_click( ). The
MyForm class here is an event raiser class and hence contains an event as a data member
called c1 of the type click. It also contains a method called mouseclick( ). In this method we
have created an object of the mouseeventargs class. In the statement,

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

c1 ( this, m ) ;

c1 encapsulates the button_click( ) method. this contains the reference of MyForm object
(event raiser) and m is a reference of the mouseeventargs object. In the MyForm1 class, we
have defined the method button_click( ) (i.e. event handler). When the compiler encounters the
statement c1 += new click (button_click), it creates an event object (delegate object) that wraps
up button_click( ) method. So whenever the c1 event is raised (or called, as in this program), the
method button _click( ) would get executed.

We could call a method even using a delegate. Then what are events for? Take a look at the
following statement.

c1 = new click ( button_click ) ;

where, c1 is a delegate reference. This statement has a bug. Here, we are assigning a new
delegate object to c1 and so, all the delegates previously added are now lost. Instead of =
operator we should have used += operator to add a new delegate object to the delegate list. This
would never happen in case of events. This is because we can perform only two operations on
events, namely, += and -=. We cannot use = operator with events. As such events provide a
protection layer on delegates. When we use the += and -= operators with delegates, they get
converted into a call to Delegate.Combine( ) and Delegate.Remove( ) methods. If we use +=
and -= operators with events they get converted into a call to add_c1( ) and remove_c1( )
methods. These methods in turn call the Delegate.Combine( ) and Delegate.Remove( )
methods.

WinForms also follow the same mechanism. Only thing is, we don't need to invoke the event
handlers ourselves. They get called automatically when events occur. The compiler adds suitable
code such that when an event occurs our event handler would get called. Let us now see what
code gets generated when we create a WinForm application and add an event handler.

The minimal code that is required to create a WinForm application is given below:

using System ;
using System.Windows.Forms ;
namespace WinFormDemo
{
public class Form1 : Form
{
static void Main( )
{
Application.Run ( new Form1( ) ) ;
}
}
}

Here, we have derived a class Form1 from the Form class and passed a reference to its object
to the Application.Run( ) method. This method creates the form, displays it on screen and starts
a message loop for it. Of course, we don't need to write this code, Wizard generates it for us. If
we add a control to the form, a reference to the class representing the control gets added to the
class as a private member. If we add a button the reference to the Button class would get added
as shown below.

private System.Windows.Forms.Button button1 ;

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

The reference button1 would get initialized in the InitializeComponent( ) method as given
below.

this.button1 = new System.Windows.Forms.Button( ) ;

On adding a handler for the Click event, the code generated for it looks as given below.

this.button1.Click += new System.EventHandler ( this.button1_Click ) ;

The EventHandler is a delegate defined in the System namespace. This statement wraps the
EventHandler around the button1_Click( ) method so that when the Click event is fired,
button1_Click( ) method would get called. The definition of button1_Click( ) method is shown
below.

private void button1_Click ( object sender, System.EventArgs e )


{
}

The first parameter passed to button1_Click( ) method identifies the object that fired the event
(button1 in this case). The second parameter contains additional information about the event.
The objects of every control class fire events and now you can appreciate how easy it is to handle
these events under .NET.

Article: C# - GDI+ - An Extension To GDI - I

If you have programmed under Windows you are familiar with the term GDI (Graphical Device
Interface). GDI simplifies drawing by providing an interface to the hardware devices like screen or
printer such that the programmers don't need to bother about hardware details and their
differences. The same program can work on different display adapters, printers, keyboards, etc.
without modifying it.
.NET uses GDI+, an extension to GDI, which further simplifies drawing. GDI+ has added several
new features like graphics paths, support to image file formats, image transformation, etc. GDI+
has also modified the programming model by introducing fundamental changes in the
programming model used by GDI.

Changes In Programming Model

GDI uses an idea of Device Context (DC). Device Context is a structure that stores all the
drawing related information viz. features of display device and attributes that decide the
appearance of the drawing. Every device context is associated with a window. To draw on a
window, one must first obtain a device context of that window. If we want to change any attribute,
say, pen color we first select it in the device context by calling the SelectObject( ) method. Once
selected all the drawing is done using this pen unless and until we select another pen in device
context.

GDI+ works with 'graphics context' that plays similar role as device context. The graphics context
is also associated with a particular window and contains information specifying how drawing
would be displayed. However, unlike device context it does not contain information about pen,
brush, font, etc. If we want to draw with new pen we simply have to pass an object of Pen class to
the DrawLine( ) method (this method draws line on window). We can pass different Pen objects
in each call to DrawLine( ) method to draw the lines in different colors. Thus GDI uses a stateful
model, whereas, GDI+ uses a stateless model. The Graphics class encapsulates the graphics
context. Not surprisingly, most of the drawing is done by calling methods of the Graphics class.

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

Working With GDI+

We would see how to draw text and graphics using GDI+ by writing a small program. Create a
Windows Application. Windows programmers know that a window receives WM_PAINT message
when it is to be painted. We need to handle this message if we want to do any painting in the
window. In .NET to do this we can either override the virtual method OnPaint( ) of the Form class
or write a handler for the Paint event. The base class implementation of OnPaint( ) invokes the
Paint event handler through delegate. Hence we should write our code in the Paint event
handler.

Add the Paint handler to the form. The Form1_Paint( ) handler would look like this.

private void Form1_Paint ( object sender, PaintEventArgs e )


{
}

The first parameter passed to the Form1_Paint( ) handler contains the reference to the object of
a control that sends the event. The second parameter contains more information about the Paint
event. We would first see how to display a string on the form. To display the string we would use
DrawString( ) method of the Graphics class.

private void Form1_Paint ( object sender, PaintEventArgs e )


{
Graphics g = e.Graphics ;
Font myfont = new Font ( "Times New Roman", 60 ) ;
StringFormat f = new StringFormat( ) ;
f.Alignment = StringAlignment.Center ;
f.LineAlignment = StringAlignment.Center ;
g.DrawString ( "Hello!", myfont, Brushes.Blue, ClientRectangle, f ) ;
}

The Graphics property of the PaintEventArgs class contains reference to the Graphics object.
We can use this reference for drawing. In a handler other than Paint event handler we can obtain
the Graphics reference using the CreateGraphics( ) method of the Form class. The
DrawString( ) method has several overloaded versions. We used one that allows us to display
centrally aligned text in desired font and color. The first parameter passed to the DrawString( )
method is the string we wish to display. The second parameter is the font in which text would get
displayed. We have created a font by passing the font name and font size to the constructor of
the Font class. The text gets filled with the brush color specified as the third parameter. The
fourth parameter specifies the surrounding rectangle. We have passed ClientRectangle property
of Form class that contains a rectangle representing the client area of the form. To centrally align
the text we have used the StringFormat class. The Alignment and LineAlignment properties of
this class contain horizontal and vertical alignment of text respectively.

The Graphics class contains various methods to draw different shapes. This includes drawing
rectangle, line, arc, bezier, curve, pie, etc. We would add the code in Form1_Paint( ) handler that
draws rectangles in different pens and brushes. You would be able to draw other shapes on
similar lines.

The following code draws a rectangle using green colored pen having line thickness of 3.

Pen p = new Pen ( Color.Green, 3 ) ;


g.DrawRectangle ( p, 20, 20, 150, 100 ) ;

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

The Pen class encapsulates various styles of pens like solid, dash, dash-dot, etc. We can change
the style of pen using the DashStyle property of the Pen class. This is shown in the following
statement.

p.DashStyle = DashStyle.Dash ;

If we want, we can specify custom pen style by using the DashPattern property. There are
several other properties of the Pen class that allow us to specify the pen type (hatch fill, gradient
fill, solid color, etc), cap style, join style, etc.

Unlike GDI, GDI+ provides separate methods for rectangle and filled rectangle. To fill the
rectangle we need to pass a Brush object. This is shown below.

HatchBrush hb = new HatchBrush ( HatchStyle.BackwardDiagonal,


Color.Red, Color.Black ) ;
g.FillRectangle ( hb, 200, 20, 150, 100 ) ;

We have used hatch brush to fill the rectangle. The hatch brush is created using the HatchBrush
class. We have mentioned the hatch style as BackwardDiagonal. The rectangle will get filled
with the hatch brush in red and black color combination. Like the HatchBrush class there are
several other classes used to fill the shapes with viz. SolidBrush, TextureBrush, and
LinearGradientBrush. Gradient brush is something that was not available in GDI. Let us see
how to use it.

LinearGradientBrush gb = new LinearGradientBrush ( ClientRectangle, Color.BlanchedAlmond,


Color.Aquamarine, 90 ) ;
g.FillRectangle ( gb, ClientRectangle ) ;

Here, we have created an object of the LinearGradientBrush class and passed to its constructor
the rectangle to be filled, and two colors that form the gradient pattern. The last parameter
specifies the angle from which we wish to draw. Specifying 90 would fill the window vertically.

Article: C# - GDI+ - An Extension To GDI - II

...Continued from last week

Coordinates And Transformations

In the Graphics methods we specify coordinates in two-dimensional coordinate system. The


system has origin at left-top corner and x and y axes point to right and down respectively. All the
methods take coordinates in pixels. The coordinates passed to Graphics methods are world
coordinates. When we pass world coordinates to a method, they firstly get translated into page
coordinates (logical coordinates) and then into device coordinates (physical coordinates).
Ultimately, the shape gets drawn in device coordinates. In both the page and device coordinate
system the measure of unit is same i.e pixels. We can customize the coordinate system by
shifting the origin to some other place in client area and by setting a different measure of unit. Let
us see how this can be achieved. We would first draw a horizontal line having 1 inch of width.
Here is the code to do this.

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

private void Form1_Paint ( object sender, PaintEventArgs e )


{
Graphics g = e.Graphics ;
g.PageUnit = GraphicsUnit.Inch ;
Pen p = new Pen ( Color.Green, 1 / g.DpiX ) ;
g.DrawLine ( p, 0, 0, 1, 0 ) ;
}

Here firstly we have set the PageUnit property to GraphicsUnit.Inch specifying that the unit of
measure is an inch. We have created a Pen object and set its width to 1 / g.Dpix. The Dpix
property of the Graphics class indicates a value, in dots per inch, for the horizontal resolution
supported by this Graphics object. Note that this is necessary because now Pen object also
assumes 1 unit = 1 inch. So, if we don't set the pen width like this, a line with 1 inch pen width
would get drawn. Next we have drawn a line having one unit measure, which happens to be an
inch.

Let us now shift the origin to the center of the client area and draw the line again.

private void Form1_Paint ( object sender, PaintEventArgs e )


{
Graphics g = e.Graphics ;
g.PageUnit = GraphicsUnit.Inch ;
g.TranslateTransform ( ( ClientRectangle.Width / g.DpiX ) / 2, ( ClientRectangle.Height /
g.DpiY ) / 2 ) ;
Pen p = new Pen ( Color.Green, 1 / g.DpiX ) ;
g.DrawLine ( p, 0, 0, 1, 0 ) ;
}

Here, after setting the unit to inches using the PageUnit property, we have called the
TranslateTransform( ) method to shift the origin to the center of the client area. This method
maps the world coordinates to page coordinates and so the transformation is called world
transformation. The x and y values we have passed to the TranslateTransform( ) method get
added to every x and y values we pass to the Graphics methods. Finally, we have created a pen
having proper width and drawn the line.

GDI+ also allows us to orient the x and y axes's direction to the specified angle. For this, it
provides the RotateTransform( ) method. For example, if we call the RotateTransform( )
method before drawing the line as shown below,

g.RotateTransform ( 30 ) ;

then line would get displayed slanting downwards, 30 degrees below the base line. We can use
this functionality of the RotateTransform( ) method to create an application like analog clock.

Disposing Graphics Objects

Whenever we open a file, we close it after we have finished working with the file. This is because
a handle is associated with the file that remains open if we don't close it explicitly. Similarly, GDI+
resources like pens, brushes, fonts need to be disposed of because they encapsulate GDI+
handles in them. To release the GDI+ resources, we can call the Dispose( ) method on every
object that is to be released. For example, following statement would release the pen object
represented by penobject using the Dispose( ) method.

penobject.Dispose( ) ;

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

We must also release the Graphics object obtained by calling the CreateGraphics( ) method.

Article: C# - Reading Metadata Using Reflection

Every managed application in .NET is deployed as an assembly and every assembly defines
certain types. These types are revealed in the form of metadata. Metadata is the data written in
binary form in Portable Executable (PE) file. Metadata gives a detailed description of types and
external assemblies that are used by the types. For example, metadata of a class would
completely define the class including its methods, parameters of methods, calling convention,
class's data members and visibility of class members. We can read this information from
metadata using reflection. .NET base class library has provided namespaces and classes for this
encapsulated in System.Reflection namespace. Using reflection we can read types from
assembly, create instances of types dynamically, invoke methods, etc. Before we discuss how to
use reflection technology, we would see how types are arranged in metadata and what purpose
does metadata serve.

One of the biggest benefits of .NET is that code written for it can be used by different languages.
A function defined in VC++ can be called from VB. But as both the languages use different syntax
there must be some common format to enable interoperability. This common format is metadata.
Another benefit of using metadata is that it eliminates need of specifying the import library in the
linker options. This is possible because metadata is written in the same EXE or DLL file as the
code itself. The information in metadata is arranged in the following hierarchy.

Reflection allows us to either read data from assembly or write data to assemblies. The
System.Reflection namespace contains classes to read an assembly, whereas,
System.Reflection.Emit namespace contains classes to write to the assembly. In this article, we
would firstly create an application that lists all the types of selected assembly. Then, on selecting
a type its members get displayed.
Create a Windows Application and design a form as shown in the following figure.

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

The variables and events of different controls in the form are given in the following table.

Control Variable Event


TextBox aname
Load Button load Click
Types ListBox list SelectedValueChanged
Methods and
Constructors listmethods
ListBox
Properties ListBox listprop
Events ListBox listeve

Also add the OpenFileDialog control to the form. On clicking the 'Load' button the standard
'Open' dialog box gets displayed. If user selects an assembly and clicks the OK button, its path
gets displayed in the text box, the assembly gets loaded in memory and its types get displayed in
the list box. To do this, we have added the Click event handler as shown below.

private void load_Click ( object sender, System.EventArgs e )


{
openFileDialog1.InitialDirectory = @"C:\WINDOWS\Microsoft.NET\Framework\v1.0.3705" ;
openFileDialog1.Filter = "Assemblies (*.dll)|*.dll" ;

if ( openFileDialog1.ShowDialog( ) == DialogResult.OK )
{
list.Items.Clear( ) ;
aname.Text = openFileDialog1.FileName ;
Assembly a ;
try
{
a = Assembly.LoadFrom ( aname.Text ) ;
tarray = a.GetExportedTypes( ) ;
}
catch ( Exception ex )
{

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

MessageBox.Show ( "Error in loading assembly" ) ;


return ;
}
foreach ( Type type in tarray )
list.Items.Add ( type.FullName ) ;
list.SetSelected ( 0, true ) ;
}
}

Here, firstly we have set the default folder where all .NET framework assemblies are stored. We
have also set the Filter property to '.dll' so that only assemblies would be listed in the dialog. To
load the selected assembly, we have read the assembly path from the text box and called the
LoadFrom( ) static method of the Assembly class. This method returns a reference to the
Assembly object. Using this reference, we have called the GetExportedTypes( ) method that
returns an array of types available in the assembly. tarray is an array of Type objects. Add this
array as a private data member. The types returned by the GetExportedTypes( ) method are
added to the list box in the foreach loop using the Add( ) method.

Now let us write the code to display type members in respective list boxes, if any type is selected.
The SelectedValueChanged event handler is given below.

private void selchange ( object sender, System.EventArgs e )


{
int index = list.SelectedIndex ;
Type t = tarray [ index ] ;

listmethods.Items.Clear( ) ;
listprop.Items.Clear( ) ;
listeve.Items.Clear( ) ;

ConstructorInfo [ ] ci = t.GetConstructors( ) ;
foreach ( ConstructorInfo c in ci )
listmethods.Items.Add ( c ) ;

PropertyInfo [ ] pi = t.GetProperties( ) ;
foreach ( PropertyInfo p in pi )
listprop.Items.Add ( p ) ;

EventInfo [ ] ei = t.GetEvents( ) ;
foreach ( EventInfo ev in ei )
listeve.Items.Add ( ev ) ;
MethodInfo [ ] mi = t.GetMethods ( BindingFlags.Instance |
BindingFlags.DeclaredOnly | BindingFlags.Public |
BindingFlags.NonPublic ) ;
String str = "" ;
foreach ( MethodInfo m in mi )
{
if ( t == m.DeclaringType )
{
str = m.Name ;
str += " ( " ;
ParameterInfo [ ] pif = m.GetParameters( ) ;
foreach ( ParameterInfo p in pif )
{

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

str += p.ParameterType ;
str += " " ;
str += p.Name ;
str += ", " ;
}
int c = str.LastIndexOf ( ',' ) ;
if ( c != -1 )
str = str.Remove ( c, 1 ) ;
str += " )" ;
listmethods.Items.Add ( str ) ;
}
}
}

To display members we must first obtain the item selected from the list box. We have done so by
using the SelectedIndex property of the ListBox class. We have retrieved the selected type from
the tarray array.

The Type class contains various methods to access members of a type. We have used the same
to read constructors, methods, properties and events of the selected type. These methods return
a reference to an array containing respective members. We have listed the members in the
respective list boxes. To the GetMethods( ) method we have passed certain flags. These flags
indicate that we intend to read the instance methods, methods that are not inherited from base
type and methods that are public as well as non-public. We can mention this flag in all the other
methods also. Since method name and its parameters need to be read separately, we have used
string concatenation to form a string that looks like a prototype declaration of method. Again, we
have listed only those methods that directly belong to this type. We have used the DeclaringType
property of the MethodInfo class.

We would now see a small example that loads a user-created assembly, obtains a class type,
creates its instance and invokes a method defined in the assembly. Here is the code…

Assembly a = Assembly.LoadFrom ( "c:\\mymath.dll" ) ;


Type t = a.GetType ( "mymath" ) ;
MethodInfo m = t.GetMethod ( "add" ) ;
Object obj = Activator.CreateInstance ( t ) ;
Object[ ] arg = new Object [ 2 ] ;
arg [ 0 ] = 10 ;
arg [ 1 ] = 20 ;
m.Invoke ( obj, arg ) ;

mymath is the name of class written in 'mymath.dll'. To the GetMethod( ) method we have passed
the name of the method we want to invoke. Next, by calling the CreateInstance( ) method we
have created an object of type stored in t and collected its reference in obj. The add( ) method
takes two integers. So, we have created an array of objects arg. Lastly, we have called the add( )
method by using the Invoke( ) method. The add( ) method adds the two integers passed to it and
displays the result.

Article: C# - Working With Attributes - I

Attributes are used to specify more information about an entity. This information gets written in
metadata at compile time. An entity to which an attribute can be applied is called 'attribute target'.
The target can be an assembly, interface, structure, class and all possible class members. An
attribute is applied to the target by specifying the attribute name in brackets as shown below.

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

[Serializable]

This attribute is applied to a class stating that objects of this class can be serialized. When
compiler encounters this attribute, it adds suitable instructions in the metadata.

There are thousands of pre-defined attributes in FCL. In addition to them .NET allows us to define
our own attributes, called 'custom attributes'. In this article we would examine the process of
defining and using the custom attributes and reading them using reflection.
We would create a custom attribute that can be applied to create a documentation of a class and
its members. Documentation of a class includes for what the class was designed and how many
methods it has. Documentation of methods includes what does they do and so on. We could write
comments to know this information. However, comments remain in the source code and we may
not have access to it. If we add documentation through attributes it remains in the assembly and
can be accessed using reflection.

Declaring an Attribute

As everything in C# is declared in a class, an attribute is also embodied in a class. To create a


custom attribute we have to derive a class from the System.Attribute class. We have named our
derived class as DocumentAttribute. The class DocumentAttribute has three data members as
shown below.

class DocumentAttribute : System.Attribute


{
string info ;
int cnt ;
}

The string variable info keeps description of the entity and the integer variable cnt keeps count of
the methods. We can declare attributes either with parameters or without parameters. The
parameters can be positional parameters or named parameters. The positional parameters are
initialized in constructor, whereas, named parameters are initialized by defining a property.
Another difference between the two is that positional parameters must be passed in the same
sequence as given in the constructor. The named parameters are optional and can be passed in
any sequence. We have declared the Document attribute to take two parameters. We want that
one of them viz. info should be positional parameter and cnt should be named parameter. This is
because cnt would be used only if attribute is applied to class. For class members we can drop it.
So, we must define a constructor and a property as shown below.

public DocumentAttribute ( string i )


{
info = i ;
}

public int Count


{
get
{
return cnt ;
}
set
{
cnt = value ;
}
}

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

As we know, custom attributes are written in metadata and can be read through reflection.
Generally speaking reading an attribute means reading values of data members of the attribute
class. If we try to read the Document attribute it won't be able to access the info data member as
it is declared private. So, in order to expose it through metadata, we would write a read-only
property. Here it is.

public string Info


{
get
{
return info ;
}
}

We must also mention the attribute targets. This can be done by using nothing else than an
attribute called AttributeUsage. The AttributeUsage attribute targets classes. So, it has to be
declared just above the DocumentAttribute class as shown below.

[ AttributeUsage ( AttributeTargets.Class | AttributeTargets.Method |


AttributeTargets.Constructor | AttributeTargets.Field, AllowMultiple = false ) ]

class DocumentAttribute : System.Attribute


{
}

The AttributeUsage attribute takes two parameters. Using the first parameter we can specify
attribute targets. By setting the second parameter to true we can specify that one member can
have multiple Document attributes. When attribute targets are assembly or module, the attributes
should be placed immediately after all using statements and before any code.

Article: C# - Working With Attributes - II

Continued from last week...

In the last article we saw how to create an attribute, let us now see how to use it.

Using an Attribute

We would use the Document attribute to create documentation of the class test1. Here is the
declaration of test1 class.

[ Document ( "Class test1: created for testing custom attributes", Count = 2 ) ]


class test1
{
[ Document ( "i: Counter variable" ) ]
int i = 0 ;

[ Document ( "Ctor test1: zero-argument ctor" ) ]


public test1( )
{
}

[ Document ( "increment( ): Increments counter" ) ]

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

public void increment( )


{
i++ ;
}

[ Document ( "decrement( ): Decrements counter" ) ]


public void decrement( )
{
i-- ;
}
}

We have applied the Document attribute to the class through the statement

[ Document ( "Class test1: created for testing custom attributes", Count = 2 ) ]

Note that although name of our class is DocumentAttribute we have omitted the word Attribute
from here. This is because, if we don't write Attribute, compiler adds it for us. When compiler
encounters this statement, it searches for a class derived from the System.Attribute class in all
the namespaces mentioned in using statements.

The positional parameters are passed as the normal parameters. But named parameters are
passed by mentioning the name of the parameter like

Count = 2

No need to say that this would invoke the set block of Count property. On similar grounds, we
have applied our attribute to other class members.

Reading Attributes

Following code snippet shows how to read the Document attribute applied to a class.

Type t = typeof ( test1 ) ;


object[ ] a = t.GetCustomAttributes ( typeof ( DocumentAttribute ), false ) ;
foreach ( object att in a )
{
DocumentAttribute d = ( DocumentAttribute ) att ;
Console.WriteLine ( "{0} {1}", d.Info, d.Count ) ;
}

To begin with we have created a reference t to the Type object. We have used the typeof
operator on test1 class, which returns reference to an object of Type. The
GetCustomAttributes( ) method takes the type of the attribute we want to search and returns an
array of references to objects, each of type DocumentAttribute. Next, we have run a foreach
loop to read and display each attribute in the array. In our case only one attribute would get
displayed.

To read the attributes for methods, we would first obtain all the methods and then read attributes
of each of them. This is done through the following statements.

MethodInfo[ ] mi = t.GetMethods( ) ;
foreach ( MethodInfo m in mi )
{

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

object[ ] o = m.GetCustomAttributes ( false ) ;


foreach ( object ma in o )
{
DocumentAttribute d = ( DocumentAttribute ) ma ;
Console.WriteLine ( "{0}", d.Info ) ;
}
}

We have used the reference t to obtain the methods and collected them in an array of type
MethodInfo. We have called the GetCustomAttributes( ) method of the MethodInfo class to
read the attributes of each method.

Similarly we can use the GetCustomAttributes( ) method of the ConstructorInfo and FieldInfo
classes to read the attributes given to constructors and fields.

Article: C# - Accessing Registry

Registry has a lion's share in running the system smoothly. It stores all the configuration
information relating to Windows setup, user preferences, softwares installed and devices.

The registry is arranged in a hierarchical tree like structure. Each node in this tree is called a key.
Each key can contain additional keys or sub-keys (which allow further branching) as well as
values that are used to store the actual data. Each registry key may have several values. For
example a registry key 'Desktop' may have values like 'Wallpaper', 'TileWallpaper', etc. Each
value in a key contains the actual data. This data may take several forms ranging from a simple
integer value to a user-defined binary object. Each type is represented by a special registry
specific type. For example an integer is represented by REG_DWORD and a string is
represented by REG_SZ.

Many applications store their status viz. last file opened in the application, options selected by the
user, etc. in registry. We would also create such an application that would store the background
image, foreground color, size of the window and its position in the registry so that next time when
the application is run these selections could be restored.

For accessing the registry we will use the Registry and RegistryKey classes available in the
Microsoft.Win32 namespace. Naturally, we will have to add a using statement for this
namespace. Create a Windows Application and design a form as shown in the following screen
shot.

Also add the OpenFileDialog and ColorDialog controls to the form. Name them as file and color
respectively. The 'Choose Bitmap' button allows user to select an image file through the 'Open'
file dialog. The 'Choose Color' button lets the user to select a foreground color through the
standard 'Color' dialog.

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

To store the information of our application we would create a tree structure of two sub-keys-
Theme and Settings under the 'HKEY_LOCAL_MACHINE/SOFTWARE' key. The Settings sub-
key would contain all the values and data. Each key we want to access is represented by an
object of the RegistryKey object. So, create the objects that would represent the SOFTWARE
key and two user-defined keys as shown below.

RegistryKey skey, tkey, rootkey ;

To write anything in registry keys, we must open them. If keys are not created, we must first
create them. We would do this in constructor after a call to the InitializeComponent( ) method.
Add the following statements to the constructor.

rootkey = Registry.LocalMachine.OpenSubKey ( "SOFTWARE", true ) ;


tkey = rootkey.CreateSubKey ( "Theme" ) ;
skey = tkey.CreateSubKey ( "Settings" ) ;

In a file system, root drives like C:\ or D:\ are the root directories. In registry, there are root keys
called 'registry hives' or 'base keys'. There are seven such registry hives. The Registry class
provides seven fields of type RegistryKey representing the seven registry hives. The
LocalMachine field represents the HKEY_LOCAL_MACHINE base key. The OpenSubKey( )
method opens the key. Since we have called the method using LocalMachine field, it would open
the SOFTWARE key of Local Machine hive. By passing true as the second parameter we have
specified that the key is to be opened for writing. Next, we have created the 'Theme' sub-key in
the SOFTWARE key and 'Settings' in the 'Theme' sub-key. We have called the CreateSubKey( )
method for this.

Now let us add handlers for the buttons. The b_bitmap_Click( ) handler gets called when
'Choose Bitmap' button is clicked.

private void b_bitmap_Click ( object sender, System.EventArgs e )


{
file.Filter = "Image Files (*.bmp,*.gif,*.jpg)|*.bmp;*.gif;*.jpg||" ;
if ( file.ShowDialog( ) == DialogResult.OK )
{
BackgroundImage = Image.FromFile ( file.FileName ) ;
skey.SetValue ( "Image", ( string ) file.FileName ) ;
}
}

Here, we have displayed the 'open' dialog. We have applied filter so that only image files would
get displayed. If the user selects file we have changed the background image of the form and
also written the file path as data of the 'Image' value in the 'Settings' sub-key. We have called the
SetValue( ) method for writing the data. The SetValue( ) method takes the value name and data
as parameters. The data needs to be type-casted in suitable type as the method takes parameter
of type object.

The b_color_Click( ) method gets called when clicked on the 'Choose Color' button. The handler
is given below.

private void b_color_Click (object sender, System.EventArgs e )


{
if ( color.ShowDialog( ) == DialogResult.OK )
{

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

ForeColor = color.Color ;
skey.SetValue ( "Red", ( int ) color.Color.R ) ;
skey.SetValue ( "Green", ( int ) color.Color.G ) ;
skey.SetValue ( "Blue", ( int ) color.Color.B ) ;
}
}

Finally add the code to write size and position to the registry. This code should get executed when
the window is closed. So, we would add this code in the Dispose( ) method. The Dispose( )
method is given below.

protected override void Dispose ( bool disposing )


{
skey.SetValue ( "Height", ( int ) Height ) ;
skey.SetValue ( "Width", ( int ) Width ) ;
skey.SetValue ( "X", ( int ) DesktopLocation.X ) ;
skey.SetValue ( "Y", ( int ) DesktopLocation.Y ) ;

skey.Close( ) ;
tkey.Close( ) ;
rootkey.Close( ) ;

// AppWizard generated code


}

After writing the values we have closed the keys by calling the Close( ) method.

Our writing part is now over. We want that when application is executed the next time, the form
should get displayed the same way as it was before closing. To read the information from registry,
we have written a user-defined method readsettings( ).

public void readsettings( )


{
rootkey = Registry.LocalMachine.OpenSubKey ( "SOFTWARE", false ) ;
tkey = rootkey.OpenSubKey ( "Theme" ) ;
if ( tkey == null )
return ;
skey = tkey.OpenSubKey ( "Settings" ) ;

string f = ( string ) skey.GetValue ( "Image" ) ;


if ( f != null )
BackgroundImage = Image.FromFile ( f ) ;
try
{
int r = ( int ) skey.GetValue ( "Red" ) ;
int g = ( int ) skey.GetValue ( "Green" ) ;
int b = ( int ) skey.GetValue ( "Blue" ) ;
ForeColor = Color.FromArgb ( r, g, b ) ;

Height = ( int ) skey.GetValue ( "Height" ) ;


Width = ( int ) skey.GetValue ( "Width" ) ;

int x = ( int ) skey.GetValue ( "X" ) ;


int y = ( int ) skey.GetValue ( "Y" ) ;
DesktopLocation = new Point ( x, y ) ;

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

}
catch ( Exception e )
{
return ;
}
}

Here, firstly we have opened the keys. When the application is run for the first time, keys are not
created. So, we have checked for the null reference in the RegistryKey object. The statements
written thereafter read the data from registry and use it.

Call this method from the InitializeComponent( ) method after the initialization code.

Article: C# - Creating Multithreaded Applications - I

In a broad sense Multithreading can be thought of as the ability to perform several jobs
simultaneously. For example, while working in Windows we can simultaneously carry out different
jobs like printing a document on the printer, receiving e-mails, downloading files and compiling
programs. All these operations are carried out through different programs, which execute
concurrently in memory.

Even though it may appear that several tasks are being performed by the processor
simultaneously, in actuality it is not so. This is because in a single-processor environment, the
processor divides the execution time equally among all the running threads. Thus each thread
gets the processor's attention in a round robin manner. Once the time-slice allocated for a thread
expires, its state and values are recorded, the operation that it is currently performing is put on
hold and the processor directs its attention to the next thread. Thus at any given moment if we
take the snapshot of memory we will find that only one thread is being executed by the processor.
Thread switching happens so fast that we get a false impression that the processor is executing
several threads simultaneously.
Multithreading has several advantages to offer. These are listed below:

Responsiveness: Take an example of MS-Word. Here had the spell checker and the grammar
checker not run as different threads, we would have been required to write documents and submit
it to the checkers from time to time. This would have resulted in low responsiveness. Since the
checkers run in different threads, our document gets checked as we type, thereby increasing the
responsiveness of the application.

Organization: Threading simplifies program organization. In the 'File Copy' example if both the
operations-playing the animation and the actual copying-are run in the same thread, then after
copying a few thousand bytes we would be required to play the next frame of animation. If we run
the copying code and animation code in separate threads we can avoid cluttering the copying
code with animation code and vice versa.

Performance: Many a times it happens that a program needs to wait for user input or has to give
some output. The I/O devices are generally slower than the processor. So the application waits
for the I/O operation to finish first. If instead we use another thread for the I/O operation, the
processor time can be allotted to other important tasks independent of the I/O operation, thereby
increasing the performance.

Launching threads

Now that we know what threads are, let us now see how they can be created. Starting a thread is
very simple. The following statements launch a new thread.

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

TheradStart ts = new ThreadStart ( func ) ;


Thread t1 = new Thread( ) ;
t1.Start( ) ;

While creating a thread, we must specify which method should get executed when the thread
starts execution. If we wish that a static method func( ) should get executed in the thread, we
would have to wrap its address in a delegate and pass it to the constructor of the Thread class.
For this, we have to use a predefined .NET delegate class called ThreadStart. The signature of
this delegate is such that it returns a void and does not accept any arguments. Hence func( )
also needs to have the same signature. To start the thread we must call the Start( ) method of the
Thread class. Both the Thread class and the ThreadStart delegate belong to the
System.Threading namespace hence we need to write using System.Threading at the
beginning of any program.

Let us now see an example where multithreading is actually needed. Here we plan to make a
simple game. The UI of the game is given in the following screen shot:

This application consists of two buttons named Start and Hit, and three textboxes named num1,
num2 and num3.

The user needs to click on the Start button to start the game. As soon as this button is clicked,
random numbers would get displayed on the three textboxes. Now at any instance if the user
clicks on the Hit button, the display of numbers stops. If the numbers turn out to be the same the
user hits the jackpot.

It is impossible to generate and display the random numbers in the three textboxes
simultaneously in the main thread. If we attempt to do so, numbers in the second textbox would
get generated only after generating and displaying numbers in the first textbox. So here if we
want concurrent functionality, we need to generate and display the numbers for the textboxes in
three different threads. On clicking the Start button, the three threads get launched as shown in
the following code snippet:

private void start_Click ( object sender, System.EventArgs e )


{
t1 = new Thread ( new ThreadStart ( this.display1 ) ) ;
t1.Start( ) ;
t2 = new Thread ( new ThreadStart ( this.display2 ) ) ;
t2.Start( ) ;
t3 = new Thread ( new ThreadStart ( this.display3 ) ) ;
t3.Start( ) ;
}

We have added the references t1, t2 and t3 of the Thread class as data members of the Form1
class. The display1( ) method is given below.

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

public void display1( )


{
int j = r.Next ( 0, 50 ) ;
int k = r.Next ( 50, 100 ) ;

for ( int i = j ; i <= k ; i++ )


{
num1.Text = i.ToString( ) ;
Thread.Sleep ( 200 ) ;
}
}

Here we have used an object of the Random class referred to by r that we also added as a data
member of the Form1 class. Using this object we have created two random numbers and
displayed all numbers lying between the two in the textbox. The display2( ) and display3( )
methods are on the same lines. Hence random numbers keep on getting displayed
simultaneously on the three textboxes. Now the user needs to click the Hit button. The handler
for the Hit button is given below:

private void hit_Click ( object sender, System.EventArgs e )


{
t1.Abort( ) ;
t2.Abort( ) ;
t3.Abort( ) ;
if ( int.Parse ( num1.Text ) == int.Parse ( num2.Text ) && int.Parse ( num2.Text ) == int.Parse (
num3.Text ) )
MessageBox.Show ( "Jackpot" ) ;
}

Here we have aborted the threads using the Abort( ) method, compared the numbers and
displayed a message if they are same.

Article: C# - Creating Multithreaded Applications - II

...Continued from last week

Thread States

From the time a thread is started until it gets terminated the thread undergoes many transitions
and is said to be in at least one of the several 'thread states'.

A thread can be in one or more of the following states at any given time: Unstarted, Running,
Suspended, WaitSleepJoin, SuspendRequested, Aborted, AbortRequested, Stopped and
StopRequested. All these states are members of the ThreadState enumeration declared in
System.Threading namespace. Let us now discuss these states.

Unstarted: A thread is said to be in the Unstarted state when it is first created. It remains in this
state until the program calls the Start( ) method of the Thread class.

Running: As soon as the Start( ) method is called, the thread starts executing and is said to be in
the Running state. This means that the thread will now start getting CPU time slots

Suspended: When a running thread's Suspend( ) method is called, the thread goes into the

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

Suspended state and would stop receiving CPU time-slots.

WaitSleepJoin: At times we may want to prevent our thread from getting CPU cycles till passage
of some time or make our thread wait till some other thread completes some operation or wait till
some other thread terminates. We can achieve these three scenarios by calling the methods
Thread.Sleep( ), Monitor.Wait( ) and Thread.Join( ) methods respectively on our thread. Upon
calling one of these three methods, our thread enters the WaitSleepJoin state.

Once in this state we can transition out of it in the following three ways:

(a) The sleeping time specified by the Sleep( ) method expires.


(b) Another thread calls the Thread.Interrupt( ) method before the sleeping time expires.
(c) Another thread calls the Monitor.Pulse( ) method or Monitor.PulseAll( ) method.
Monitor.Pulse( ) moves the waiting thread into the Running state. Monitor.PulseAll( ) method
moves the thread along with all the other waiting threads into the Running state.

All the above three ways move the thread from the WaitSleepJoin state to the Running state.

Stopped: When a thread completes its execution, it goes into the Stopped state.

Aborted: Whenever an exception is thrown and the thread stops executing abruptly it goes into
the Aborted state.

AbortRequested: The AbortRequested state is reached when a thread is in another state but is
being requested to abort. As soon as it comes out of the present state, it gets aborted.

SuspendRequested: The SuspendRequested state is reached when a thread is in another


state but is being requested to suspend using the Suspend( ) method. As soon as it comes out of
the present state, it gets suspended.

StopRequested: The StopRequested state is reached when a thread is being requested to


stop. There is no method available that we can invoke to manually force our thread in this state.

The following figure depicts the life cycle of a thread.

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

Article: C# - Synchronizing Threads

Synchronization plays an important role in multithreaded applications where the threads are not
independent of each other and share common resources. This is because if two threads share
common resources and try to manipulate the resources simultaneously, the resources become
inconsistent. To tackle such situations synchronization provides a lock on the resource that is
shared among threads and makes a thread wait until the other thread finishes the job with the
resource. Thus synchronization 'locks' the shared resource and prevents another thread from
using it.

C# provides a lock keyword to lock the shared object or resource. Whatever is written inside the
parenthesis following the lock keyword gets locked for the current thread and no other thread is
permitted to obtain the lock on that resource or object. We can write an expression that evaluates
to an object, or just the object on which we wish to have a lock, inside the parenthesis. Whatever
the expression may be, the result should be a reference type. The code that uses the object to be
synchronized should be written inside the block of the lock statement.

To give you a more concrete example, consider two threads working on a file. If both the threads
try to open the file and write to it simultaneously, an exception is thrown. Here what we need to do
is synchronize both the threads in such a way that only one thread opens the file and writes in it
at any given moment.

We have illustrated the same scenario in the example that follows. The user interface of the
application is shown in the following screen shot.

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

Here we have added a textbox named quantity, a button called purchase and a label called
msg. In this application we have simply asked the user number of goods he wants to purchase,
i.e. the demand. We have maintained number of goods in stock in a file called log.bin. Whenever
the user purchases certain amount of goods, the number in the file is updated.

In this application we have also launched another thread which keeps on checking continuously
whether the goods are out of stock or not. If the thread finds that the number of goods in the store
is zero, it fills the store with hundred goods and hence updates the number in log.bin file.

We need to synchronize the two threads so that only one thread works on log.bin at one time.
We added the following as data members of the Form1 class.

FileInfo f ;
FileStream fs ;
byte total = 100 ;

total denotes the total number of goods in store. We have used a value like 100 that can be
represented in one byte. This is because FileStream is used to write an array of bytes in the file
and if we take a larger number, we would have to first create an array of bytes representing the
large number. For the sake of simplicity here we have used a number that can be represented in
one byte.

We initialized the reference f, and launched the thread that would keep on checking the stock
from time to time after the call to the InitializeComponent( ) method in the constructor as shown
below:

f = new FileInfo ( "C:\\log.bin" ) ;


Thread t = new Thread ( new ThreadStart ( checker ) ) ;
t.IsBackground = true ;
t.Start( ) ;

We have made this thread a background thread because we wish that as soon as the application
terminates, the thread should also get terminated. The checker( ) method is given below:

public void checker( )


{
while ( true )
{
lock ( f )
{

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

try
{
fs = f.OpenWrite( ) ;
if ( total <= 0 )
{
total = ( byte ) ( total + 100 ) ;
fs.WriteByte ( total ) ;
msg.Text = "Stock sold out!!!! Goods
incremented" ;
}
else
msg.Text = "Items in stock: " + total ;
Thread.Sleep ( 1000 ) ;
fs.Close( ) ;
}
catch
{
MessageBox.Show ( "Can not Open file" ) ;
}
}
}
}

We have put the checker logic in a while loop so that the store is checked continuously after
every 1000 milliseconds (Thread.Sleep(1000) ensures this). Next we have obtained a lock on the
file object referred to by f using the lock statement. After acquiring the lock we have checked
whether total is zero or less than zero. If yes, we have incremented total by 100 and wrote the
value back in the file. If it is not zero or less than zero, we have simply displayed the number of
goods in the label named msg. We have put the whole logic in a try-catch block, the reason for
which would be clarified later.

Now if the user supplies some number in the textbox and clicks on the purchase button, the
following handler gets called:

private void purchase_Click ( object sender, System.EventArgs e )


{
lock ( f )
{
try
{
fs = f.OpenWrite( ) ;
byte b = byte.Parse ( quantity.Text ) ;
total = ( byte ) ( total - b ) ;
fs.WriteByte ( total ) ;
MessageBox.Show ( "Transaction Complete" + "\n" + "Item
remaining: " + total ) ;
fs.Close( ) ;
}
catch
{
MessageBox.Show ( "Cannot Open file" ) ;
}
}
}

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

Here also we have first acquired a lock on the file object. Next we have collected the quantity
demanded by the user in a byte called b. Then we have subtracted that amount from total and
wrote back the new value of total in the file. We have put this logic also in a try-catch block. This
method gets executed in the main thread, whereas checker( ) gets executed in a thread referred
to by t.

Now if you execute the program, you would see that the number of goods in the store is displayed
continuously on the msg label. As soon as the user purchases some goods, the number is
updated and when the number goes below zero, the goods are incremented.

This works fine, but if you really want to understand the need of synchronization, remove or
comment the lock statement and see the effect. As soon as the user clicks on purchase an
exception gets thrown indicating that the file is already in use. To catch this exception we have
used the try-catch blocks. The exception gets thrown because both the threads try to open and
write to the file simultaneously.

Besides the lock statement synchronization can also be achieved in C# using the Interlocked
class, the Monitor class, Mutexes and Events.

The Interlocked class: provides four methods to perform operations like incrementing,
decrementing or exchanging variables in a thread-safe manner. The four static methods are-
Increment( ), Decrement( ), Exchange( ), and CompareExchange( ).

Monitors: in .NET are similar to the lock statement and are used to synchronize concurrent
thread accesses so that any resource can be manipulated only by one thread at a time. Thus they
support mutually exclusive access to a shared resource. Monitors are similar to Critical
Sections in Windows. The Framework Class library provides a Monitor class to represent the
Monitor. The above program will also work if we use Monitor.Enter( f ) and Monitor.Exit( f )
methods, belonging to the Monitor class, instead of the lock statement. All we need to do is to
write the code present in the lock block between the calls to Monitor.Enter( f ) and Monitor.Exit(
f ) methods. In fact when we use the lock statement it gets resolved into calls to Monitor.Enter( )
and Monitor.Exit( ) methods in the IL code.

Mutexes: The word mutex comes from two words-"mutually' and "exclusive". Mutexes are similar
to monitors except that they permit the object or resource to be shared across processes.
Mutexes can thus synchronize threads belonging to different applications. The
System.Threading.Mutex class represents a mutex object.

Events: are used to synchronize threads in some order. For example if two threads are executing
and we want that not only should the threads work synchronously, but they should also get
executed alternately, we should use events. If we use events we will get the following order of
execution:

Thread1 executing
Thread2 executing
Thread1 executing
Thread2 executing

And so on… But instead if we use only monitors, we will achieve synchronization but threads are
likely to get executed in the following manner:

Thread1 executing
Thread1 executing
Thread2 executing
Thread1 executing

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

The .NET Framework class library wraps two of the Windows' kernel objects-auto-reset events
and manual-reset events-into two classes called AutoResetEvent and ManualResetEvent.

Article: C# - File Transfer Using Network I/O - I

Though on the face of it the Internet and Web appear fairly simple, if you scratch the surface you
would appreciate that it is built upon complex protocols, networking technologies and programs.
.NET attempts to reduce this complexity for the programmer and therefore is able to impact the
web and network programming in a major way.

Network Programming

Network programming under .NET is quite similar to reading and writing files on local disk.
Network applications are written using the Client-Server model. In this model the communication
is carried out using entities called "sockets". Sockets are nothing but software abstractions that
are used to represent the end points of a connection between two machines. For any given
connection there is one socket on the client and one socket on the server. A program can read
from a socket or write to a socket in a manner that is similar to File-IO. The socket-based
communication can be of two types, namely, Connection-Oriented and Connectionless. Of these
the Connection-Oriented service uses the popular Transmission Control Protocol (TCP), whereas
the Connectionless service uses the User Datagram Protocol (UDP). In this article we will
concentrate on TCP protocol.

To be able to communicate between any two machines in a network, there must be a unique way
to identify them. This is achieved using the IP (Internet Protocol) Address of the machine. If we
mention a machine name it ultimately gets converted into an IP Address. However, it is possible
for more than one application to be using network connection at the same time. Therefore each
application must have a unique ID so that the client can indicate which application it is looking for.
This unique ID is called port number. Thus the IPAddress and port number represent respectively
the first and second level of addressing.

.NET provides several classes and interfaces organized under the namespace
System.Net.Sockets to help us write Connectionless and Connection-Oriented networking
applications. Typically in a Connection-Oriented service, a server waits for a connection request
from the client. This waiting is generally done in a loop. Once the server gets a request a
connection is setup between the server and the client. The end points of this connection are
sockets. The functionality of these sockets has been wrapped inside the TcpListener and
TcpClient classes present in the System.Net.Sockets namespace. Hence to carry out
Connection-Oriented communication between two applications running on same/different
machines we need to create objects of these classes. The TcpListener object is used to listen to
the requests from the client. The TcpClient object is used to establish a connection between the
client and the server. Let us now see how to use the classes in this namespace to build an
application.

We have designed this application to transfer a file requested by the client from server to client.
The same application acts as a client as well as a server. The interface of this application is
shown below.

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

The following table shows the controls and their Names.

Control Name
Server Text Box Tserver
Port Text Box tport
Listen As Server
bserver
Button
Connect As Client
bclient
Button
File Name Text Box fname
Open Button bopen
Text Box text

Both the users have to start the same application. Out of the two, one should listen as server and
another should connect as client. It is necessary to listen as server before connecting as a client,
otherwise the client would get an exception. To be able to listen as server, the user has to enter
the port number (any integer value) and click the 'Listen As Server' button. The client must enter
both the server name (name of machine on which server application is running) and the same
port number and then click the 'Connect As Client' button. The client now can enter the file name
with entire path in the 'Enter File Name' text box and click the 'Open' button. As soon as the client
clicks the 'Open' button a request to send the specified file is sent to the server and the file
contents are received back from the server.

Let us now add the handlers and write code in them. First of all we would add the Click event
handler for the 'Listen As Server' button. The code of the handler is given below.

private void bserver_Click ( object sender, System.EventArgs e )


{

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

int portno = Convert.ToInt16 ( port.Text ) ;


TcpListener l = new TcpListener ( portno ) ;
l.Start( ) ;
tc = l.AcceptTcpClient( ) ;
st = tc.GetStream( ) ;
bserver.Enabled = false ;

recvthread r = new recvthread ( st ) ;


Thread t = new Thread ( new ThreadStart ( r.sendfile ) ) ;
t.IsBackground = true ;
t.Start( ) ;
}

Here, we have first obtained the port number. We have then created an object of the TcpListener
class and stored the port number in it. We have then called the Start( ) method of the
TcpListener class. This method would wait in a loop (listening) for a connection request from the
client. The method would listen on the port number assigned to the TcpListener object. Here
we're effectively blocking on the Start( ) method until a request comes in from the client. We have
then called the AcceptTcpClient( ) method to accept the connection request and obtain an object
of the TcpClient class. Hence we need to create a reference tc of the type TcpClient as the data
member of the Form1 class. We have then called the GetStream( ) method using the tc
reference to obtain a reference to the object of the NetworkStream class. This object would be
used to write into the socket. To collect the reference we need to create a reference st of the type
NetworkStream as the data member of the Form1 class. We have disabled the 'Listen As
Server' button so that user should not click it again.

The server and client can exchange messages as soon as the connection is established. The
messages sent by both the server and client would get written to the stream. We do not receive
any notification when the data is written to the stream. Hence we need to continuously check
whether the data has been written to the stream or not so that we can read it. If we don't start
another thread and wait for the messages in the current thread that has displayed the form, we
would not be able to interact with the form. Hence it is necessary to start a thread in which we can
read the data from stream. We also need to make the thread a background thread because as
soon as the application closes, we also want the thread to stop. The thread would need the
NetworkStream reference to read the messages from the stream. We cannot pass these
parameters directly to the sendfile( ) method that is used for reading and sending file contents in
the thread as the ThreadStart delegate doesn't permit it. Hence we have wrapped the sendfile( )
method in the recvthread class and used its constructor to initialize the parameter needed by the
sendfile( ) method. To the one-argument constructor of the recvthread class, we have passed
the reference to the NetworkStream object (obtained using the GetStream( ) function). Next, we
have started the thread to read the data received from the socket.

Article: C# - File Transfer Using Network I/O - II

... Continued from last week

Let us now write the code that should get executed when client clicks the 'Connect As Client'
button. The bclient_Click( ) handler is given below.

private void bclient_Click ( object sender, System.EventArgs e )


{
String servername = tserver.Text ;
int portno = Convert.ToInt16 ( port.Text ) ;

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

tc = new TcpClient( ) ;
try
{
tc.Connect ( servername, portno ) ;
}
catch ( Exception ex )
{
MessageBox.Show ( "Cannot connect to server" ) ;
return ;
}

bclient.Enabled = false ;
}

Here, we have firstly obtained the server name and port number. In the next statement we have
created an object of the TcpClient class. Using this object we have called the Connect( ) method
and passed to it the server name and port number. The Connect( ) method would send the
connection request to the server specified by the server name at the port specified by the port
number. The Connect( ) method would wait until the server accepts the connection. Lastly, we
have disabled the 'Connect As Client' button. The client can now enter and send the file name to
the server. The handler for the 'Open' button is given below.

private void bopen_Click ( object sender, System.EventArgs e )


{
string s = fname.Text ;
s += "*" ;

byte[ ] buf = new byte [ s.Length ] ;


buf = Encoding.ASCII.GetBytes ( s ) ;

st = tc.GetStream( ) ;
st.Write ( buf, 0, s.Length ) ;

recvthread r = new recvthread ( st, text ) ;


Thread t = new Thread ( new ThreadStart ( r.getfile ) ) ;
t.IsBackground = true ;
t.Start( ) ;
}

In this handler we have obtained the file name and attached a character to the string object to
mark the end of the file name. Why we need this would be clear in a short while. To write the file
name on stream we have first created an array of bytes and copied the contents of string object
into the array. We have then obtained the stream object by calling the GetStream( ) method and
written the filename to the stream by calling the Write( ) method of the NetworkStream class.
The Write( ) method writes to the stream and advances the current position within this stream by
the number of bytes written. Next, we have started a thread as we did for server. This time we
have passed the reference to the NetworkStream object as well as reference to the TextBox
object. Note that this time we have passed two arguments to the constructor of the recvthread
class. The getfile( ) method would receive the file contents sent by the server and display them in
the text box. Let us now see how the recvthread class is declared.

class recvthread
{
NetworkStream ns ;
TextBox tb ;

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

public recvthread ( NetworkStream s, TextBox t )


{
ns = s ;
tb = t ;
}

public recvthread ( NetworkStream s )


{
ns = s ;
}

public void sendfile( )


{
byte[ ] buffer = new byte[ 255 ] ;
ns.Read ( buffer, 0, buffer.Length ) ;
string str = Encoding.ASCII.GetString ( buffer ) ;
int i = str.IndexOf ( '*' ) ;
str = str.Substring ( 0, i ) ;
string filestr = "" ;
try
{
FileInfo f = new FileInfo ( str ) ;
StreamReader sr = f.OpenText( ) ;
string temp ;
do
{
temp = sr.ReadLine( ) ;
filestr += temp ;
filestr += "\r\n" ;
} while ( temp != null ) ;

byte[ ] buf = new byte [ filestr.Length ] ;


buf = Encoding.ASCII.GetBytes ( filestr ) ;
ns.Write ( buf, 0, filestr.Length ) ;
}
catch( Exception e )
{
MessageBox.Show ( e.ToString( ) ) ;
}
}

public void getfile( )


{
byte[ ] buffer = new byte[ 512 ] ;
ns.Read ( buffer, 0, buffer.Length ) ;
string str = Encoding.ASCII.GetString ( buffer ) ;
tb.Text = str ;
}
}

The class contains two data members that are initialized in the constructor. The class has two
constructor of which one-argument constructor is called from the bserver_Click( ) handler,
whereas, the two-argument constructor is called from the bclient_Click( ) handler.

In the sendfile( ) method, which would get called when the server thread starts, we have called
the Read( ) method of the NetworkStream class. The Read( ) method reads a sequence of bytes

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

from the stream referred to by s and advances the current position within the stream by the
number of bytes read. In our case, the Read( ) method would read the file name written to the
stream by the client. The bytes read would get stored in the buffer array. We have encoded the
bytes read in the buffer array into a string using the Encoding.ASCII.GetString( ) method. This
method would copy all the 255 characters to the string object. We must take only that part of the
string where file name is stored. For this we would use the end mark '*' that we have
concatenated to the file name in the bopen_Click( ) method. In the next few statements, we have
opened the file and read its contents. Now the only job remaining is to write the contents back to
the client. We have done so by calling the Write( ) method. The client also stands ready to read
the file contents in the getfile( ) method.

In the getfile( ) method we have merely called the Read( ) method, converted the byte stream
into a string and displayed it in the text box.

Lastly, add the following using statements at the beginning of the program.

using System.Net.Sockets ;
using System.Text ;
using System.IO ;
using System.Threading ;
Article: C# - Implementing UDP

Unlike the TCP protocol, the UDP protocol is connectionless. Here there is no setting up of
connection needed, instead the data is sent in packets. The .NET framework provides the
UdpClient class for connectionless transmission. Like TcpListener and TcpClient, UdpClient
also wraps the Socket class. The UdpClient's Send( ) and Receive( ) methods invoke the
SendTo( ) and ReceiveFrom( ) methods of the Socket( ) class respectively.

To demonstrate the usage of the connectionless service we have created two applications-
Quizmaster and Player. The idea is basically to conduct an online quiz, where the Quizmaster
would ask questions to two players on two different machines. The player who responds with a
correct answer first wins. Create a Windows application named Quizmaster and design the form
as shown below.

The Quizmaster asks a question by typing it in the 'Post a Question' text box named que. He is
also supposed to provide an answer to cross check the answers supplied by the players in the

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

'Correct Answer' text box named ans. Then he should specify the names of the computers on
which the 'Player' application is executing. We have allowed two players to play at one time.
These names should be supplied in the 'Computer 1' and 'Computer 2' text boxes named
pcname1 and pcname2. On receiving the answers, they would get displayed in the messages
list box.

Let us first take a look at the Quizmaster application. After typing the question-answer along with
the computer names, the Quizmaster clicks the 'Send' button. This invokes the following handler:

private void sendbut_Click ( object sender, System.EventArgs e )


{
string question ;
byte[ ] senddata ;
question = que.Text + "@" + Dns.GetHostName( ) ;
answer = ans.Text ;
senddata = Encoding.ASCII.GetBytes ( question) ;
try
{
client.Send ( senddata, senddata.Length, pcname1.Text, 201 ) ;
}
catch
{
MessageBox.Show ( "Cannot send to " + pcname1.Text ) ;
}
try
{
client.Send ( senddata, senddata.Length, pcname2.Text, 201 ) ;
}
catch
{
MessageBox.Show ( "Cannot send to " + pcname2.Text ) ;
}
}

In this handler we have first collected the question as well as the answer in the strings question
and answer respectively. We have made answer a data member of the class because we will
need it in another method to crosscheck the answers provided by the players. Next we have
appended the question with the computer name separating them with an '@'. The GetHostName(
) method of the Dns class returns a string containing the host name of the machine. Then we
have encoded the data in an array of bytes called senddata. The data is sent using the Send( )
method of the UdpClient class. For this we have added a data member called client of the type
UdpClient to the Form1 class. The Send( ) method takes four parameters-an array of bytes to
be sent, the length of the array of bytes, the computer name where we wish to send the data and
the port number to which the data would be sent. We chose the port number to be 201 (you can
choose any other). Now the Quizmaster application should be ready to accept answers from the
players. The player who first sends the correct answer wins. This calls for waiting for a packet to
arrive at the specified port. For this we have started a different thread from the constructor of the
Form1 class. This thread would start waiting for a packet as soon as the application starts. The
following code written inside the constructor launches a separate thread

Thread svthread = new Thread ( new ThreadStart ( startserver ) ) ;


svthread.IsBackground = true ;
svthread.Start( ) ;
The startserver( ) method is given below

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

public void startserver( )


{
// 1-Create an IPEndPoint to receive messages
IPEndPoint recvpt = new IPEndPoint ( IPAddress.Any, 0 ) ;
byte[ ] data ;
string str, from ;
int index ;
while ( true )
{
// 2-Receive data
data = server.Receive ( ref recvpt ) ;
str = Encoding.ASCII.GetString ( data ) ;
index = str.LastIndexOf ( "@" ) ;
from = str.Substring ( index + 1 ) ;
messages.Items.Add ( str ) ;
str = str.Remove ( index, str.Length - index ) ;

// 3-Check the answer


string result ;
if ( str.CompareTo ( answer ) == 0 )
{
result = "Correct! your rank is " + rank + "@" + HostName( ) ;
rank += 1 ;
}
else
result = "Your answer is wrong!" + "@" + Dns.GetHostName( ) ;
if ( rank == 3 )
rank = 1 ;
// 4-Send the result
byte[ ] senddata ;
senddata = Encoding.ASCII.GetBytes ( result ) ;
try
{
client.Send ( senddata, senddata.Length, from, 201 ) ;
}
catch
{
MessageBox.Show ( "Cannot send result" ) ;
}
}
}

Here, we have firstly created an object of the IPEndPoint class. We need it to receive messages
from the client. To the constructor of the IPEndPoint class we have passed a default IPAddress
using the Any Filed of the IPAddress class. The Any field specifies that the server should listen
for client activity on all network interfaces. We have also passed a port number 0 to indicate that it
should pick any available port.

The player sends his answer to the Quizmaster in packets. To receive the packet we have called
the Receive( ) method of the UdpClient class. We have added server as a data member of the
Form1 class as shown below.

UdpClient server = new UdpClient ( 200 ) ;

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

The Receive( ) method returns an array of bytes containing the answer which we have after
converting into string displayed in the list box. The player would send his answer along with the
computer name separated with '@'. To check whether the answer is correct or not we must first
separate the answer and computer name. The correctness of answer is checked using the
CompareTo( ) method of the String class.

If the answer is correct we have constructed a string result containing a rank. We have added
rank as an integer data member of the Form1 class and initialized it to 1. If the answer does not
match then we have stored a string saying that the answer is wrong. If the answer is right the
rank is also incremented by 1 so that whoever replies next will be ranked 2nd. If the rank
exceeds 2 we have reset it to 1 because there are only two players.

Next we have sent the result string using the Send( ) method of the UdpClient class.

Separating the string, checking the answer and sending the result should be carried out every
time a packet is received. So, we have done them in a while loop.

Now let us take a look at the 'Player' application. The 'Player' is a very simple application. Its form
contains a label named question. We have changed the font size of the text that would get
displayed in the label to 11 and changed its style to bold. All the player needs to do is type in the
answer and click the 'Send' button.

We chose 201 as the port number where the player would receive packets and 200 as the port
number for sending the packets. In the player application too we have started a new thread in the
constructor of the Form1 class that waits for a packet to arrive, as shown below.

Thread svthread = new Thread ( new ThreadStart ( startplayer ) ) ;


svthread.IsBackground = true ;
svthread.Start( ) ;
The startplayer( ) method is given below
public void startplayer( )
{
IPEndPoint recvpt = new IPEndPoint ( IPAddress.Any, 201 ) ;
byte[ ] data ;
string str ;
int index ;
while ( true )
{
data = server.Receive ( ref recvpt ) ;
str = Encoding.ASCII.GetString ( data ) ;
index = str.LastIndexOf ( "@" ) ;
from = str.Substring ( index + 1 ) ;
str = str.Remove ( index, str.Length - index ) ;
question.Text = str ;
}
}

Here also we have created an object of the IPEndPoint class and collected its reference in
recvpt. After receiving the question we have separated the question and the computer name in
str and from respectively. server (a reference of UdpClient instance) and from (a reference to a
string) have been added to the Form1 class as data members. Then we have displayed the
question on the label named question.

As soon as the player receives a question he has to type in the correct answer and click the
'Send' button. This would invoke the following handler.

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

private void sendbut_Click ( object sender, System.EventArgs e )


{
byte[ ] senddata ;
string answer ;
answer = ans.Text + "@" + Dns.GetHostName( ) ;
senddata = Encoding.ASCII.GetBytes ( answer ) ;
try
{
client.Send ( senddata, senddata.Length, from, 200 ) ;
}
catch
{
MessageBox.Show ( "Error sending data" ) ;
}
}

Here we have collected the answer provided by the player in a string called answer and
appended it with an '@' followed by the host name of the player machine. After encoding it in a
byte array we have again used the Send( ) method of the UdpClient class to send the data.
client has been added as the data member of the Form1 class. Now since both the applications
are ready, we can enjoy quizzing.

Article: C# - Introduction To Assemblies

Assembly is an important element of .NET programming. In .NET platform, an assembly is a unit


of reuse, versioning, security and deployment. In order to package and deploy our types, they
must be placed into modules that are part of an assembly. Every managed application in .NET is
deployed as an assembly. It means that entire .NET code on compilation gets converted into an
IL code and gets stored as an assembly. In addition to the IL code, an assembly also contains
Assembly Metadata (Manifest), Type metadata and Resources. Assemblies are hence self-
describing. Let us peep into the structure of an assembly.

Structure Of Assembly

If an assembly is to be made up of several programs, the programs can be stored in separate


modules. Suppose there are two source files 'a.cs' and 'b.cs' of which, 'a.cs' is stored in a module,
whereas, 'b.cs' is stored in the assembly itself. Both comprise an assembly named 'mydll.dll'. The
structure of the assembly 'mydll.dll' would look as shown in the following figure.

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

The PE file 'a.dll' is said to be stored in a module of the 'mydll.dll' assembly. Had 'mydll.dll'
contained resources, they would also get added in the structure with the type metadata and
manifest. The 'assembly description' shown in manifest contains the identity of the assembly,
consisting of its name, version and culture. An assembly has a four part version number e.g.
1.0.1.1. The parts are <Major> . <Minor> . <Build> . <Revision>. Other contents are the names of
all the files in the assembly, information regarding whether all the types defined in the assembly
are visible to other assemblies or private to one, a hash of all files in the assembly and details of
any security permissions that clients need to have in order to be able to run the assembly.

Private and Shared Assemblies

We can create two types of assemblies-private assemblies and shared assemblies. A private
assembly is used by only one application while a shared assembly is shared amongst different
applications.

By default when we compile a C# program, the assembly produced will be a private assembly.
This assembly (DLL/EXE) should be placed in the same folder as the calling application. With a
private assembly it's not necessary to think about naming conflicts with other classes or
versioning problems because each application has its own copy of the assembly. In shared
assemblies we have to ensure that the assembly is unique, and therefore, have a unique name
(called strong name).
In this article we would see how to build and use a shared assembly.

We plan to write a class library consisting of a function called display( ). We will call this function
from a client program, which we will create later. Here is code of the display( ) method which is
defined in the mytext class.

public class mytext


{
public void display ( Form fr, string s, Color c, string fname, int size, Point pt )
{
Graphics g = fr.CreateGraphics( ) ;
Font myfont = new Font ( fname, size) ;
SolidBrush mybrush = new SolidBrush ( c ) ;
g.DrawString ( s, myfont, mybrush, pt ) ;
}
}

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

The display( ) method simply draws text with the specified Font and Brush. On building the
project a 'fontassembly.dll' file would get created in the 'fontassembly\bin\Debug' subfolder.

A shared assembly is always unique. To be uniquely identified, a shared assembly has a strong
name. The combination of a file name, a public key, a version number and culture (locale details)
gives an assembly a strong name, which is guaranteed to be unique. Now let's first see what are
public and private keys and then see how to build them.

Public, Private Keys And Encryption

Encryption is the act of encoding files/programs so that others not privy to the decryption
mechanism cannot understand the content's of the text. Thus encryption is the process of hiding
our data from anyone and everyone we feel should not know it. Under .NET platform this has
special significance since here we distribute our IL (Intermediate Language) code embedded in
assemblies, instead of the executable machine code, which is not too much difficult to decipher.
.NET has a strong inbuilt mechanism to maintain the privacy of code. If this had not been the
case, any one with the ILDASM.EXE utility would have an access to your code. Not only that he
or she would also have the opportunity to distribute it under his name. .NET achieves this security
by public key encryption.
Public Key and Private Keys are complimentary entities; one is meaningless without the other.
The creation of Public and Private Keys is carried out by complicated mathematical algorithms. A
document encrypted with one key can be decrypted only using the other key. Not even the key
with which we encrypted the data can be used to decrypt it back. The public key can be
distributed freely without any fear of it being misused.

Building the Keys

To build public and private keys we have to use the sn (standing for strong name) utility. This
utility generates a public/private key pair. The public key created using this utility will be used to
define a strong name. To create the key pair we must type the following at command prompt:

C:\CSharp\fontassembly>sn -k mykey.snk

On executing the utility a file called mykey.snk gets created. This file contains the public and
private keys

To create a strong name the compiler uses the public key from the mykey.snk file, hence we
must provide this file to the compiler. To do so we would have to open the AssemblyInfo.cs file
of the project. In this file we would have to set the AssemblyKeyFile attribute to the '.snk' file
path. The attribute must be either set to an absolute path to the key file or if the file is copied to
the local directory of the project, only the file name must be mentioned. We need to add the
following to the 'AssemblyInfo.cs' file.

[ assembly: AssemblyKeyFile ( "mykey.snk" ) ]

We should also change the version number of our assembly as shown below.

[ assembly: AssemblyVersion ( "1.0.1.1" ) ]

On rebuilding the program, the assembly would now use the public key from the mykey.snk file
along with the name of the assembly, the version number and the culture to build a strong name.
Culture is a combination of a two letter word indicating the language and a two letter word
indicating the country code. The strong name never contains the private key. This ensures that
the private key is not written in the manifest and hence is not made available to everybody. This
strong name is written in the manifest of the assembly.

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

Along with the strong name, the compiler also generates a cryptographic hash from the names
and contents of the files in the assembly. The compiler then encrypts the cryptographic hash for
the assembly using the private key (available in mykey.snk). It places the encrypted hash in the
manifest of the assembly. This hash would be used by the client to check the authenticity of the
assembly.
So, in all, two things are written inside the manifest, the strong name and the encrypted hash of
the names and contents of the files. The process of writing the encrypted hash value in the
manifest is called 'Signing of an assembly'. Now our shared assembly is ready. To make it
available to all the clients we would have to install it in the Global Assembly Cache. All the
shared assemblies available on a system are stored in the Global Assembly Cache. This store
is located in the <drive>:\Windows\Assembly folder.

Installing The Shared Assembly

To install a shared assembly in the global cache we would have to use the Global Assembly
Cache utility tool called gacutil along with the /i option. Here /i stands for install. This is what we
must type at the command prompt to install the assembly.

C:\CSharp\fontassembly\bin\Debug>gacutil /i fontassembly.dll

If the assembly is successfully installed, the following message would appear:

Assembly successfully added to the cache

Building The Client

Let us now build a client that would use the assembly that we created above. To create the client
select a 'Windows Application' project and name it as fontclient

When we click on the form, some text should be displayed at the position where we click. This
can be achieved by calling the display( ) method from 'fontassembly.dll' in the
Form1_MouseDown( ) handler. To have access to this method we have added a reference of the
mytext class as a data member of the Form1 class. The Form1_MouseDown( ) handler is
shown below.

private void myform_MouseDown ( object sender, System.Windows.Forms.MouseEventArgs e )


{
if ( e.Button == MouseButtons.Left )
{
Point pt = new Point ( e.X, e.Y ) ;
t.display ( this, "Hello", Color.Red, "Comic Sans MS", 30, pt ) ;
}
}

Here we have first checked whether the left mouse button has been clicked. If so then we have
called the display( ) method of the mytext class from the fontassembly assembly.

For the mytext class to become available we have added the statement using fontassembly ;.
However this is not enough. We also need to add a reference to the library. To do this we should
right click on 'References' in the Solution Explorer window and select 'Add References'. On doing
so the 'Add References' window would appear. Execute the program and click on the form, a
string "Hello" would appear at the point where mouse is clicked.

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

Article: C# - Emitting Metadata

Reflection is generally used for three purposes: viewing metadata, type discovery and invoking
methods. However, the most powerful use of Reflection is emitting metadata to assembly.
Reflection emit supports creation of types at run-time. For emitting metadata, .NET has provided
Reflection.Emit namespace.

Reflection emit enable creation of dynamic module defined in a dynamic assembly. A dynamic
module created in a dynamic assembly can be transient or persistable.

When I first read about Reflection emit the first question came to my mind is that where on earth
would I need to write metadata to an assembly when the compiler does it for us? I found few
application scenarios where the applications use Reflection emit. Some of them are executing a
script in a web browser, executing a script in an ASP.NET Page, compiling a Regular Expression,
etc. Let us discuss these scenarios in brief.

When a web browser requests for an HTML page containing a script program the web browser
first launches the script engine. Then it extracts the script from the HTML page and passes it to
the script engine. The script engine creates a dynamic assembly by writing metadata on the fly.
The script engine uses the Reflection emit functions to emit the code into the dynamic
assembly.

In the second scenario, a browser opens an ASP.NET page containing a script program. The
program is compiled on the server and executed. For this, ASP.NET launches the script engine to
compile and execute the program. The script engine creates a persistable dynamic assembly and
a dynamic module in it. It compiles the program using the reflection emit functions and emits the
code into the persistable dynamic module. The compiled code is then executed. If any expression
is encountered the script engine creates a transient dynamic module in the dynamic assembly to
contain the code for the expression. The script engine evaluates the expression by executing the
transient dynamic module. ASP.NET requests the script engine to save the dynamic assembly
and the persistable dynamic module in the cache so that the script does not need to be
recompiled when the page is visited again.

In the third scenario, a compiler uses Reflection emit to compile regular expressions in source
code. The compiler processes the first use of a regular expression in a user’s source code. The
compiler compiles the regular expression into a custom scanner class using reflection emit. The
regular expression is first translated to the compiler’s regular expression bytecodes. For example,
one instruction might say, “try to match zero or more a’s.” The regular expression bytecodes are
then translated to Microsoft intermediate language (MSIL). For example, the compiler might
generate a loop that iterates over all the occurrences of the letter 'a' that it found. The compiler
saves the compiled scanner class for future use. Whenever a subsequent expression is
encountered, the compiler instantiates the compiled scanner class and executes the code.

In this article we would create a type called sample at run-time and store it in an assembly. The
class has a method fun( ) that outputs a string “Hello” on console. Here is the source code.

static void Main ( string[ ] args )


{
AssemblyName an = new AssemblyName( ) ;
an.Name = "emitassembly" ;

AppDomain ad = Thread.GetDomain( ) ;
AssemblyBuilder ab = ad.DefineDynamicAssembly ( an, AssemblyBuilderAccess.Save ) ;

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

ModuleBuilder mb ;
mb = ab.DefineDynamicModule ( "emitmodule", "emitmodule.mod" ) ;

TypeBuilder t = mb.DefineType ( "sample", TypeAttributes.Public ) ;

MethodBuilder m = t.DefineMethod ( "fun", MethodAttributes.Public, typeof ( void ), null ) ;

ILGenerator mil = m.GetILGenerator( ) ;

Type[ ] tp = new Type [ 1 ] ;


tp [ 0 ] = typeof ( String ) ;
MethodInfo wm = typeof ( Console ).GetMethod ( "WriteLine", tp ) ;

mil.Emit ( OpCodes.Ldstr, "Hello" ) ;


mil.Emit ( OpCodes.Call, wm ) ;
mil.Emit ( OpCodes.Ret ) ;

t.CreateType( ) ;
AssemblyBuilder asb = ( AssemblyBuilder ) t.Assembly ;
asb.Save ( "emitassembly.dll" ) ;
}

The first step in creating a type is to create an assembly. We have created an assembly named
‘emitassembly’ using the Reflection.AssemblyName class. An object of AssemblyName class
fully describes an assembly’s unique identity. Using this object we have obtained an object of the
Reflection.Emit.AssemblyBuilder class. To obtain the assembly builder object we have called
the DefineDynamicAssembly( ) method on current domain. The current domain is obtained by
calling the GetDomain( ) method of the current thread. The parameters passed to the
DefineDynamicAssembly( ) are the assembly name and an assembly access mode. The 'Save'
mode specifies that the assembly we are creating will be persistable i.e will be saved on disk. If
we specify the access mode as ‘Run’ instead of ‘Save’ the assembly would be transient. It can be
executed but would not be saved on disk. The third mode is ‘RunAndSave’ which means the
dynamic assembly can be executed and saved on disk. The type we would create will be written
in a module built dynamically. We have created this module using the
Reflection.Emit.ModuleBuilder object. The method DefineDynamicModule( ) creates a
module named ‘emitmodule’ and saves it on disk in a file ‘emitmodule.mod’. We can now emit the
type sample in the module emitmodule. The DefineType( ) method of the ModuleBuilder class
defines the specified type and returns an object of Reflection.Emit.TypeBuilder object. The
TypeBuilder class provides methods using which we can define classes, methods and fields.

In the next statement we have defined the method fun( ). The second parameter specifies the
access specifier, whereas, third and fourth parameters specify the return type and an array
containing types of parameters respectively.

Now since our type stands created, only thing remaining is to emit the body of the fun( ) method.
The Reflection.Emit. ILGenerator class is used to generate IL instructions. The class contains a
method called Emit( ) that is used to write the IL into the assembly.

We are supposed to call the WriteLine( ) method from the fun( ) method. So, we have firstly
obtained the MethodInfo object representing the WriteLine( ) method. The GetMethod( )
method would match the WriteLine( ) method receiving a string.

mil.Emit ( OpCodes.Ldstr, "Hello" ) ;


mil.Emit ( OpCodes.Call, wm ) ;
mil.Emit ( OpCodes.Ret ) ;

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

The first call to Emit( ) method would push the reference to the string “Hello” to the metadata.
The second call would call the method as described by the second parameter. The third call to
the Emit( ) method would return from the method. The OpCodes is the class that contains
number of static fields representing the IL instructions.

Next, we have cooked the type by calling the CreateType( ) method of the TypeBuilder class.
The Assembly property of the TypeBuilder class returns the dynamic assembly that contains
calling type. We have stored this assembly object in the AssemblyBuilder class. This is possible
because the Assembly class is the base class of the AssemblyBuilder class. Finally we have
saved the dynamic assembly to the disk using the Save( ) method of the AssemblyBuilder
class. Add the using statements as given below.

using System.Threading ;
using System.Reflection ;
using System.Reflection.Emit ;

Let us use this assembly in a test program. Create another console application and write the
following statements in Main( ).

sample s = new sample( ) ;


s.fun( ) ;

Add reference to the ‘emitassembly.dll’ through Solution Explorer. Run the program. The string
“Hello” would get displayed on the console.

Another way to invoke the fun( ) method is to use Reflection as shown below.

Assembly a = Assembly.LoadFrom ( "emitassembly.dll" ) ;


Type t = a.GetType ( "sample" ) ;
Object o = Activator.CreateInstance( t ) ;
t.InvokeMember ( "fun", BindingFlags.InvokeMethod, null, o, null ) ;
Article: C# - Adding Resources To Assembly

An assembly can contain resource files. An assembly containing resources is called 'satellite
assembly'. A resource file can contain any resource such as text, string tables, pictures, etc. The
resource file can be embedded inside the assembly. In this article we plan to create a resource
file called 'quotes.resources' in an application called res and embed this file in another assembly
called resclient. The 'quotes.resources' file would contain 5 images and 5 quotes as resources.
The assembly in which we would embed this file will simply pick out a random image and a quote
and display them on a form. Let us first see how to build a resource file.

Create a Console Application. Add the following code in the Main( ) method.

using System ;
using System.Resources ;
using System.Drawing ;

static void Main ( string[ ] args )


{
ResourceWriter rw = new ResourceWriter ( "quotes.resources" ) ;

Image img0 = Image.FromFile ( "heart.jpg" ) ;


Image img1 = Image.FromFile ( "fire.jpg" ) ;

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

Image img2 = Image.FromFile ( "face02.jpg" ) ;


Image img3 = Image.FromFile ( "face03.jpg" ) ;
Image img4 = Image.FromFile ( "face05.jpg" ) ;

rw.AddResource ( "img0", img0 ) ;


rw.AddResource ( "img1", img1 ) ;
rw.AddResource ( "img2", img2 ) ;
rw.AddResource ( "img3", img3 ) ;
rw.AddResource ( "img4", img4 ) ;

rw.AddResource ( "quo0", "Health is wealth" ) ;


rw.AddResource ( "quo1", "A long journey starts with the single step" ) ;
rw.AddResource ( "quo2", "Better late than never but better never late" ) ;
rw.AddResource ( "quo3", "Opportunity knocks for those who listen" ) ;
rw.AddResource ( "quo4", "The best time to make a friend is before you need one" ) ;
rw.Close( ) ;
}

After creating a ResourceWriter reference we have created 5 Image references img0 through
img4 and initialized them with images from 5 different files. Next we added these resources in the
file using the AddResource( ) method of the ResourceWriter class. The first argument of the
method specifies the key and the second argument specifies the image object to be added. The
key that we have added is in the form imgnumber. Note that the image files must either be in the
'bin/debug' folder or their path must be specified..

Next we have added 5 quotes to the same file with the key format quonumber. Then we have
closed the ResourceWriter by calling the Close( ) method.

On executing this application a file called 'quotes.resources' gets created. Now let us see how to
embed this file in another assembly. For this we have created a simple windows forms application
called resclient and added a PictureBox named pic and a Label named quote to it. We have
changed the font size and color of the text that would get displayed in the label using the
'Properties' window.

To embed the resource file we need to select the 'Add | Add Existing Item' from the context menu
that pops up on right clicking the Solution Explorer. Select the 'quotes.resource' file. The file gets
displayed in the Solution Explorer. In the Properties window of this resource file change the
BuildAction from None to Embedded Resource so that the resource gets embedded into the
output assembly. The 'Properties' window is shown in the following figure.

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

After this much is done, we have added code to the constructor of the form class to display a
quote and a picture in the form. The constructor is given below:

public Form1( )
{
InitializeComponent( ) ;
Assembly asm = Assembly.GetExecutingAssembly ( ) ;
ResourceManager rm = new ResourceManager ( "resclient.quotes", asm ) ;
Random r = new Random( ) ;
string str ;
int i = r.Next ( 4 ) ;
str = string.Format ( "img{0}", i ) ;
pic.Image = ( Image ) rm.GetObject ( str ) ;
i = r.Next ( 4 ) ;
str = string.Format ( "quo{0}", i ) ;
tip.Text = ( string ) rm.GetObject ( str ) ;
}

To use the embedded resource, we have used the ResourceManager class defined in the
System.Resources namespace. We need to pass the reference of the Assembly class where
the resources are embedded to the constructor of the ResourceManager class. In this case the
file is embedded in the executing assembly, so we have passed the result of
Assembly.GetExecutingAssembly( ) as the second argument. The first argument is the root
name of the resource file. The root name is made of the namespace followed by the name of the
resource file without extension. We have collected the reference of this ResourceManager object
in rm.

To extract a resource from the file we have used the GetObject( ) method. We have passed a
key to this method. This method returns us the object associated with the key specified. To create
the key we have used the Random class's Next( ) method that would return any number between
0 and 4 (0 & 4 inclusive). Next we have set the Image property of pic and Text property of quote
to the Image and string objects respectively returned by the GetObject( ) method. The output of
this application is shown in the following figure.

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

Every time we execute this application we get a different picture and quote on the form.

Article: C# - XML And ADO.NET

A powerful feature of ADO.NET is its ability to convert the data stored in a data source in XML
and vice versa. In this article we would read records from a data source and display them in a
'DataGrid' control. At the same time we would write the records in an XML file. The contents of the
XML file would get displayed in a text box where we can modify it. The modified contents would
get added to the data set and would get displayed in the 'DataGrid' control. We are going to use
OLEDB for accessing the database.

Let us first understand few basic issues in the ADO.NET technology. The System.Data
namespace is the root namespace of ADO.NET API. The primary namespaces of ADO.NET,
System.Data.OleDb and System.Data.SqlClient contain classes that enable programs to
connect with and modify the datasources. A datasource can be any file containing records such
as a '.mdb' file. The namespace OleDb can be used to work with any datasource. On the other
hand SqlClient namespace is used for working with MS SQL Server 2000 datasources.

ADO.NET has two major components-DataSet and .NET Data Providers. A .NET Data Provider
is used for connecting to a database, executing commands, and retrieving results.

DataSet is used to cache the data read from the datasource in local memory. The data stored in
the memory can be modified and written back to the datasource. The System.Data.DataSet
class is provided to take care of the DataSets.

Let us move on and write a program using ADO.NET. Create a Windows application and design
the form as shown in the following figure.

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

The dark gray colored control is the 'DataGrid' control. The controls, their Names and handlers
are given in the following table.

Control Name Handler


DataGrid dg -
Write Button wb Click
Clear Button cb Click
Read Button rb Click
TextBox xmltext -

First of all we would look at the Click event handler for the 'Write' button.

private void wb_Click ( object sender, System.EventArgs e )


{
String constr = @"Provider=Microsoft.Jet.OLEDB.4.0; Data Source=c:\book.mdb" ;
OleDbConnection con = new OleDbConnection ( constr ) ;
con.Open( ) ;

String comstr = "SELECT Name, Email, Phone FROM addressbook" ;


OleDbCommand com = new OleDbCommand ( comstr, con ) ;

OleDbDataAdapter adapt = new OleDbDataAdapter ( com ) ;


adapt.Fill ( dset, "addressbook" ) ;

dg.SetDataBinding ( dset, "addressbook" ) ;

dset.WriteXml ( "addressbook.xml" ) ;
xmltext.Text = dset.GetXml( ) ;

con.Close( ) ;
}

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

Interacting with a database using ADO.NET involves connection and command objects. Since we
have used OLEDB to access the database, the connection must be established between the
database and OLEDB .NET Provider. The class OleDbConnection is used for this job. So, in this
method we have firstly created an object of this class passing to it the connection string. The
connection string contains the name of the OLEDB .NET Provider and that of the datasource. Our
datasource is 'book.mdb' that maintains an address book. This file is already created using
Microsoft Access. It contains details like names, e-mail IDs and phone numbers. Only creating
object of connection class does not physically open a connection to the database. Calling Open( )
method does. So we have called the Open( ) method in the next statement.

The Command object allows us to execute an SQL statement or a stored procedure in a data
source. We have created the command object using the OleDbCommand class and passing to it
the command string. The command string contains the SQL statement to select all the records
from the datasource.

The command object is used to connect the connection object to a DataAdapter object. A
DataAdapter is used to fill data from the database into the DataSet object. To read the records
into the DataSet we have used the OleDbDataAdapter.Fill( ) method. To this method we have
passed the DataSet object dset and the table name. Add the data member dset of type DataSet
to the form class. Initialize the data set object in the constructor as

dset = new DataSet( ) ;

Next, we have called the DataGrid.SetDataBinding( ) method to bind the grid control with the
datasource. We have passed the DataSet object as the first parameter to specify whose data the
grid control should display. Second parameter is the name of table within the datasource we want
to bind to the control. When this function call is executed, the data grid is filled with the records in
the DataSet.

Next comes the main part of the program i.e writing records to an XML file. The
DataSet.WriteXml( ) method generates the XML representation of the data contained in the
DataSet object and writes it to the specified file. We have displayed the same XML data that we
have just written to the file in the text box. For this, we have called the DataSet.GetXml( )
method.

The OleDbConnection.Close( ) method closes the connection with the datasource. A part of the
XML file is given below.

<NewDataSet>
<addressbook>
<Name>Meghana</Name>
<Email>Meg2003@hotmail.com</Email>
<Phone>2242567</Phone>
</addressbook>
….
</NewDataSet>

On clicking the 'Clear' button the grid control should get cleared so that we can display modified
contents in it. The code to clear the control is given in the cb_CLick( ) event handler. The handler
is given below.

private void cb_Click ( object sender, System.EventArgs e )


{
dset.Clear( ) ;
dg.Update( ) ;

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

Since the grid control is attached to the datasource represented by dset, clearing dset and
updating the grid control clears the contents from it.

Now add the following node to the XML data displayed in the text box.

<addressbook>
<Name>Sanjay</Name>
<Email>sanju@hotmail.com</Email>
<Phone>227257</Phone>
</addressbook>

Click the 'Read' button. Following handler would get called.

private void rb_Click ( object sender, System.EventArgs e )


{
StreamWriter sw = new StreamWriter ( "addressbook.xml", false ) ;
sw.Write ( xmltext.Text ) ;
sw.Close( ) ;
dset.ReadXml ( "addressbook.xml" ) ;
dg.SetDataBinding ( dset, "addressbook" ) ;
}

Here, we have used the StreamWriter class to write the contents from textbox to the XML file. To
read new contents of the file and fill the DataSet with it we have used the ReadXml( ) method.
Again to fill the grid control we have called the SetDataBinding( ) method. The result is shown in
the following figure.

Note that we must add the following declarations at the beginning of the program.

using System.Data.OleDb ;
using System.IO ;
Article: C# - Using MS Agents - I

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

The characters provided by Microsoft Agent technology are something we often use in MS-Word,
Excel and PowerPoint applications. These are cute animated characters that appear to help us
finding answers to questions. The MS Agent characters can be added to Windows applications as
well as to Web applications. The MS Agent control provides access to four animated characters-
Genie (genie), Merlin (genius), Peedy (parrot) and Robby (robot). Out of these we are going to
use Peedy and Merlin in this article.

The synopsis of the application is like this. We would first create a ‘timer’ user control that would
show current time on a label. The control would expose two properties through which client can
set the alarm time and a message string. It would also throw an event when the time set by the
client and the current time equals. The client would handle this event and communicate the
message through either Peedy or Merlin. Selection of animation character can be made through
radio buttons. Every character supports number of animations. Our application would allow user
to select the animation using a combobox. The characters would also speak the text that the user
would enter in a text box.
Let us see in brief how to create a user control. Create a ‘Windows Control Library’ project named
‘ClockControl’. As soon as we do this, a class called UserControl1 gets created. Add two labels
and a timer control (named mytimer) to the form. Set the Interval property of the Timer control to
1000 milliseconds (1 second). Add two methods—start( ) and stop( )—to the UserControl1
class. These methods are given below.

public void start( )


{
DateTime d = DateTime.Now ;
sec = d.Second ;
min = d.Minute ;
hrs = d.Hour ;
mytimer.Start( ) ;
}
public void stop( )
{
mytimer.Stop( ) ;
}

Add the three integers—sec, min and hrs as data members of the class that represent the
seconds, minutes and hours respectively. In the start( ) method we have set these data members
to the present time using DateTime class. We have then started the timer by invoking the Start( )
method of the Timer control. In the stop( ) method we have stopped the Timer using the Stop( )
method. Add the Tick event handler. In this event handler we have simply displayed the current
time in the label control named time. The mytimer_Tick( ) handler is given below.

private void mytimer_Tick ( object sender, System.EventArgs e )


{
sec += 1 ;
if ( sec == 60 )
{
min += 1 ;
sec = 0 ;
if ( min == 60 )
{
hrs += 1 ;
min = 0 ;
}
}

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

String str = hrs + ":" + min + ":" + sec ;


time.Text = str ;
}

Add the data members altime and almessage of type string. Add the AlarmTime and Message
properties for these data members. Now our approach is that whenever the alarm time becomes
equal to the current time, the event must be raised. To do so, we need to keep on checking the
current time in the mytimer_Tick( ) event handler and once the condition is satisfied we need to
throw an event to the client. Declare the delegate and an event in the UserControl1 class as
shown below:

public delegate void del ( object sender, TimeEventArgs e ) ;


public event del d ;

The TimeEventArgs is a user-defined class that needs to be necessarily derived from the
EventArgs class. This class simply contains a public data member msg of type String and a
constructor to initialize msg. The TimeEventArgs is given below.

public class TimeEventArgs : EventArgs


{
public String msg ;
public TimeEventArgs ( String s )
{
msg = s ;
}
}

Add the code as shown below to check the time and raise the event.

int i = str.LastIndexOf ( ":" ) ;


str = str.Substring ( 0, i ) ;
if ( ( str == altime ) && ( sec == 0 ) )
{
TimeEventArgs t = new TimeEventArgs ( almessage ) ;
d ( this, t ) ;
}

Here, when the current time equals the alarm time, we have created an object of the
TimeEventArgs class by passing the message to it and raised the event d. Build the application.
The ‘ClockControl.dll’ file would get created.

Article: C#- Using MS Agents - II

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

We would now create the client. Create a Windows application and design the form as shown in
the following figure.

Note that in order to run the application we must first download and install Microsoft Agent
software from the website www.microsoft.com/products/msagent/downloads.htm. Next we need
to add them to the toolbox by right clicking on the Toolbox and selecting ‘Customize Toolbox’.
From the dialog box that would appear we need to select Microsoft Agent Control 2.0 and then
click on ‘OK’. On doing so the Microsoft Agent control would get added to the toolbox. Next we
need to drag the control on the form. On dragging the Microsoft Agent control an object of the
type AxAgent class that belongs to the AxAgentObjects namespace gets added as data
member of our Form1 class. Following table shows the controls and their properties.

Control Name
TextBox speechtext
Speak button speak
Peedy
ped
Radiobutton
Merlin
mer
Radiobutton
ComboBox mood
Change button change
Agent agent
Add the following code to the constructor.

String loc = @"C:\WINNT\msagent\chars\" ;


agent.Characters.Load ( "Merlin", loc + "merlin.acs" ) ;
agent.Characters.Load ( "Peedy", loc + "peedy.acs" ) ;
speaker = agent.Characters [ "Peedy" ] ;
loadmoods( ) ;

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

speaker.Show ( 0 ) ;

Here we have first created a string, loc, specifying the location of the character on the disk. Next
we have used the Load( ) method of IAgentCtlCharacter, whose reference can be obtained by
accessing the Characters property of AxAgent class, to load both the characters. We have
passed the character name, location and file name to the Load( ) method, which creates an
object of the specified character. In this application we have planned to keep Peedy as the
default character and so set the Checked property of ‘Peedy’ radio button to true. Add a
reference to the IAgentCtlCharacter interface as the data member of the form as

AgentObjects.IAgentCtlCharacter speaker ;

Next, we collected the reference of Peedy in speaker. Then we have called the loadmoods( )
method. This is a user-defined method that populates the combo-box with names of animations.
We have then called the Show( ) method to display the character. Lastly, we have started the
timer by calling UserControl1.start( ) method. The loadmoods( ) method is defined as given
below.

public void loadmoods( )


{
IEnumerator arr ;
arr = agent.Characters [ speaker.Name ].AnimationNames.
GetEnumerator( ) ;

mood.Items.Clear( ) ;
while ( arr.MoveNext( ) )
mood.Items.Add ( arr.Current ) ;
}

Here, we have created a reference arr of the type IEnumerator. Then using the GetEnumerator(
) method we have obtained a list of all the animations of the current speaker and added the
animations to the combo-box.
User can select the character of his choice using the radio buttons and clicking the ‘Change’
button. The change_Click( ) method is given below.

private void change_Click ( object sender, System.EventArgs e )


{
String character ;
if ( ped.Checked == true )
character = ped.Text ;
else
character = mer.Text ;

speaker.Hide ( 0 ) ;
speaker = agent.Characters [ character ] ;
loadmoods( ) ;
speaker.Show ( 0 ) ;
}

Here, we have first checked which of the two radio buttons is selected using the Checked
property of the ped radio button. Then using the Hide( ) method we have removed the current
character from view and loaded the newly selected character. We have again called the
loadmoods( ) method to populate all the moods of the newly selected character in the combo
box. Finally using the Show( ) method we have displayed the character.

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

As soon as the user selects some mood from the combo box, the
mood_SelectedIndexChanged( ) event handler gets invoked. This handler is given below.

void mood_SelectedIndexChanged ( object sender, System.EventArgs e )


{
speaker.StopAll ( "Play" ) ;
speaker.Play ( mood.Text ) ;
speaker.Play ( "RestPose" ) ;
}

In this handler we have first stopped all the animations presently playing using the StopAll( )
method. Next we have played the selected mood from the combo box using the Play( ) method.
To this method we have passed the name of animation to play. After this we have played the
‘Rest Pose’ animation, which indicates an idle position of the character.
If we type something in the textbox and click on the ‘Speak’ button the speak_Click( ) event
handler gets called. Here we have first played the animation selected by the user and then played
the text written by the user using the Speak( ) method. Here is the handler.

void speak_Click ( object sender, System.EventArgs e )


{
speaker.Play ( mood.Text ) ;
speaker.Speak ( speechtext.Text, "" ) ;
}

The jobs that are remaining are adding the user control and writing an event handler for it. Add
the user control by right clicking on the Toolbox and selecting ‘Customize Toolbox’. From the
dialog box that would appear select the .NET Framework Components tab. Click the ‘Browse’
button. From the ‘Browse’ dialog select the ‘ClockControl.dll’ and click ‘Open’. The user control
would get added to the list of controls. Dismiss the dialog by clicking on ‘OK’. It would appear on
the Toolbox. Drag and drop it on the form. Name it as c. Set the Alarmtime and Message
property of the control through the Properties window. First of all we need to start the timer in the
constructor of the Form1 class by calling the start( ) method of the control. Do so as given below.

c.start( ) ;

We also need to add an event handler to handle the d event of the control. Do so through
Properties window. The code in this handler is shown below.

void c_d ( object sender, ClockControl.TimeEventArgs e )


{
int i ;
for ( i = 0 ; i < 5 ; i++ )
speaker.Speak ( e.msg, "" ) ;
}

The TimeEventArgs object would contain the message to be displayed in the msg data member.
In the event handler we have simply made the character speak out the message five times.

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

Article: C#- Solutions, Projects, Items, Etc. - I

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

Article: C#- Going International With Locale - I

As the number of Internet users grew worldwide, need to create software supporting multiple
languages was felt intensely because only ten percent of people use English as primary
language. People wanted an application that could communicate with them in their native
language. This became simple with the release of .NET framework.

Locale and .NET Culture

Geographically speaking, a locale is a place. In software terms, a locale is a set of information


associated with a place. Locale information includes the name and identifier of the spoken
language, cultural conventions, etc. A Locale Identifier (LCID) is used to retrieve information
about the locale. LCID is a 32-bit unsigned integer value that is divided into four parts. The first
two parts identify the language and sub-language (sub-language corresponds to country/region)
and the last two parts specify the sorting order for text strings.

The culture in .NET refers to user’s language and region. A culture is identified by language
code–region/country code. For example, French language spoken in France is identified by ‘fr-
FR’. Here, ‘fr’ is the short form for ‘French’ and ‘FR’ is abbreviation of France. Similarly, ‘fr-CA’ is
the culture identifier for French in Canada. There are cultures that are identified by language only.
These cultures are called neutral cultures. The cultures having language-region combination are
called specific cultures. For example, ‘fr’ is a neutral culture, whereas, ‘fr-FR’ is a specific culture.

.NET encapsulates the culture related information in the System.Globalization and


System.Resources namespaces. The object of the Globalization.CultureInfo class represents
a specific culture. Using the methods of this class, we can obtain the information of the culture
that is set for the current thread. Following code snippet shows how to set the culture for the
current thread and obtain its name, number format and currency format.

foreach ( CultureInfo c in CultureInfo.GetCultures( CultureTypes.AllCultures ) )


{
Thread.CurrentThread.CurrentCulture = new CultureInfo ( c.Name ) ;
Console.WriteLine ( "{0}:{1},Num:{2},Dt:{3},Curr:{4}",c.Name,
c.EnglishName, (12345).ToString ( "n" ), ( 12345.50 ).ToString ( "c" ),
( DateTime.Now ).ToShortDateString( ) ) ;
}

The CultureInfo.GetCultures( ) method returns the list of all the supported cultures.
CultureTypes is an enum that contains the types of culture viz. specific, neutral, all cultures and
only those cultures that are installed on the system. To set the culture for a thread, firstly we must
obtain the reference to that thread. Here, we have obtained the same by using the
CurrentThread property of the Thread class. The two culture values of an application determine
what resources are loaded for an application and how information like currency, numbers, and
dates is formatted. The resources loaded are determined by the UI culture setting, and the
formatting options are determined by the culture setting. The Thread class provides two
properties—CurrentCulture and CurrentUICulture to change the respective culture settings. We
have used the CurrentCulture property since we needed to set the culture specific formatting
options. The Name and EnglishName are properties of the CultureInfo class that give the
culture name and its corresponding Language (Country/Region) combination respectively. Of
course, we need to use the Globalization and Threading namespaces to run this code.

We would now see how to localize resources. We would create a localized WinForm application
that would allow user to select a language. On clicking a button another form would get displayed
in the selected language. This form would contain a textbox where you can type your name. On

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

clicking a button you would be greeted in the selected language. Our form would look as shown
below.

Name the radio buttons as reng, rger, rita, and rfre respectively. Name the ‘Display’ button as
bdisplay. Add the Click event handler for the ‘Display’ button. Here is the handler.

void bdisplay_Click (object sender, System.EventArgs e )


{
Thread t = Thread.CurrentThread ;
if ( rfre.Checked )
t.CurrentUICulture = new CultureInfo ( "fr-FR" ) ;
if ( rger.Checked )
t.CurrentUICulture = new CultureInfo ( "de-DE" ) ;
if ( rita.Checked )
t.CurrentUICulture = new CultureInfo ( "it-IT" ) ;
if ( reng.Checked )
t.CurrentUICulture = new CultureInfo ( "en-US" ) ;

greetform g = new greetform( ) ;


g.ShowDialog( ) ;
}

Here, we have only checked which radio button the user has selected and set the UI culture
accordingly. After this we have displayed another form. We need to add this form to the project.
Add controls to this form as shown below.

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

The controls and their names are given in the following table.

Control Name
Name text
tname
box
Greet button bgreet
Label lgreet
Close button bclose

Add the Click event handlers for the ‘Greet’ and ‘Close’ buttons. The bgreet_Click( ) handler is
given below.

void bgreet_Click ( object sender, System.EventArgs e )


{
String s ;

DateTime t = DateTime.Now ;
}

Article: C#- Going International With Locale - II

Last time we had designed the greeting form and added code to change the culture. Let us now
add localization support to it.

After we are done with developing the form, select the Localized property of the greetform to
True. This property specifies whether localized code is to be generated for this form. We must
now specify the languages that our application would support. For this, select the Language
property. Click the down arrow. It would display list of cultures. Select ‘French (France)’ then
select ‘Italian (Italy)’ and ‘German (Germany)’ one after other. As soon as we select a language,
say, French (France) two resource files ‘greetform.fr.resx’ and ‘greetform.fr-FR.resx’ get added to
our project. In these files we need to add French equivalents for the resources. Add the data as
shown in the following table in the ‘greetform.fr-FR.resx’ file. We will see the purpose of
‘greetform.fr.resx’ file later.

Name Value
Lname.Text Nom:
bgreet.Text Saluer
bclose.Text Fermer

Following table shows the data to be added to German and Italian resource files.

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

Name Value
German
lname.Text Name:
bgreet.Text Begrüßen
bclose.Text Enden
Italian
lname.Text Nome:
bgreet.Text Saluτare
Bclose.Text Argomentare

Now you can run the program. Select a language and display the greetform. The greetform in
Italian is shown in the following figure.

But there is a problem in this output. Although resources are appearing in Italian, the greeting
message is still in English. This is because, when we localize resources, an entry is made in their
properties to extract proper resource from appropriate resource file. Since welcome messages
are string literals their properties are not changed. We have to do this job ourselves. We also
need to make few changes in the program. Add the following translations in the resource files for
German, French and Italian.

Name Value
French
GoodMorning Bonjour
GoodAfternoon Bonsoir
GoodEvening Bonaprèsmidi
German
GoodMorning Guten Morgen
GoodAfternoon Guten Tag
GoodEvening Guten Abend
Italian
GoodMorning Boungiorno
GoodAfternoon Bounpomeriggio
GoodEvening Buonasera

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

We must also provide default culture settings for English. For this, we can modify the main
resource file i.e. ‘greetform.resx’. In this file we must add three resource strings and their English
equivalents that happen to be same.

Change the bgreet_Click( ) handler as given below.

private void bgreet_Click ( object sender, System.EventArgs e )


{
ResourceManager r = new ResourceManager ( "locale_greet.greetform",
Assembly.GetExecutingAssembly( ) ) ;
String s ;

DateTime t = DateTime.Now ;
if ( t.Hour <= 12 )
s = r.GetString ( "GoodMorning" ) ;
else
{
if ( t.Hour <= 19 )
s = r.GetString ( "GoodAfternoon" ) ;
else
s = r.GetString ( "GoodEvening" ) ;
}
s += " " + tname.Text ;
lgreet.Text = s ;
}

The ResourceManager class provides methods to work with culture specific resources at run-
time. The ‘locale_greet.greetform’ is the root name of the resources (If resource file name is
“MyResource.en-US.resources” then root name is “MyResource”) that we want to access from
the current assembly. We have specified fully qualified name of the resource file. We have used
the ResourceManager.GetString( ) method to extract the value of the resource passed to it as
parameter. Use the System.Resources and System.Reflection namespace for the
ResourceManager and Assembly classes respectively.

Now run the program again and confirm that the greetings are displayed in the chosen language.

Behind The Scene

Let us see what happens behind the scene when we localize the form, select the language and
compile the program.

When we set the Localizable property to true, information about all the resource strings,
properties, embedded pictures, etc. gets stored in the root resource file i.e ‘greetform.resx’. The
following statement gets added to the InitializeComponent( ) method.

ResourceManager resources = new ResourceManager( typeof ( greetform ) ) ;

The type greetform provided to the constructor is used to gather all information like assembly
name, root name of resource, etc. for finding the resources. Instead of assigning values directly to
the properties, methods like GetString( ), GetObject( ) are used to retrieve the strings and
pictures from the resource file. Before retrieving the values, the CurrentUICulture property is
checked for the current culture.

On compilation, for every localized resource separate assembly called ‘satellite assembly’ gets

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

created in the folder named after the culture name. We can find this folder in ‘bin\Debug’ folder.
The satellite assembly contains manifest describing the localized resource. Since resources are
shipped as separate assemblies and not as part of main assembly we can easily replace or
update resources corresponding to a specific culture without replacing the application's main
assembly.

We know that on selecting the language two resource files get created. One is for specific culture
(greetform.fr-FR.resx) and another for neutral culture (greetform.fr.resx). To understand the
purpose of creating two files, we must first understand the path in which localized resources are
searched.

The localized resources are searched for in a hierarchical manner. At the top of hierarchy is the
resources for default culture i.e English (“en”). Below that are the resources for any neutral
culture. Below those are the resources for any specific cultures. Suppose a user requests for the
resources localized in French (France). The CLR would first search in the global assembly cache
for the assembly matching requested culture (“fr-FR”). If not found, it searches in the folder of
currently executing assembly for the ‘fr-FR’ folder. If not found it searches the GAC again for the
fallback culture contained in the parent assembly (“fr’). If the parent assembly is not found run-
time searches all potential levels of parent assemblies. On failing that then it uses the resources
for default culture. If we don’t provide the neutral cultures problem may arise in some cases. For
example, it may so happen that a machine contains culture of “fr-CA” and our program loads the
culture “fr-FR”. If “fr-FR” is not found then run-time would directly load the English culture instead
of French culture that we could provide in neutral “fr” assembly.

Article: C#- Security Under .NET

Security in the field of computers is similar to that in the real life. We install security systems in
our homes, banks and work places. These systems include gatekeepers, ID cards, Closed circuit
cameras, etc. Parallels to these are found even in the digital world. Gatekeepers are comparable
to FireWalls. FireWalls are programs that will continuously keep a watch on the files that are
coming into our computer. Files that are known to be malicious are denied an entry. Similarly ID
cards are comparable to user names and passwords. Cameras are comparable to network
monitors or file-system monitors. Network monitors listen to and keep a record of all the
communication happening on the network. Similarly, File System monitors keep track of any
changes made to the files on the hard disk. In the computer world it is important to know who is
allowed to use something and to what extent. That “Who” could be a person sitting at a computer
or a program that is being executed. This divides security implementation in two distinct
branches.

- Protection from malicious code


- Protection from malicious users

The implementation of security in either type involves two stages, identification and deciding the
scope of activity. In security terminology this is known as authentication and authorization
respectively. Authentication is responsible for identification and authentication for deciding scope
of activity. We would discuss authentication and authorization in detail later. After a program/user
is positively identified, it needs to be decided as to what are the activities that he is allowed to do.
A list is constructed containing all the things that the program/user is allowed to do. Each entry in
this list is known as permission. The list is known as the permission set.

Windows Security Model

Windows like many other operating systems decides permissions on the basis of the type of user
who has logged in. The security features were almost negligible under Windows 9x operating

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

systems. Two users could look at each other’s personal data without ever being asked why. All
software installed were available to all the users. Windows NT had a better design. There was
now a distinction between different users using a machine. Moreover, every user had to log on to
the computer before using it and then log off. There was no such thing as a default user. The
operating system interacted differently with different users. Windows implemented a concept
called group. A group is a set of users having same permissions. And for the user the group to
which he belongs becomes his role. For example if “XYZ” belongs to the Administrator group,
then role of “XYZ” is Administrator and had permissions to almost do anything on the machine.
Then there were users, which could use the computer but could not do tasks such as installing
new software or changing system variables such as page memory size, etc. There were
Replicators, Printers, Power Users and so on. An administrator had the right to add new users to
the machine. He could decide the permissions to be given to these users. An Administrator could
also create custom groups with custom permissions. A user belonging to a certain group could do
only those things that were permitted to him and nothing else. For example a user allowed to use
only a printer could do only that besides logging on and off.

Under Windows if we intend to get some work done, we pass a request stating that to the
operating system. The operating system in turn performs the task for us. In a network, the origin
of a request could be the local machine or the remote machine. Requests could be anything like
accessing data, authenticating a user against a list of valid users maintained on the server or
using a resource like printer. The server operating systems are fine-tuned to prioritize network
requests (requests from remote computer) rather than local requests. Again keeping in tune with
the concept of security we can configure the server to respond only to certain requests and turn
down others. Another thing is, to grant permissions for requests on the basis of the computer that
is requesting or grant them on the basis of the current login on that computer. This scenario is
very flexible and highly configurable. Let’s see how the operating system manages this. With
Windows NT 3.1 and onwards, Microsoft introduced a new way of managing files on the hard disk
called the NT File System (NTFS). This file system was better than the FAT32 file system. NTFS
had provisions to allow or deny access to files on the basis of the user requesting to access it.
For every file NTFS maintains a list of users allowed to access it. This functionality is not
implemented in the FAT32 file system. Instead in FAT32, the operating system keeps a list of files
and who is allowed to access them. Such an arrangement works but at the cost of performance.

The protection mechanisms discussed above were about granting of permissions to the user who
is logged on. But if the user runs the malicious code, there is nothing that can be done to stop the
code from causing havoc. This concern has been addressed by .NET through a concept called
Code Access Security that we would discuss later.

Authentication and Authorization

As stated earlier, authentication is identification of user and authorization is granting permissions


to the identified user. In any security related scenario, Authentication and Authorization are
indispensable.

Windows NT at the time of Login, performs authentication and authorization. Windows maintains
a list of all users allowed to use that computer. This list is known as the Access Control List
(ACL). Whenever a person tries to login using one of these registered users, Windows internally
looks at ACL, and grants permissions to the user according to his or her role. Permissions are
access permissions to files, ability to install programs, modify system parameters and so on.

After authenticating a user, the next step is to determine whether that user has permission to
access the resources it is requesting. This process is known as authorization. Authorization can
be controlled using any of the following methods.

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

a. Windows Access Control List (ACL) - This allows us to create permissions specific to
the file system. Users can be
allowed or denied access to resources right at the file system level. The NTFS file system
discussed earlier is best suited
for this. Using ACL to grant/deny permissions works best where our application is
authenticated using Windows account.

b. Web Server Permissions - Web Server Permissions are configured on the IIS (Internet
Information Server). This
configuration specifies permissions such as read, right, access and denial to anyone
accessing the website. There is a
difference between NTFS permissions and Web Server permissions. Web Server
Permissions apply to all those who
access the web and FTP sites, NTFS permissions apply only to specific users and
groups with registered Windows
accounts.
c. URL Authorization - The URL maps specific users and roles to the contents of the URL.
It is possible to specifically
allow or deny users and roles, access to contents of the URL. Entries made to the
‘web.config’ file will implement this
authorization.
d. Principal Objects - Under Security terminology users or entities that have been
authenticated are known as Principals.
Identification of the principal could be through any of the above-discussed procedures or
could also be custom defined.
The .NET platform provides a GenericPrincipal Class that can be extended as per
requirements. We can then map our
custom table to the Windows accounts.

Security Under .NET

.NET security mechanisms work in close interaction with Windows security. It divides security into
two distinct models.

- Role Based Security


- Code Access Security

Role based security decides permissions on the basis of the role (or type) of the user, whereas
code access security grants permission on the basis of identity of the code. Identifying code is
identifying the location from where the code is running.

Article: C#- Role Based Security Model - I

Role based security is an elegant way to provide user authorization and user access checks for
our application. We must first understand what ‘role’ means in security vocabulary. A role is a set
of users sharing same security privileges. A user belonging to particular role can access the
code/softwares/resources for which permissions are granted for the role.
Granting permissions to access resources/code using roles rather than using a particular user is
easier to manage. For example, suppose an application grants permission to access a particular
feature to four users. Now if the number of features grow to ten the application would need to
decide which user to grant permission to access which feature and add the permissions
accordingly. If the application uses role-based security it needs to only declare that the users
belonging to a particular role can access a feature. Another important thing is, role based model
works without walking the stack. Before we learn more about role-based security let us first see
what is stack walk.

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

Stack Walk

Stack walks are an essential part of the security system. A stack walk operates in the following
manner. Every time a method is called a new activation record will be put on the stack. This
record contains the parameters passed to the method, if any, the address to return to when this
function completes and any local variables. At certain stages during execution, the thread might
need to access a system resource, such as the file system. Before allowing this access the
protected resource may demand a stack walk to verify that all functions in the call chain have
permission to access the system resource. At this stage a stack walk will occur and each
activation record is checked to see that callers do indeed have the required permission.

Principal

In case of role-based security, the code can perform actions based on the data it collects about
the user. It is best when used in conjunction with Windows 2000 accounts. The heart of Role
based security lies the Principal (identity and role of the user). Role based security is most useful
in situations where access to resources is an issue. Consider a bank, where everyone needs to
log into a software in order to use it. Access to records will depend on the role of the user trying to
access it. A clerk will login with a different role than the manager, hence he will not be allowed
access to personal data of various customers whereas the manager might have the powers to
modify them if necessary. These situations are very common and hence .NET provides easy
ways to implement security on the basis of roles. .NET allows developers to use role based
security as attributes freeing the business logic from the responsibility of performing security
checks.
Let us now put the role-based security model to work in an application. This application retrieves
personal information about employees that is stored in a database. User will be allowed to view
the database only if he has an administrative login on that computer.
Create a Windows application and design the form as shown in following figure

Change the names of the controls as shown in the following table

Control Name
Employee ID empid
First Name fname
Last Name lname
City city
Lookup button lookup
Exit button exit

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

Article: C#- Role Based Security Model - II

Now, add the Click event handler for the ‘Lookup’ button. Add the code given below in this
handler.

private void lookup_Click ( object sender, System.EventArgs e )


{
SqlDataReader dr = null ;
SqlConnection con = new SqlConnection
((@"server=(local)\NetSDK;Trusted_Connection=yes;database=backup" ));
SqlCommand com = new SqlCommand ( "Select * from Employees",con ) ;
con.Open( ) ;
dr = com.ExecuteReader( ) ;
while ( dr.Read( ) )
{
if ( empid.Text == dr [ "EmployeeID" ].ToString( ) )
{
fname.Text = dr [ "FirstName" ].ToString( ) ;
lname.Text = dr [ "LastName" ].ToString( ) ;
city.Text = dr [ "City" ].ToString( ) ;
}
}
con.Close( ) ;
}

Here, we have created three basic objects required to deal with database—dr, com and con of
type SqlDataReader, SqlCommand and SqlConnection respectively. We have then used the
ExecuteReader( ) method of the command object to execute the command and collected the
result in dr. Then we have iterated through the record set till we find the record whose Employee
ID matches with the one user has asked for. Once the record is found we have displayed it in the
text boxes.

Add an event handler for the Load event and write code in it as given below.

private void Form1_Load ( object sender, System.EventArgs e )


{
AppDomain.CurrentDomain.SetPrincipalPolicy (
PrincipalPolicy.WindowsPrincipal ) ;
WindowsPrincipal p = ( WindowsPrincipal ) Thread.CurrentPrincipal ;
lookup.Enabled = p.IsInRole ( WindowsBuiltInRole.Administrator ) ;
}

In this handler to begin with we have set the principal of the current application domain. The
method SetPrincipalPolicy( ) is used for this purpose. To access the current domain we have
used the CurrentDomain property of the AppDomain class. It returns a reference to the
application domain in which our application is running. We have passed the
PrincipalPolicy.WindowsPrincipal to this method. PrincipalPolicy is an enumeration in the
System.Security.Principal namespace. PrincipalPolicy enumeration holds three types
NoPrincipal, UnauthenticatedPrincipal and WindowsPrincipal. Of these three, the
WindowsPrincipal holds the identity of the current user logged on to Windows.

In the next statement we have created a reference to an object of type WindowsPrincipal. The

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

WindowsPrincipal class is capable of holding all information about a Windows account holder.
The reference is made to point to the identity of the current user. In the previous statement we
have setup the principal policy of the current application domain to the current user. Since our
application thread is executed inside the current application domain, CurrentPrincipal property
of the thread will hold the same value that we setup for the whole application domain in the
previous statement.

This much just to access the Windows identity of the current user. Now we must check whether or
not the role of the current user is that of the Administrator. The WindowsPrincipal object we
have referenced above has a method IsInRole( ) which compares the role of information it holds
with the one that has been passed to it. We have passed the
WindowsBuiltInRole.Administrator role to this method to check whether the user belongs to
the Administrator group. If IsInRole( ) returns true it means that the user is actually a member of
the Administrator group and hence the Enabled property of the ‘Lookup’ button is set to true to
allow user to look up the employee’s information. Otherwise the button is disabled.

If the role of the user using this program is not ‘Administrator’, then the interface will look as
shown in the following snap shot

Lastly add the Click event handler for the ‘Exit’ button and call Dispose( ) method from it to close
the form. Note that we must use System.Threading, System.SqlClient and System.Principal
namespaces to run the program.

Article: C#- Creating Web Application - I

ASP.NET is a technology used to create web applications and dynamic web sites. ASP.NET is
compatible and is integrated with the .NET environment. It is very much different from ASP. First
let’s see how it differs.

ASP (Active Server Pages) is a technology that helps us create web pages dynamically. An ASP
page is an HTML file with server-side script written in VBScript or JScript. When a client requests
an ASP page, the web server delivers the static HTML portions of the page as it is, and processes
the server side script, which further generates HTML. The problems faced with ASP are:

(a) The scripting is interpreted, leading to slow rendering of pages.

(b) The entire HTML portion (content) and scripting portion (code) is jumbled up in one ‘.asp’ file.

(c) We have to write code in ASP for everything including simple jobs like validating form fields.

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

ASP.NET solves all these problems faced with ASP. First of all ASP.NET pages are compiled and
not interpreted. Secondly ASP.NET pages are structured, meaning server-side scripts and plain
HTML are not jumbled up; scripts and HTML can be separated. ASP.NET provides a feature
called code-behind. This feature allows us to separate the server-side code of a page, and place
it into another file. A ‘.aspx’ file contains the HTML portion of the application and a ‘.cs’ file
contains the code. This allows one team of team members to concentrate on HTML design, as
others work on the code.

Web Forms

.NET Web Applications or Web Forms like WinForms brings RAD to development of web
applications. Web forms are created by dropping controls onto a form and then double-clicking
those controls and writing event handlers for them in code behind pages. The controls to be used
in Web Forms are present in the .NET Framework class library. Some controls are mere wrappers
around simple HTML tags, but others represent complex UI objects that generate HTML. Let us
first build a Web Form and then understand the working of an ASP.NET Web Form application.

In this article we would see how to create a registration form that would allow students to register
for an online course.
Let us now set to build the application. Create an ASP.NET application names ‘Registration’ by
selecting ASP.NET Web Application from the template list. On doing so a virtual directory named
Registration would get created in the IIS and its local location will be
‘C:\Inetpub\wwwroot\Registration’. As soon as we create a project the following files would get
generated in the Registration directory:

- A Global.asax file containing application-level program directives, handlers for application and
session-level events, and
declarations of objects that are globally accessible to all parts of the application.
- A Web.config file containing XML that stores the application configuration information.
- A WebForm1.aspx file containing HTML for rendering Web Forms.
- A WebForm1.aspx.cs file containing the code behind page written in C#.NET.
- An AssemblyInfo.cs file containing standard code for assembly description.
- A WebForm1.disco file describing any web services in the project.

We will only be concentrating on the ‘WebForm1.aspx’ file (content) and the ‘WebForm1.aspx.cs’
(code) file for our application.

On creating the application an empty web form would get displayed in the design view of the
‘WebForm1.aspx’ file. We intend to add a table to this form. To add a table we need to select
Table menu and then ‘Insert | Table’ option and we would be presented with the ‘Insert Table’
Dialog box. Select the rows (11) and columns (3) that we wish to add to the table. A grid would
get displayed on the form. Insert the controls—labels, text boxes, validation controls and button to
the form as shown in the following figure.

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

The details of the controls are given in the following table.

Control Name
TextBox uid
TextBox pass
TextBox cpass
TestBox sname
TextBox address
TextBox state
TextBox zip
TextBox country
TextBox mail
RadioButtonList course
Button submit

The controls appearing in red color are called validation controls. Whenever we enter something
on the form and submit it to the server it is called a postback. Validation controls provide a
method of validating user input without writing any code. Whenever postback is initiated (i.e. we
click the ‘Submit Form’ button) each control checks the control it is validating and changes its
IsValid property accordingly. If the property is set to false it means that the user input is wrong. In

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

such a case an error message is flashed. If the property is set to true the postback occurs. Some
of the validation controls that we have used in this program are given in the following table.

Control Name
RequiredFieldValidator reqid
CompareValidator compass
RegularExpressionValidator checkmail

The pass textbox would accept a password. Generally a password is something that should not
be visible hence we need to change the TextMode property of this textbox to Password. Now
whatever the student types in this textbox is substituted by *s.

We must now change the properties of validation controls. How to do this would be discussed
next week.

Article: C#- Creating Web Application - II

To accomplish this we must set the ErrorMessage property of this validator to some string and
most importantly associate this validator with the uid textbox. We can do so by setting the
ControlToValidate property of this control to the uid textbox.

The name compass is given to the CompareValidator control. This control is used to check
whether the value in the Password textbox matches the Confirm Password textbox. To be able to
do so we need to set the ControlToValidate property of the validator to cpass and
ControlToCompare to pass. If the password does not match, an error message should be
displayed.

The name checkmail is given to the RegularExpressionValidator. Here too we need to set the
ErrorMessage property to a string and the ControlToValidate property to the mail textbox. This
is because we want that the e-mail should be in a proper format. To be able to do so we can set
the RegularExpression property of this control to Internet e-mail Format. This can be done by
clicking a small button that appears beside the property name in the Properties window. On doing
so a Regular Expression Editor would get open. We can now choose “Internet E-mail address”
from the editor.

What we plan to do in this application is to store the information of the student in the database.
So whenever the student enters his or her information and clicks the ‘Submit Form’ button a
handler should get called that will write the details to the database. Add the Click event handler
for the ‘Submit Form’ button and write the code in it as shown below.

private void submit_Click ( object sender, System.EventArgs e )


{
String constr = @"Provider=Microsoft.Jet.OLEDB.4.0 ; Data
Source=c:\online.mdb" ;
String cmdstr = "SELECT * from registration" ;
OleDbDataAdapter da ;
da = new OleDbDataAdapter ( cmdstr, constr ) ;
DataSet ds = new DataSet( ) ;
DataTable dt = ds.Tables [ "registration" ] ;
da.Fill ( ds, "registration" ) ;
DataRow row = dt.NewRow( ) ;
row [ 0 ] = uid.Text ;
row [ 1 ] = pass.Text ;

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

row [ 2 ] = sname.Text ;
row [ 3 ] = address.Text ;
row [ 4 ] = state.Text ;
row [ 5 ] = zip.Text ;
row [ 6 ] = country.Text ;
row [ 7 ] = mail.Text ;
row [ 8 ] = course.SelectedItem.Text ;
dt.Rows.Add ( row ) ;
OleDbCommandBuilder mybuilder ;
mybuilder = new OleDbCommandBuilder ( da ) ;
da.Update ( ds, "registration" ) ;
Response.Redirect ( "Confirm.aspx" ) ;
}

We have used the OLEDB .NET Data provider in this case with a disconnected approach and the
data source is the ‘online.mdb’ file stored in the local drive. In this handler we have created the
connection string, the command string, the OleDbDataAdapter object and the DataSet object.
Next we have filled the DataSet with the table from the database and extracted the Table in a
DataTable object referred to by dt. Then we have created a new DataRow object. We have
initialized the row fields with the text entered in the corresponding textboxes containing the
student’s information. Next we have added the row to the DataTable object referred to by dt.
Then we have created an OleDbCommandBuilder object and updated the database using the
Update( ) method. After doing this we have used the static method called Redirect( ) of the
Response class to browse to a different page called ‘Confirm.aspx’. We can create the
‘Confirm.aspx’ file by simply adding another Webform (.aspx file) to the project (through Solution
Explorer), naming it ‘Confirm.aspx’ and adding the text to it.

Compilation

We are now all set to compile the program. We need to do so using ‘Build | Compile’ menu option.
On compiling the HTML tags present in the ‘WebForm1.aspx’ file and the code in the
‘WebForm1.aspx.cs’ file called the code-behind file, a new intermediate file would get created.
This file contains a class written in C# and is derived from the WebForm1 class that contains
code to emit HTML from ASP.NET tags. This class gets compiled to a ‘Registration.dll’ file.

Here we have chosen to deploy our files on the local machine. But if we plan to deploy it on the
Web Server, we need to copy the ‘.aspx’ and ‘.aspx.cs’ files into the virtual directory. We can also
copy the ‘Registration.dll’ file but this is optional because if the file is not deployed, it gets created
and cached in the web server as soon as the first request is made. The process of compilation is
shown in the following figure.

Let us now see the ‘WebForm1.aspx’ file in HTML view. This file contains the ASP.NET tags for
our application. The first line of this file is known as the @Page directive. This directive is given
below.

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

<%@ Page Language = "c#" Codebehind = "WebForm1.aspx.cs" Inherits =


"Registration.WebForm1"%>

This directive defines general attributes and compilation settings for ASPX files (for example, C#
or VB). It also specifies the code behind file and the base class from which the intermediate class
was derived.
Sending A Request
Now, if a client wants to send a request for executing the program that we developed, he can do
so by starting the browser and mentioning the following URL

http://localhost/Registration/WebForm1.aspx

This sends a request to the server. On the server, an object of the class present in
‘Registration.dll’ would get created and an event handler called Page_Load( ) would get called.
This handler outputs HTML, which is then rendered on the client browser.
Now whenever a student enters information into the registration form and clicks on the ‘Submit
Form’ button, he is presented with the page shown in the following figure.

Article: C#- Code Access Security

Code access Security is a new concept brought in by the .NET framework. Code access security
essentially involves granting permissions to an assembly. Code access security uses the location
of assembly and other information about the identity of code as a primary factor in determining
permissions to be granted to the assembly. This information about the identity of an assembly is
called evidence. Once loaded in runtime, the code starts executing in the restricted environment
depending upon permissions granted to it. If the code is not trusted enough to run or runs but
performs an action for which it has no permissions, then a security exception is thrown. The code
access security system means we can stop running of malicious code and also restrict the code
to run in a restricted environment where we are sure that it won’t do any damage to the
resources. Let us now see few cases where code access security becomes crucial.

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

Suppose an organization is working with some extremely important data, we would use code
access security system to state which code is allowed to access the database and which is not.
Similarly if we run an application from a network drive and it tries to access the file on a local
drive an exception must be thrown. This can be done using code access security system.
It is important to know that code access security protects resources like local disk, network, user
interface from malicious code. It is not a tool for protecting software from users.

Code access security works on the basis of Code Groups and Permissions.

Code Group

Code groups are a grouping of assemblies with same privileges. For example, code groups
include “Internet” and “Intranet”. The group Internet includes code downloaded from Internet and
the group Intranet includes code sourced from LAN. The information based on which the
assemblies are grouped is called evidence. The assembly loader is responsible for collecting the
evidence at load time based on where the code is loaded from. The CLR ships with seven types
of evidence.

- Zone: Region from which the code originated


- Site: Web site from which the code was downloaded
- URL: Specific location of the code
- Application Directory: Location of the assembly
- Strong name: The unique name for the code
- Publisher: Publisher of the code
- Hash value: Hash value for the assembly

Collectively these seven types of evidence are called host evidence as they are implemented by
the host environment.

Permission

Permission means authorization to perform actions. These actions often involve accessing certain
resources. These permissions are exposed programmatically through the
System.Security.PermissionSet namespace.

Whenever a code is running, the CLR has to decide which permissions to grant that code and
which ones to deny. The CLR decides which permissions to grant and which to deny by doing a
simple trick, it checks whether the caller of our code has the permission perm1 or not. CLR
repeats this process for the callers of our assembly till there are no more callers are left. If all the
callers have that permission, our code is granted the requested permission. This can be better
explained by the following example.

Consider an assembly A. which calls Assembly B, B in turn calls C. C finally calls our assembly D.
If our assembly demands a certain permission say perm1, the CLR will first check whether our
assembly's caller (C in this case) has that permission. If it has, the CLR further looks whether B
has it or not. If B has that permission, the CLR finally checks to see whether the root assembly A
has the demanded permission. If all of the preceding assemblies C, B and A have that
permission, our assembly is also granted the permission.

Even if any one intermediate assembly does not have the demanded permission, our assembly is
denied perm1. This process of checking permissions of all the parent assemblies is known as
Stack Walking. Stack Walking is a costly activity, but considering the gains it has to offer in terms
of security implementation, Microsoft decided to implement it in the CLR.

Assemblies demand permissions when it is clear that without those permissions the assembly will
not execute. Demanding permissions is done programmatically. The following program shows us

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

how.

Our program will read a file from the local disk and display the first line. In our program we will
demand complete access to the ‘C:\’ drive. If the access demand is denied, an exception will be
raised which we will catch.

Create a Windows based application and design the form as shown below.

Name the text box as t, Read button as bread and Exit button as bexit. Add the following code in
the constructor of the Form1 class just below the call to InitializeComponent( ) method.

FileIOPermission fp ;
try
{
fp = new FileIOPermission( FileIOPermissionAccess.AllAccess, @"C:\" );
fp.Demand( ) ;
}
catch ( Exception e1 )
{
MessageBox.Show ( e1.Message ) ;
}

Here we create a reference of type FileIOPermission. We have inisialised the reference in the
try block. In the constructor we have passed the AllAccess enumerated type to specify that our
code needs complete access permissions to the ‘C:\’ drive of the machine where our application
is to execute. The constructor is followed by a demand for the above permission.

It is necessary to place the demand part in a try-catch block because if the permission is denied,
the Demand( ) method would raise an exception and our program would be terminated abruptly.

Now add a handler for the Read button. Write the code as shown below to it.

private void bread_Click ( object sender, EventArgs e )


{
StreamReader sr = new StreamReader ( "c:\\hi.txt" ) ;
t.Text = sr.ReadLine( ) ;
sr.Close( ) ;
}

We have created a stream reader object to read the “c:\hi.txt” file. Next we have read a line from
that file and displayed it in the text box t.
Now add a handler for the Exit button and call Dispose( ) method from it. Calling Dispose( )
would terminate the application if the Exit button is clicked.

Finally add the following declarations at the beginning of the program.

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

using System.IO ;
using System.Security ;
using System.Security.Permissions ;

Run this application in various scenarios, like on the local machine with security on, local machine
with security off, copy it to another machine and run it from the remote computer. Configure
security policy to give full trust for code from the remote machine and run the program. Also try
out running the program from the remote computer with security switched off. To switch the
security on/off we can use the ‘caspol’ utility that is shipped with Visual Studio.NET. This exercise
will give you a better insight into the working of code access security.

Article: C#- ASP.NET security

ASP.NET security is mostly concerned with building secured sites that serve up pages only to
authorized users. There are certain sites on the net that require login before displaying certain
pages. These sites must implement some application level security to identify authorized users.
This application-level security is provided using ASP.NET. It works in conjunction with IIS, the
.NET platform and the underlying operating system security services.

Whenever a client tries to connect to a website, it has to make a request to the Web Server for a
particular page. This request is known as a webrequest. To implement the security at application
level, the application needs to take two actions—identify the person who has made the request to
the web server and specify who can access which pages.

This action of identifying the caller of web page is known as authentication. Once authentication
is done, it is decided which pages the caller can view. This is known as authorization. ASP.NET
supports four types of authentication and authorization mechanisms.

- Windows authentication
- Passport authentication
- Forms authentication

Let us discuss them one by one.

Windows Authentication

This type of authorization is best suited for intranet applications. A user will be able to access a
requested resource only if he has a valid and active account on Windows. Moreover that account
needs to have permissions to access the specific resource. This type of authentication is very
secured since it uses hash algorithms to encode and decode client’s credentials. However there
are a few problems, this type of authentication does not work through most proxy servers,
firewalls, and some routers. Hence this technique is not very suitable for Internet applications.

Setting up Windows authentication is simple. Just make the following settings in the ‘web.config’
file of your project.

<configuration>
<system.web>
<authentication mode="Windows" />
<identity impersonate="true" />
<system.web />
<configuration />

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

These entries ask ASP.NET to use Windows authentication with Identity impersonation for the
authentication. Simply doing this will not work if IIS is configured to accept anonymous requests
to this website (by default IIS accepts anonymous requests to any Website). To turn off
anonymous access to this site, follow the instructions given below.

(a) Start Internet Services Manager from Administrative tools in the Control Panel.
(b) In the IIS, explore the branch with name same as your local machine name.
(c) Explore ‘Default WebSites’.
(d) Locate the Website we want to authenticate using Windows authentication.
(e) Right click on it and select Properties. Property pages would get displayed.
(f) Select the tab named ‘Directory Security’
(g) Click on the edit button inside the group box named Anonymous access and authentication
control
(h) In the following dialog, uncheck Anonymous access check box. Make sure Integrated
Windows Authentication check box
is checked.
(i) Click OK to dismiss the dialogs.

This process will force IIS to pop up Windows authentication dialog before displaying the web
page requested.

This can be done programmatically by modifying the <authorization> section of the web.config
file. Make the following changes to the authentication section

<configuration>
<system.web>
:::
<authorization>
<deny users="?" />
</authorization>
:::
</system.web>
</configuration>

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

We instruct IIS to not to allow any users without proper authentication. The tag deny users=”?”
will stop all unauthenticated users from accessing the website.

Passport Authentication

Passport authentication is a service provided by Microsoft. This service allows us to implement


single SignIn for multiple applications or Websites that want to authenticate users. The user is
expected to use only one user name and password to access all the sites more over, the user
need not re-SignIn whenever he switches from one site to another (provided both sites support
Passport authentication). For example, if site1.com and site2.com both support passport
authentication, then if a user visits site1.com, sign in the site and then decide to visit site2.com,
you will be automatically authenticated on the basis of the credentials you presented at site1.com.
This is possible because whenever you sign into a Passport service supporting site, the service
creates a secure cookie into our machine. Later when we visit another Passport supporting site,
our browser presents this cookie. This cookie indicates that we have already been authenticated
and no new authentication is required. To setup Passport authentication, following configuration
needs to be added to the ‘web.config’ file.

<configuration>


<system.web>
<authentication mode="Passport" >
<Passport redirectUrl="internal|url" />
<authentication />
<system.web />


<configuration />

But Passport service is not free. If we want to support Passport authentication on our website, we
will have to subscribe to it.

Forms Authentication

Form based Authentication is best suited where very high degree of security is not required. We
can use our own login form, replacing the default login provided by Windows. In almost all
situations we will allow anonymous access to our website, since authentication is done by
ASP.NET instead of IIS.

ASP.NET first checks whether there is any authentication cookie present in the request header. If
cookie is present, we know that the user is already authenticated and his identity is present in the
cookie. Otherwise the user is automatically redirected to our custom login page. The user then
presents his login credentials. If the user is authenticated, we place a cookie in the request
header and pass it on to ASP.NET other wise access is denied.

Form based authentication is configured in the ‘web.config’ file. The <authentication> section
carries information regarding cookies, password formats, list of registered users, etc.

Article: C#- The Regular Expressions

Almost every application has search facility, where we type a string in a dialog box and search it
in the given text. We can replace the string with specified string too. We can provide this kind of
facility in our program using methods of the System.String class. But if we wish to search how
many times a string is repeated or the strings starting and ending with a given character or the

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

strings representing dates in a given range or strings having repeated characters in it, etc. then
searching becomes difficult. For this kind of situation regular expression language is of great use.
In regular expressions language we can write search expressions. Using these search
expressions we can extract, delete or replace a substring. We can also split a string into
substrings.

One of the most common usages of regular expressions is to validate the user input such as e-
mail address, credit card number, ZIP code, etc. Another common use of regular expression is
‘screen scraping’. Suppose a web site extracts real time information from a database and
displays it on an HTML page. Information can be a weather report, stock exchange prices, air
ticket reservation and so on. If we want to use this information in our application we would access
the HTML page. What we would get is the HTML script. We would need to parse the script to
obtain the required information. Regular expressions can be effectively used in this task.

The regular expressions language consists of literals and metacharacters (sometimes called
escape sequences). A metacharacter acts as a command to the regular expression parser. A
parser is the engine responsible to understand and interpret the regular expression. The
System.Text.RegularExpressions namespace provides classes to create and use the regular
expressions.

Let us take an example. The metacharacter '\b' is used as a word boundary indicating either
beginning or end of a word. If we wish to search a word that starts with character ‘a’ then the
search expression will be @“\ba”. To search for a word that ends with characters ‘ing’ the
expression will be @“ing\b”. If we have to write an expression that searches strings starting with
@“\ba” and ending with @“ing\b”, what about the characters in the middle? For this, we must use
the '\S' escape sequence. '\S' stands for any character except a whitespace. So, our expression
would be @“\ba\S*ing\b”. * here means zero or more number of characters. So the expression
“\S*” means zero or more number of characters except the whitespace

Let us use this search expression in a program.

using System ;
using System.Text.RegularExpressions ;
static void Main ( string [ ] args )
{
String instr = @“It's amazing that the amount of news that happens in the world everyday
always just
exactly fits the newspaper." ;

String pattern = @"\ba\S*ing\b" ;


Match m = Regex.Match ( instr, pattern,
RegexOptions.IgnoreCase ) ;
while ( m.Success )
{
Console.WriteLine ( m.Value ) ;
m = m.NextMatch( ) ;
}
}

This program would output ‘amazing’. The Regex class contains several methods that we can
use to perform operations using the specified regular expression. Here, the string pattern
contains our regular expression. The static method Regex.Match( ) finds the string matching to
the specified pattern in the input string instr. Matching is done case-insensitively since we have
mentioned the enumerated value RegexOptions.IgnoreCase. The Match( ) method returns a
reference to an object of the Match class that we have collected in m (don’t get confused

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

between the Match( ) method and Match class). If the Match( ) method succeeds, the Value
property of the Match class contains the resultant substring and the Success property contains
true. Another property of Match class called Index contains the index of the first character of the
resultant substring. To locate and display all the matching substrings, we have called the
NextMatch( ) method of the Match class. The NextMatch( ) method returns the Match reference
with the next matching substring. If the NextMatch( ) method is called after the last match is
found, it would fail and the Success property would contain false. Instead of m.Value we can
directly pass m to WriteLine( ) method because it calls the ToString( ) method overridden in
Match class. The ToString( ) method of Match class returns the same substring that the Value
property holds.

The following table displays the metacharacters we can use in regular expression.

Expression Meaning
. Matches any character except \n
[character] Matches a single character in the list
[^characters] Matches a single character not in the list
Matches a single character in the specified
[charX-charY]
range
Matches a word character (word character is
\w
any alphanumeric character and underscore)
\W Matches a non-word character
\s Matches a whitespace character
\S Matches a non-whitespace character
\d Matches a decimal digit
\D Matches a non-digit character
^ Beginning of the line
$ End of the line
\b On a word boundary
\B Not on a word boundary
* Zero or more matches
+ One or more matches
? Zero or one matches
{n} Exactly n matches
{n,} At least n matches
{n,m} At least n but no more than m matches
() Capture matched substring
(?<name>) Capture matched substring into group name
| Logical OR

We would now write a program that splits a given input string using the specified delimiter.
Suppose we have collected e-mail addresses separated by semicolon ( ; ). Then we can split the
string into single address as shown in the following code.

String instr = "rucha_200@hotmail.com;malviya@yahoo.com;rdeshpande@hotmail.com" ;


Regex ex = new Regex ( ";" ) ;
string [ ] str = ex.Split ( instr ) ;
foreach ( string s in str )
Console.WriteLine ( s ) ;

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

We have created an object of the Regex class passing to its constructor the delimiter string i.e ‘;’.
The Split( ) method of the Regex class splits the string passed to it. It uses the pattern passed to
the Regex’s constructor. The Split( ) method splits the string into substrings and returns an array
of the substrings. We have collected the same and displayed. We can use multiple delimiters to
split a string. The multiple delimiters must be separated by a pipe ( | ) character.

We saw how to find a pattern in a string using the Match( ) and Matches( ) methods. We can use
these methods to find multiple patterns in a string too. For example,

String instr = @"The brain is a wonderful organ, it does not stop until you get into the office." ;
Regex ex = new Regex ( "(is)|(in)|(it)" ) ;
MatchCollection mc = ex.Matches ( instr ) ;
foreach ( Match m in mc )
Console.WriteLine ( "{0} found at position {1}", m, m.Index ) ;

We have specified the multiple patterns “is”, “in” and “it” separated by ‘|’. This will display multiple
instances of the given patterns along with their positions. The character ‘i’ is common in all the
patterns, so alternatively, we can use a regular expression as "i(s|n|t)".

Regular expressions language can be effectively used for creating applications like HTML
processing, HTTP header parsing, etc. Here is an example that checks the HTML script for the
‘href’ tag used for specifying links.

String instr = @"<HTML>


<A href = ""freevb.htm"">Free VB.NET source code</A>
<A href = ""freec.htm"">Free VC++ source code</A>
</HTML>" ;
string pattern = @"href\s*=\s*(?:""(?<1>[^""]*)""|(?<1>\S+))" ;
MatchCollection mc = Regex.Matches ( instr, pattern,RegexOptions.IgnoreCase ) ;
foreach ( Match m in mc )
Console.WriteLine ( m ) ;

Interpreting the expression used to find hrefs is now your job.

We can use the brackets [ ] to find a set or range of characters in a string. For example, the
expression “[aeiou]” can be used to match any vowel in the string. On the other hand, if we use ^
as the first character in [ ] then it finds characters other than those specified. For example,
“[^aeiou]” will find all the consonants. To find characters that fall in a range, we can use dash (–)
to separate the two characters. For example, the expression “\d[0-25-9]” will find any digit (\d is
used to match a digit) in the string that is in the range 0 to 2 or 5 to 9.

Groups And Captures

One of the features of regular expressions is that we can group characters together. For example,
suppose a training institute has maintained a list of machine names and their IP addresses in a
string. We can create two different groups. One group will contain machine names from all the
strings and second will contain IP addresses. Following program illustrates how to create and use
groups.

using System ;
using System.Text.RegularExpressions ;
static void Main ( string [ ] args )
{

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

string instr = "User1 192.168.90.45\n" + "User2 192.168.90.46\n" + "User3 192.168.90.47" ;


Regex ex = new Regex ( @"(?<name>\S+)\s"+@"(?<ip>(\d|\.)+)" ) ;
MatchCollection mc = ex.Matches ( instr ) ;
foreach ( Match m in mc )
{
Console.WriteLine ( "\nEntire string: {0}", m ) ;
Console.WriteLine ( "Name: {0}", m.Groups [ "name" ] ) ;
Console.WriteLine ( "IP: {0,5}", m.Groups [ "ip" ] ) ;
}
}

The groups are always created in pair of parenthesis. Our two groups namely name and ip are
noticeable by the two pairs of parenthesis.

Article – C# - Printing Through .NET

Any sophisticated application would definitely have support for printing. .NET facilitates printing
with the help of a PrintDocument component. Along with this we can make use of the various
dialog boxes that are commonly used for printing.

The PrintDocument Component

.NET supports printing through methods and properties of the PrintDocument component. The
PrintDocument component is available in the Toolbox and when added to a form, it appears in
the component tray at the bottom of the Windows Forms Designer. This is because the
PrintDocument component is not visible at runtime.

The PrintDocument class represents the PrintDocument component and falls under the
System.Drawing.Printing namespace. Typically in a printing application we call the Print( )
method of the PrintDocument class. It also contains properties such as DefaultPageSettings,
which gets or sets page settings that are used as defaults for all pages to be printed,
PrinterSettings, which gets or sets the printer that prints the document. The class contains
events like BeginPrint, EndPrint and PageEvent. BeginPrint is raised when the Print( ) method
is called and before the first page of the document is printed. Here we can do any initializations if
needed. EndPrint event is raised when the last page of the document has been printed. We can
do cleaning up jobs here. The PrintPage event is raised when it’s time to print the current page.
We can write code in the handler of this event to do the desired printing. Hence the order of
events raised when Print( ) method is called is BeginPrint, PrintPage and then EndPrint. In the
following sections, we have programmed simple examples that illustrate how to use the
PrintDocument component to achieve printing.

Printing A Salary Slip

Let us see an example where we wish to print salary slip of an employee. Here we have created
a Windows Form Application named Salaryslip. We have added 5 textboxes to the form to gather
information about the employee—a ‘Name’ textbox named name, a ‘Month’ textbox named
month, a ‘Gross Salary’ textbox named sal, a ‘Tax’ textbox named tax and a ‘Total’ textbox named
total. We have added these textboxes to collect information about an employee like his name, his
salary, the tax he needs to pay, etc. Next we have calculated his salary according to the tax. We
have also added two buttons to the form—a ‘Print’ button named print and a ‘Calculate’ button
named cal. As soon as the user clicks on the Calculate button the salary gets calculated and if
he clicks on the Print button the salary slip gets printed. Next we have added the PrintDocument
component to our form. It gets added in the component tray. We have changed the name of the
component from PrintDocument1 to mypdoc.

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

We have added an event handler called cal_Click( ) to handle the Click event of the Calculate
button. This handler is shown below:

private void cal_Click ( object sender, System.EventArgs e )


{
int t = int.Parse ( sal.Text ) - int.Parse ( tax.Text ) ;
total.Text = t.ToString( ) ;
}

Here we have subtracted the tax from the gross salary and stored it in an integer variable called t.
Then we have set the Text property of the textbox named total to t (we converted t from an
integer to a string). On clicking the Print button the event handler called print_Click( ) would get
called. This handler is shown below:

private void print_Click ( object sender, System.EventArgs e )


{
mypdoc.Print( ) ;
}

In this handler we have simply called the Print( ) method of the PrintDocument class. Whenever
the Print( ) method is called the events are raised. We have not added handlers for the
BeginPrint and EndPrint handlers. We have added a handler for the PrintPage event. If we
double click on mypdoc in the component tray of the Windows Form Designer, the
mypdoc_PrintPage( ) event handler gets added automatically to the code. This handler is shown
below:

private void mypdoc_PrintPage ( object sender, System.Drawing.Printing.PrintPageEventArgs e )


{
Graphics g = e.Graphics ;
SolidBrush b = new SolidBrush ( Color.Black ) ;
Pen p = new Pen ( Color.Black, 3 ) ;
Font f = new Font ( "Arial", 10 ) ;

g.DrawString ( "Name", f, b, 30, 50 ) ;


g.DrawString ( empname.Text, f, b, 130, 50 ) ;

g.DrawString ( "Month", f, b, 30, 70 ) ;


g.DrawString ( month.Text, f, b, 130, 70 ) ;

g.DrawString ( "Gross Salary", f, b, 30, 100 ) ;


g.DrawString ( sal.Text, f, b, 130, 100 ) ;

g.DrawString ( "Tax", f, b, 30, 120 ) ;


g.DrawString ( tax.Text, f, b, 130, 120 ) ;

g.DrawString ( "Total", f, b, 30, 140 ) ;


g.DrawString ( total.Text, f, b, 130, 140 ) ;

Font f1 = new Font ( "Arial", 15, FontStyle.Bold ) ;


g.DrawString ( "KNK Pvt Ltd", f1, b, 50, 10 ) ;

g.DrawRectangle ( p, 14, 4, 180, 175 ) ;


p.Width = 2 ;
g.DrawRectangle ( p, 22, 95, 165, 75 ) ;
}

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

PrintPageEventsArgs provides data for the PrintPage event. Using this class we have retrieved
the Graphics object using which we will do the painting. Next we have created Pen, Brush and
Font objects. Then using these objects we have printed the strings.
Run the program. Enter the salary and tax and click the Calculate button. The result would get
displayed in the Total text box. Figure 1 shows the form with salary details.

Figure 1

As soon as we click the Print button, the ‘Printing’ dialog indicating the number of page that is
getting printed gets displayed. The salary slip that gets printed is shown in Figure 2.

Figure 2

Article – C# - Form Authentication

ASP.NET has come with a new feature called Form authentication. Form authentication involves
asking the user his credentials and authenticate him to access the web pages if his credentials
are ok. Form authentication has greatly reduced the quantum of code that checks whether the
user has logged in or not, if he has not then redirects the user to the login page and if the login is
successful, redirects the user to the page he has requested. All this is managed by making
entries in ‘Web.config’ file where we can specify the login page and the pages that are protected.

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

The first time the user tries to access the protected pages ASP.NET asks him to login. If the login
is successful, ASP.NET grants him an authentication ticket in the form of a cookie and then allows
the user to the access the protected page. If the user requests the page again and again this
cookie allows him to access the pages without having to log in.

Let us now implement the form authentication in a program. Our program will have a default
page, a login page and a protected page that is displayed only if the login succeeds.

First of all to create the forms, create an ASP.NET Web application. Rename the web form to
‘public.aspx’. Also change the CodeBehind tag to ‘public.aspx.cs’. We would keep the public
page simple. It would contain only a button ‘View Page’ on clicking which it would open the
protected page. But before opening the page, it would ask username and password to the client.
Add two more web forms to the application namely ‘protected.aspx’ and ‘login.aspx’. Add a label
on the protected page that would display a message on it. Add two text boxes and a ‘Login’ button
to the login page. The text boxes would take user name and password from user. On clicking the
‘Login’ button the credentials of the client would be checked and the client would be redirected to
the protected page.

Add the Click event handler for the ‘View Page’ button in the ‘public.aspx’ file. Add the following
statement to the handler.

Response.Redirect ( "Secured/Protected.aspx" ) ;

The Redirect( ) method redirects the client to the new URL specified in it.
Open the ‘Web.config’ file that gets created in the application folder. Add the statements to the
<authentication> section so that the <authentication> section would look like this:

<configuration>
...
<system.web>
<authentication mode="Forms" >
<forms loginUrl = "login.aspx">
<credentials passwordFormat="Clear">
<user name="ypk" password="kicit" />
</credentials>
</forms>
</authentication>
<system.web />

<configuration />

The <authentication mode="Forms"> indicates that the authentication mode for this website is
‘Forms’. This means that if there is no authentication cookie in the request header, the request
has to be redirected to the login page. If the cookie is found, access to the requested page is
granted. The <forms> section contains the login URL from where an identification cookie has
been placed. Next statement indicates configuration for password. The following list specifies the
correct username and password. We can specify more than one username-password entries.

Now add the Click event handler for the ‘Login’ button. Add the following code to it.

if ( FormsAuthentication.Authenticate ( uid.Text, pwd.Text ) )


FormsAuthentication.RedirectFromLoginPage ( uid.Text, false ) ;

The Authenticate( ) method would return true if the username and password match to one
specified in the ‘Web.config’ file. If it does then the client would be directed to the ‘protected.aspx’

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

page. The FormsAuthentication class is a member of the System.Web.Security namespace.


So we must declare it at the beginning of the program.

Create a virtual directory ‘Secured’ inside the application folder. Copy ‘protected.aspx’ and
‘Web.config’ files to this folder. Open the ‘Secured/Web.config’ file and add the <authorization>
section to it. The contents of the ‘Web.config’ file are given below:

<configuration>
<system.web>
<authorization>
<deny users="?" />
</authorization>
</system.web>
</configuration>

In the authorization section we have indicated that every anonymous user has to be denied
access to the page. Run the application. The default page would get displayed as shown in the
following snap shot.

Click the ‘View Page’ button. It will take you to the login page as shown below.

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

Enter the username as ‘ypk’ and password as ‘kicit’. Click the ‘Login’ button. The protected page
would get displayed. Now request the default page again and click the ‘View Page’ button. This
time the protected page would get displayed directly without asking the username and password.

Article – C# - ASP .NET Services - I

A Web service is an application stored on a machine that can be accessible through another
machine over Internet or LAN. Even before introduction of Web services we were able to access
applications or business logics across the net. Therefore, before starting with Web Services we
must know the need that gave rise to Web services.

To begin with we would discuss the four Ps that are important in doing business using computers.

• Partners: Every business needs partners and that is how they make enormous amount of
profit.
• Profit: No business can run without making profits. Profit must increase every year to
make the business successful.
• Productivity: Computer as its very nature can be used to improve productivity of a
business and hence the profit.
• Programming should be cheap: If computer is to improve productivity of the business
programming and maintenance cost should decrease.

Let us now understand the current business scenario. We would take an example of an
airlines company. The customers of the airlines company may access the company
through personal computers, PDAs or simple phones. The airlines company may
communicate with partners such as a food company or the bank. Partners and clients
would still be there but the way they would interact would be different. The airlines
company would have a web server to which clients would send requests for ASP or
HTML pages. The request would be in form of HTTP request. The Web Server would
communicate with the business logic in the application server and use the data bases to
store the data. The Web Server would respond by sending HTML back to the clients. The
food company and bank organization would have application servers running business
logic in the form of components. They would also have data base servers for secured and
efficient data storage. If airlines company is to access the business logic exposed by
application servers of food company and bank it would do so through Remote Procedure
Calls. Also the food company and bank may also be interacting with each other.

Different client organizations would use various software and programming model. Even the
Operating Systems installed on the client devices would be different. The client would like to
interact with the Web Server using these devices. The Web Server of the Airline company may
either have IIS, JWS or Apache server running appropriate sever side scripts. The food company
may have COM+ model on their Application servers with business logic implemented as COM
components and MS-SQL database. The bank organization may have J2EE model with business
logic implemented as EJB components running on their Application Servers and data base in
Oracle.

In a distributed computing architecture the clients form the Presentation layer and the DCOM
components, EJB components, CORBA components and DCOM components form the Business
layer. The clients has to cross the firewalls to access components. Firewalls ensure that
communication is done through a specified port and data format. The external applications,

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

databases and legacy system form the Data layer. In our Airline example, the main reason of
conflict is that all the three interacting companies (airlines company, food company and bank)
have different standards. The airlines company has CORBA components installed. The food
company has DCOM components and Bank has EJB components. The problems faced in
developing these components are as follows:

• Language: DCOM components could be written only in VC++ or VB, whereas, EJB
components could be written only in Java.
• Infrastructure: CORBA components need ORB libraries and services. DCOM
components need COM libraries and services, and EJB components need J2EE
Services.
• Layout of Objects: Layout of CORBA components differ from DCOM components which
in turn differs from EJB components.
• Description: CORBA components are defined using CORBA Interface Description
Language, DCOM components are defined using Microsoft Interface definition languages
and EJB components are exposed as interfaces.
• Discovery Standards: CORBA components are discovered using the CORBA registry,
DCOM using the Registry and EJB using the Java Native Directory Interface.

The conflict between these models occur mainly due to the Wire Protocol and Data Standard.
This was different for each of the infrastructure. CORBA uses IIOP (Inter Internet Object
Protocol), DCOM uses RPC (Remote Procedure Calls) and EJB uses RMI (Remote Method
Invocation) / IIOP. All these protocols are non-standard protocols and hence are not followed by
all companies.

These existing Distributed Computing solutions suffer from various problems. For example,
DCOM is a proprietary protocol. It does not support interoperability and it has firewall problems
because DCOM transfers data in binary format and it uses many ports to call remote functions.
CORBA uses IIOP protocol, which is non-internet friendly. EJB requires very costly infrastructure.
Moreover all these object models require their client to use the same libraries as that used on
server. This makes a very tight coupling between client and the component. If component is
changed and written using new object model the client will also have to change.

To address these needs, XML Web services came into existence and were introduced as part of
ASP.NET, which is part of the .NET Framework. Web services are based on open Industry
standards, such as HTTP, XML, and SOAP. Using these open standards, Web services deliver
application functionality across the Web to any type of client, on any platform.

XML Web services are based on open Web standards that are broadly supported and are used
for communication and data formats. XML Web services provide the ability to expose application
logic as URI-addressable resources, available to any client in a platform-independent way. Web
services are self-describing. Any clients incorporating open Web standards for communication
and data formatting (HTTP and XML) can query dynamically for Web service information and
retrieve an XML document describing the location and interfaces supported by a particular XML
Web service. These open standards make Web services indifferent to the operating system,
object model, and programming language used. Web services are accessible to disparate
systems, supporting application interoperability to an unprecedented level thanks to the ubiquity
of HTTP and XML.

Instead of communicating in binary formats between applications, Web services use XML-
encoded messages. Because XML-based messaging is used for the data interchange, a high
level of abstraction exists between a Web service implementation and the client. This frees the
client from needing to know anything about a Web service except for its location, method

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

signatures, and return values. Additionally, most Web services are exposed and accessed via
HTTP, virtually eliminating firewall issues.

We would see more about Web services, the protocols they use and the way they are discovered
in the next article.

Article – C# - ASP .NET Services - II

In the last article we saw the distributed computing architecture, the different solutions for it along
with their pros and cons and the reasons why Web services came into existence. In this article we
would see more issues regarding Web services. Here we go…

SOAP

The only requirement of Web services is that both the communicating parties should have SOAP
(Simple Object Access Protocol) servers. SOAP is built upon HTTP and uses XML. It describes
function calls and their parameters using XML. The .NET Web services use this protocol for
transfer of data. A Web service is a piece of code that resides on the net server. This code can
accept request from the clients using HTTP and XML. Once a Web service is put on the Internet it
can be consumed or used by any client across the Internet that uses HTTP and XML. We can use
a Web service already available on net in our web site. For example, a book store can have a
Web service that takes an ISBN number of book and returns all the details of the book to the
user. This Web service can be used by many sites, which provide information related to books.
Apart from being generalized, the main advantage of using SOAP protocol is that SOAP can
support a rich set of data types including the primitive data types, enums, classes, structs,
ADO.NET data sets and arrays of these types.
I must note here that the Web services can be built in any .NET compliant language like VB.NET,
C# or Managed C++.
XML Web services are based on open Web standards that are broadly supported and are used
for communication and data formats. XML Web services provide the ability to expose application
logic as URI-addressable resources, available to any client in a platform-independent way. Web
services are self-describing. Any clients incorporating open Web standards for communication
and data formatting (HTTP and XML) can query dynamically for Web service information and
retrieve an XML document describing the location and interfaces supported by a particular XML
Web service. These open standards make Web services indifferent to the operating system,
object model, and programming language used. Web services are accessible to disparate
systems, supporting application interoperability to an unprecedented level thanks to the ubiquity
of HTTP and XML.

Because XML-based messaging is used for the data interchange, a high level of abstraction
exists between a Web service implementation and the client. This frees the client from needing to
know anything about a Web service except for its location, method signatures, and return values.
Additionally, most Web services are exposed and accessed via HTTP, virtually eliminating firewall
issues.

UDDI & WSDL

Web services are discovered using the UDDI (Universal Description Discovery and Integration).
We would look at UDDI in more detail later in the article. Any client can use a Web service.
Hence, when we create Web services we must provide the information programmers need to
know. For example, we must provide information about the methods available, types of
parameters and return values of methods, ways of calling these methods, how the web service
should be used, etc. This information is available through a WSDL file standing for Web service
Definition Language. This file contains XML schema that describes the web service.

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

Benefits of Web Services

One of the benefits of using Web services is that we have a broader reach. No matter what the
infrastructure is, if the object is exposed as Web service the communication becomes easier.
Another benefit is that even within enterprise the objects can be exposed as Web services. Web
services hence facilitate Business to Business (B2B) communication and Enterprise Application
Integration.

How to Use Web Service

Web services are deployed on Web Servers. Once a Web service is put on the Web any client
that understands HTTP and XML can use it. Here we have taken an example of the IIS Web
Server. The IIS has a built-in Soap Server. IIS listens for client requests on port 80. The WSDL file
can also be kept on the same web server.
The client who wants to use the web service adds the link to WSDL file in VS.NET IDE. VS.NET
then creates a proxy, which contains the methods with same name as those were exposed by the
Web service. These methods contain logic to convert the data passed by the client to SOAP
request. The client calls method in the proxy class. The proxy creates a SOAP envelope and
sends it to IIS. When IIS detects that it is a SOAP message IIS passes the message to the SOAP
server, which in turn invokes methods in the Web service. The return values trace the path back
from the server, get converted into SOAP and are sent to the proxy and finally to the client.
Like any other resources on the Internet, it would be virtually impossible to find a particular Web
service without some means to search for it. Web service directories provide central locations
where Web service providers can publish information about their Web services. Such directories
can be accessed directly or programmatically, which provide search results in response to
queries from potential Web service clients. The UDDI is such a location that defines a standard
way to publish and discover information about Web services. Using the browser we make a
request to search for the Web service. The UDDI responds with listing of the services. The list of
services contains URIs of either discovery documents or WSDL documents.
If we get this we can get the WSDL file and then the client creates a proxy object based on the
details provided by the WSDL. Once we have the proxy object we can call the methods of the
Web service.

Creating A Web Service

After understanding the need of web services, how they evolved and how they make
communication possible between heterogeneous systems, let us now see how to build and
consume a Web service. We would build a simple Web service that exposes two methods. One
method would convert temperature in Celsius to Fahrenheit. Another method would convert
temperature in Fahrenheit to Celsius. The steps to create the Web Service are given below:

(a) Open Visual Studio.NET IDE. Select 'File | New | Project | Visual C# Projects'. Select
'ASP.NET Web Service' as project template. Provide the project name as 'webservice' and click
OK. The location of this project would be 'C:\Inetpub\wwwroot' folder. The 'Inetpub' folder is
present on the local drive if IIS is installed.
(b) A form would get displayed. Right click on it and select 'View Code'. You would see a
commented HelloWorld( ) method as shown below:

//[WebMethod]
//public string HelloWorld( )
//{
// return "Hello World" ;
//}

Uncomment the code and execute the program by pressing Ctrl + F5. You would see the output
in IE as shown in the following screen shot.

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

Here, HelloWorld is a Web service. The attribute [WebMethod] enables the method from being
called by the clients through network.We would add our web methods and create a Winform
client next time.

Article – C# - Creating And Consuming Web Services

When we create a Web service project named 'webservice' a namespace having name
webservice and a class having name Service1 would get created. Change the class name to
temperature. Add the public methods ctof( ) and ftoc( ) to the class temperature. These
methods are given below.

[ WebMethod ]
public double ctof ( double c )
{
double f = ( c * 9.0 / 5.0 ) + 32 ;
return f ;
}

[ WebMethod ]
public double ftoc ( double f )
{
double c = 5.0 / 9.0 * ( f - 32 ) ;
return c ;
}

A web service class can contain methods that can be called by client or the methods that are
used internally within the class. To expose a method as a web service so that they can be called
by the clients we have to add an attribute [ WebMethod ] to it. Note that the methods to be
exposed as Web service must be declared public. Now compile and execute the program by
pressing Ctrl + F5. You will see a window as shown in the following figure.

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

Note that the 'Address' bar contains the URL 'http://localhost/webservice/Service1.asmx'. The
'.asmx' file acts as an entry point to the Web service. The statement written in the 'Service1.asmx'
file is given below:

<%@ WebService Language="c#" Codebehind="Service1.asmx.cs"


Class="webservice.temperature" %>

Here, WebService is an ASP.NET tag, which states that the code written in the specified class is
to be exposed as a web Service. The Codebehind tag specifies the name of source file in which
Web service is defined. We can omit this tag and write the Web service code in '.asmx' file itself.
In fact, defining the Web service in '.asmx' file itself facilitates the deployment of the service. The
'Service1.asmx' file contains fully qualified name of class (webservice.temperature) in which our
methods ctof( ) and ftoc( ) are defined. When the '.asmx' file is executed all those methods which
are exposed as Web service using the [ WebMethod ] attribute get displayed in the output
window.
If we click the ctof link a page as shown in the following figure gets displayed.

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

Enter a number representing the temperature in centigrade and click the 'Invoke' button. The
ctof( ) method would get called and the output would get generated in XML. You would
appreciate how testing a Web service is being made easy.
When we build the project the 'bin' folder gets created in the 'Debug' folder and 'webservice.dll'
gets created in it.
We would now create a Winform application that would use this Web service. Create the
application and design the form as shown in the following figure.

Name the text box as ttemp, label as ltemp and buttons as cb and fb respectively. We must add
a reference to the 'webservice.dll' we are going to use in this application. For this, right click on
the project name in the 'Solution Explorer' and select 'Add Web References' from the pop-up
menu. The window given below would appear.

Enter the address as 'http:\\localhost\webservice\Service1.asmx'. To use a Web service, which is


available in different machine, say User1, add its web reference by specifying the URL as
http://User1/webservice/Service1.asmx.
Click the arrow present on the right side of the 'Address' text box. A dialog box displaying a page
with links to the web methods gets displayed. Click the 'Add Reference' button on the dialog box.
On doing this, a folder 'WebReferences\localhost' gets created in the project directory. In the
'Localhost' folder four files namely, 'Reference.cs', 'Reference.map', 'Service1.wsdl' and

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

'Service1.disco' get generated. The 'Reference.cs' file contains the proxy class discussed in the
last article. The 'Reference.map' file contains the reference in the form of URLs of the '.asmx' and
the discovery files. The files 'Service1.wsdl' and 'Service1.vsdisco' are the WSDL and discovery
files respectively.
By default the proxy class gets defined in the WSclient.localhost namespace. Instead of the
localhost name we can give some meaningful name to the namespace. We can rename the
localhost namespace from 'Solution Explorer'. For this, right click the localhost name and select
'Rename' from the pop-up menu. We would give the namespace name as tempservice.
Let us now add Click event handlers for both the buttons on the form. These handlers are given
below.

private void cb_Click ( object sender, System.EventArgs e )


{
temperature t = new temperature( ) ;
double f = Double.Parse ( ttemp.Text ) ;
double d = t.ftoc ( f ) ;
ltemp.Text = d.ToString( ) ;
}

private void bf_Click ( object sender, System.EventArgs e )


{
temperature t = new temperature( ) ;
double c = Double.Parse ( ttemp.Text ) ;
double d = t.ctof ( c ) ;
ltemp.Text = d.ToString( ) ;
}

In these handlers we have used the methods exposed by our Web service. We have simply
created a reference to the temperature class's object and called the methods using it. Thus,
using a Web service is as simple as using a class.
As said earlier, the proxy class is defined in the tempservice namespace, so we must add its
declaration at the beginning of the program as,

using WSclient.tempservice ;

Run the program. Enter temperature in Celsius in the text box and click the 'Get Fahrenheit'
button. You would see the temperature in Fahrenheit displayed on the label.

Article – C# - Creating ASP.NET Client for WebService

In the last article we had created a temperature web service with two methods ctof( ) and ftoc( ).
The ctof( ) method converts the temperature in Fahrenheit to Celsius. and a WinForm based
client for it. Now let us take a look at how to create an ASP.NET Web Form client for our Web
Service.

Create an ASP.NET Web Application called 'temperatureclient'. Design the web form as shown in
the following figure using the controls from the Toolbox.

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

We have changed the background color of the table, font and font size 'Build Style' option. Select
this option from the pop-up menu that appears after right clicking on the form. We have also
changed the background colors of the label and button control by changing their respective
properties. Change the names of controls as shown in the following table.

Control Name
Text box ttemp
Celsius button cb
Farehnheight button fb
Label ltemp

The form stands created. Now we would add the reference of the Web Service assembly in our
project. For this, right click in the 'Solution Explorer' and select 'Add Web Reference' option from
the pop-up menu. On selecting this option, the 'Add Web Reference' window gets displayed.
Enter the address as 'http:\\localhost\webservice\Service1.asmx' (Name of the temperature Web
Service project is 'webservice'). Click the 'Add Reference' button on the dialog box.
On adding the reference a folder 'Web References\localhost' gets created in the project directory
containing the four files namely, 'Reference.cs', 'Reference.map', 'Service1.wsdl' and
'Service1.disco'.

Rename the namespace 'localhost' to 'currencyservice'. For this, right click the 'Web
References\Localhost' in the Solution Explorer and select 'Rename' from the pop-up menu. Also
add the reference to the currencyservice namespace at the beginning of the program:

using temperatureclient.currencyservice ;

Add the Click event handlers for both the buttons. These button handlers are given below:

private void cb_Click ( object sender, EventArgs e )


{
temperature t = new temperature( ) ;
double f = Double.Parse ( ttemp.Text ) ;
double d = t.ftoc ( f ) ;
ltemp.Text = d.ToString( ) ;
}

private void fb_Click ( object sender, EventArgs e )


{
temperature t = new temperature( ) ;
double c = Double.Parse ( ttemp.Text ) ;

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

double d = t.ctof ( c ) ;
ltemp.Text = d.ToString( ) ;
}

In these handlers we have created a reference to the temperature class's object and called the
methods using it.
Run the program. Our web form would get displayed. Following figure displays the screen shot
taken after the Web Service method ftoc( ) is invoked.

Synchronous & Asynchronous Communication

Web Services support both synchronous and asynchronous communication between the client
and the server that hosts the Web Service. Under synchronous communication, the client sends a
request to the server and waits for the response. This prevents the client from performing other
operations while waiting for the results. On the other hand, in the asynchronous communication,
the client continues processing other tasks as it waits for a response. The client responds to the
result of the service request when it becomes available.

When a proxy class is created by .NET using the wsdl tool, it generates the synchronous and
asynchronous versions of the methods in the class. The asynchronous versions consist of two
methods having names as Beginmethodname and Endmethodname. The Begin method is used
to initiate the Web Service, while the End method is used to retrieve the results.

The handler cb_Click( ) is given below that shows how to make asynchronous call to the ftoc( )
method.

private void cb_Click ( object sender, EventArgs e )


{
AsyncCallback cb = new AsyncCallback ( ftoccallback ) ;
float f = float.Parse ( ttemp.Text ) ;
t.Beginftoc ( f, cb, t ) ;

// Do some work
}

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

Here, we have firstly created a reference to the AsyncCallback delegate class. The delegate
object cb represents the method ftoccallback( ). Next, we have retrieved the value entered in the
text box and called the Beginftoc( ) method. To the Beginftoc( ) method, we have passed the
temperature in Farehnheit, reference to the callback object, and reference to the temperature
class's object. Add ftoccallback( ) as method of the WebForm1 class. This method is given
below.

public void ftoccallback ( IAsyncResult ar )


{
temperature t = ( temperature ) ar.AsyncState ;
double d = t.Endftoc ( ar ) ;
ltemp.Text = d.ToString( ) ;
}

Here, we have obtained the reference to the temperature class's object. Using this reference, we
have called the Endftoc( ) method to collect the return value, which is then displayed in the label.

Article – C# - A Tryst With Printer

Even in our increasingly digital age, there remains great power in the printed word. And though
most of us are not overly fond of the idea, we typically do end up printing reports as part of our
applications. .NET facilitates printing with the help of a PrintDocument component. Along with
this we can make use of the various dialog boxes that are commonly used for printing. We would
first get familiar with the PrintDocument component

The PrintDocument Component

.NET supports printing through methods and properties of the PrintDocument component. The
PrintDocument component is available in the Toolbox and when added to a form, it appears in
the component tray at the bottom of the Windows Forms Designer. The PrintDocument
component is not visible at runtime.
The PrintDocument class represents the PrintDocument component and falls under the
System.Drawing.Printing namespace. Typically in a printing application we call the Print( )
method of the PrintDocument class. It also contains properties such as DefaultPageSettings,
which gets or sets page settings that are used as defaults for all pages to be printed,
PrinterSettings, which gets or sets the printer that prints the document. The class contains
events like BeginPrint, EndPrint and PageEvent. BeginPrint is raised when the Print( ) method
is called and before the first page of the document is printed. Here we can do any initializations if
needed. EndPrint event is raised when the last page of the document has been printed. We can
do cleaning up jobs here. The PrintPage event is raised when it's time to print the current page.
We can write code in the handler of this event to do the desired printing. Hence the order of
events raised when Print( ) method is called is BeginPrint, PrintPage and then EndPrint.

In this article we would use the PrintDocument components and its events to print the contents
of a file. For this, we have created a WinForm application named TextPrint and created a simple
GUI as shown in the following figure.

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

We have added a textbox called filename to the form and a 'Print' button named print. We have
also added the PrintDocument component to our form and renamed it to mypdoc.
Add the Click event handler for the 'Print' button. Add the code in it as shown below:

private void print_Click ( object sender, System.EventArgs e )


{
mypdoc.Print( ) ;
}

In this handler we have simply called the Print( ) method of the PrintDocument class. Whenever
the Print( ) method is called the events are raised. We have not added handlers for the
BeginPrint and EndPrint handlers. We have added a handler only for the PrintPage event. If we
double click on mypdoc in the component tray of the Windows Form Designer, the
mypdoc_PrintPage( ) event handler gets added automatically to the code. This handler is shown
below:

private void mypdoc_PrintPage ( object sender, System.Drawing.Printing.PrintPageEventArgs e )


{
StreamReader reader = new StreamReader ( filename.Text ) ;
string str = reader.ReadToEnd( ) ;
reader.Close( ) ;
Font f = new Font ( "Arial", 10 ) ;
e.Graphics.DrawString ( str, f, Brushes.Black, 10, 10 ) ;
}

PrintPageEventsArgs provides data for the PrintPage event. This data include the Graphics for
the printer, the PageSettings for that page, the bounds of the page, and the size of the margins.
We have used the Graphics object for printing the text.

Here we have created an object referred to by reader of the StreamReader class by passing the
file specified in the filename textbox to the constructor of the StreamReader class. To create an
object of the StreamReader class we must add using System.IO to our code. Then using this
object we have called the ReadToEnd( ) method which reads the stream till the end and returns a
string which we collected in str. Next we have created a font object. Then using the
DrawString( ) method we printed the string.

Printing Graphics From A File

Now let us see how to print graphics from a file. To demonstrate this we have created a WinForm
application called GraphicsPrint. The UI of this application is same as TextPrint and the
print_Click( ) handler is also same. We have made changes only in the mypdoc_PrintPage( )
shown below:

private void mypdoc_PrintPage ( object sender,


System.Drawing.Printing.PrintPageEventArgs e )
{

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

e.Graphics.DrawImage ( Image.FromFile ( filename.Text ), 0, 0 ) ;


}

Here we have passed the file name supplied in the textbox to the FromFile( ) method of the
Image class. We have then passed the Image object returned by the FromFile( ) method to the
DrawImage( ) method. On doing so the contents of the specified file gets printed.

Printing A Multi-page Document

The application that we saw in the previous section which prints text suffer from two limitations-it
does not print words of a line that go beyond the margins and it does not print more than one
page. This is because the PrintDocument class does not allow automatic wrapping of words that
go beyond the margin. It also crops up words that don't fit into one page.
In this section we have demonstrated how to print a line that goes beyond one line and how to
print a multi-page document. To do so we have created a Windows Form Application called
Multipage. As usual, we have added a PrintDocument component and named it mypdoc. The
UI of the application is shown in the following figure.

In addition to the filename text box and the print button here we have added a multi-line textbox
named mytext and a button named open. The idea is that whichever file is displayed in the
mytext textbox gets printed even if the words go beyond the margin and pages are more than
one. In the open_Click( ) event handler we have used an object of the StreamReader class to
read from the specified file. Whatever the StreamReader reads is displayed in the mytext
textbox. The handler is shown below:

private void open_Click ( object sender, System.EventArgs e )


{
StreamReader reader = new StreamReader ( filename.Text ) ;
mytext.Text = reader.ReadToEnd( ) ;
reader.Close( ) ;
}

Add the Click event handler for the 'Print' button and add the code in it as shown below:

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

private void print_Click ( object sender, System.EventArgs e )


{
str = mytext.Text ;
mypdoc.Print( ) ;
}

Here before calling the Print( ) method we have stored the entire text from the text box into a
String called str that we have added as a data member of the form. Here we intend to print
multiple pages. Hence we have created the Font, SolidBrush and StringFormat objects in the
handler for the BeginPrint event. Note that we could have done this in the handler of the
PrintPage event as well but then these objects would have been created for each page. The
mypdoc_BeginPrint( ) event handler is shown below:

private void mypdoc_BeginPrint ( object sender,


System.Drawing.Printing.PrintEventArgs e )
{
f = new Font ( "Arial", 12, FontStyle.Regular ) ;
b = new SolidBrush ( Color.Black ) ;
strformat.Trimming = StringTrimming.Word ;
}

We have added references f (Font), b (SolidBrush) and strformat (StringFormat) as data


members of the form class. Instantiate strformat in place as

StringFormat strformat = new StringFormat( ) ;

We have set the Trimming property of the StringFormat class to StringTrimming.Word, which
ensures word wrapping. StringTrimming is an enumeration that specifies how to trim characters
from a string that does not completely fit into the specified page layout. Word specifies that text
should be trimmed to the nearest word. Next PrintPage event is raised which invokes the
following handler:

private void mypdoc_PrintPage ( object sender, System.Drawing.Printing.PrintPageEventArgs e )


{
RectangleF myrect = new RectangleF ( e.MarginBounds.Left,
e.MarginBounds.Top, e.MarginBounds.Width,
e.MarginBounds.Height ) ;
SizeF sz = new SizeF ( e.MarginBounds.Width, e.MarginBounds.Height);
e.Graphics.MeasureString ( str, f, sz, strformat, out chars, out lines ) ;

printstr = str.Substring ( 0, chars ) ;


e.Graphics.DrawString ( printstr, f, b, myrect, strformat ) ;

if ( str.Length > chars )


{
str = str.Substring ( chars ) ;
e.HasMorePages = true ;
}
else
e.HasMorePages = false ;
}

Here we have created two objects of the RectangleF and SizeF classes according to the
MarginBounds property of the PaintEventArgs class. This property returns an object of the
Rectangle class that represents the portion of the page between the margins. Then we have

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

passed the Top, Left, Width and Height properties of this rectangle to the constructor of the
RectangleF and SizeF structure.
Next we have called the MeasureString( ) method of the Graphics class which actually does the
job of making multi-page printing easy. The first four parameters passed to this method are
passed by value and the last two parameters are passed by reference. The first parameter we
have passed is the string to be measured (str). Then we have passed f, the SizeF object that we
created and strformat that determines the formatting. The next parameters that we have passed
are two integers called chars and lines that we added as data members of the form. This method
measures the string and stores the number of characters in the string in chars and number of
lines in the string in lines that would fit in the current page according to the specified font, format,
and size.

Then using the Substring( ) method we retrieved a string that would fit in one page in another
string called printstr that we added as a data member of the form. Next we printed printstr using
the DrawString( ) method. After printing the string we have checked whether the length of the
string printed is greater than the number of characters that can fit in one page. If yes, it means
that there are more pages to be printed. So, we have collected the remaining string and set the
HasMorePages property of the PrintPageEventArgs to true. This raises the PrintPage event
again and the remaining string also gets measured using the MeasureString( ) method and then
printed using the DrawString( ) method. If this string exceeds one page then again the cycle is
repeated. This keeps on happening till the length of string becomes such that it can fit in one
page, i.e. the length becomes less than chars.

Article – C# - Common Dialog Boxes For Printing

In this article we would see how to print a multi-page document using common dialog boxes of
printing such as PrintPreview, Print and PageSetup. For these dialog boxes .NET has provided
the PrintPreviewDialog control, the PrintDialog control and the PageSetupDialog control. To
illustrate the use of these dialog boxes let us create a Windows Form application called prntdlgs.
We also added a vastly used OpenFileDialog control to the form along with two textboxes-
filename and mytext-and five buttons-a 'Browse' button named browse, an 'Open' button named
open, a 'PageSetup' button named pgsetup, a 'Print Preview' button named preview, and a
'Print' button named print. Next we added five components to the component tray and changed
their names as shown below:

Component Name
PrintDocument mypdoc
PageSetupDialog mypgsdlg
PrintPreviewDialog mypreviewdlg
PrintDialog myprintdlg
OpenFileDilaog myopendlg

The UI of the prntdlg application is shown in the following figure.

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

Next we have added Click event handlers for all the five buttons. The handler for the browse
button is given below.

private void browse_Click ( object sender, System.EventArgs e )


{
myopendlg.Filter = "Text Files ( *.txt ) | *.txt" ;
myopendlg.ShowDialog( ) ;
if (myopendlg.FileName != "" )
filename.Text = myopendlg.FileName ;
}

The 'Browse' button would let the user to select a file for printing. The user would select the file
from standard Open File dialog box. We have displayed the dialog box in this handler. The
selected file name is displayed in the text box. As soon as the user clicks the 'Open' button the
following handler gets called.

private void open_Click ( object sender, System.EventArgs e )


{
StreamReader reader = new StreamReader ( filename.Text ) ;
mytext.Text = reader.ReadToEnd( ) ;
reader.Close( ) ;
}

Here we have read the file contents with the help of an object of the StreamReader class and
displayed them on the mytext textbox. Now if the user wants to change the page settings he
needs to click the 'Page Settings' button. On doing so the following handler would get called.

private void pgsetup_Click ( object sender, System.EventArgs e )


{
try
{
mypgsdlg.PageSettings = ps ;
mypgsdlg.ShowDialog( ) ;
}
catch ( Exception ex )
{

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

MessageBox.Show ( ex.Message ) ;
}
}

We have added an object referred to by ps of the PageSettings class as a data member of the
form class as follows:

PageSettings ps = new PageSettings( ) ;

The zero-argument constructor of this class creates an object of the PageSetting class for the
default printer. The default constructor initializes all fields to their default values. Next we have set
the PageSettings property of the PageSetupDialog class to ps. Then we have displayed the
Page Setup Dialog box using the ShowDialog( ) method.
The user can also preview the page to be printed by clicking on the 'Print Preview' button. On
doing so the following handler would get called.

private void preview_Click ( object sender, System.EventArgs e )


{
try
{
str = mytext.Text ;
mypdoc.DefaultPageSettings = ps ;
mypreviewdlg.Document = mypdoc ;
mypreviewdlg.ShowDialog( ) ;
}
catch ( Exception ex )
{
MessageBox.Show ( ex.Message ) ;
}
}

Here first we have collected the string in mytext textbox in str. We have added str of type string
as a data member of the form class. Next we set the DefaultPageSettings property of the
PrintDocument class to ps. Then we set the Document property of the PrintPreviewDialog
class to mypdoc, which specifies the document to be previewed. Next we have displayed the
dialog using the ShowDialog( ) method. The PrintPreviewDialog is shown in the following
figure.

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

On clicking the 'Print' button the following handler gets called.

private void print_Click ( object sender, System.EventArgs e )


{
try
{
mypdoc.DefaultPageSettings = ps ;
str = mytext.Text ;
myprintdlg.Document = mypdoc ;
if ( myprintdlg.ShowDialog( ) == DialogResult.OK )
mypdoc.Print( ) ;
}
catch ( Exception ex )
{
MessageBox.Show ( ex.Message ) ;
}
}

Here first we have set the DefaultPageSettings property of the PrintDocument class to ps.
Next we have collected the text of mytext textbox, which is to be printed in str. The document to
be printed is then set to the Document property of the PrintDialog class. Next we displayed the
PrintDialog box using the ShowDialog( ) method and if the result happens to be
DialogResult.OK, i.e if the user clicks OK, we have called the Print( ) method of the
PrintDocument class.
On calling the Print( ) method the following handlers get invoked.

private void mypdoc_BeginPrint ( object sender, System.Drawing.Printing.PrintEventArgs e )


{
f = new Font ( "Arial", 12 ) ;
b = new SolidBrush ( Color.Black ) ;
strformat.Trimming = StringTrimming.Word ;
}

private void mypdoc_PrintPage ( object sender, System.Drawing.Printing.PrintPageEventArgs e )


{

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

RectangleF myrect = new RectangleF( e.MarginBounds.Left,


e.MarginBounds.Top, e.MarginBounds.Width,
e.MarginBounds.Height ) ;
SizeF sz = new SizeF ( e.MarginBounds.Width, e.MarginBounds.Height -
f.GetHeight(e.Graphics ) ) ;

e.Graphics.MeasureString ( str, f, sz, strformat, out chars, out lines ) ;


printstr = str.Substring ( 0, chars ) ;
e.Graphics.DrawString ( printstr, f, b, myrect, strformat ) ;
if ( str.Length > chars )
{
str = str.Substring ( chars ) ;
e.HasMorePages = true ;
}
else
e.HasMorePages = false ;
}

The code written in this handler takes care of multiple pages being printed as well as word
wrapping.

Article – C# - Custom Controls - I

Prior to .NET the controls that were popularly used as language independent reusable user-
defined controls were ActiveX controls. These included controls like multimedia controls,
spreadsheet controls, mailing controls, etc. But they had their own disadvantages. ActiveX
controls were COM-based controls and COM had a steep learning curve. In addition to this there
were overheads of maintaining the registry, maintaining CLSIDs, handling interfaces and working
through complex threading models. .NET has solved all these problems by facilitating creation of
user-defined controls in a simple manner. In this article we plan to see how to create such user-
defined controls.

Custom Controls V/s User Controls

Normally when we develop a .NET Windows application, we use controls from the
System.Windows.Forms namespace. We have a wide variety of controls available, from simple
controls such as Label and TextBox, to controls that are richer and more complex, such as
MonthCalendar and ColorDialog. While these controls are good enough for most Windows
applications we need to build, sometimes we need to create a different control that we cannot find
in the Framework class library.
We can create two types of controls-Custom Controls and User or Composite Controls.

Custom controls display UI by making calls to a Graphics object. Custom controls are typically
derived from the Control class. The Control class implements very basic functionality required
by classes that display information to the user. It handles user inputs through the keyboard. It
handles message routing and security. There is limited design-time support for creating custom
controls.

User or Composite controls are composed of other existing controls. User controls are derived
from the UserControl class. The UserControl class is also derived from the Control class There
is full design-time support for creating user controls with the Visual Studio .NET Windows Forms
Designer.

Creating A Custom Control

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

Let us create a Custom Control and use it in a Windows Form project. The idea is to make an
analog clock. Here we plan to display time in a dial using the hour, minute and second hands.
The control (after dragging and dropping it in a form) is shown in the following figure.

To create a custom control, select 'Windows Control Library' template. Name the project as
ClockCtrl.

By default a class called UserControl1 gets created, derived from the UserControl class.
Change the base class of the control class from UserControl to Control. Also change the name
of the control class from UserControl1 to Clock. Next, set the Size property of the control to 120,
120 and BackColor property to Light Blue.

To keep track of the time we must add a Timer control. Do so and name it as mytimer. Set the
interval time of the timer to 1000 milliseconds (equivalent to one second) and add a handler
mytimer_Tick( ) to handle the Tick event that would get generated every second. We would
draw the hands and background of control in mytimer_Tick( ) event handler because we need to
redraw the control every second. This is the reason why we did not do the painting in the Paint
event handler.
Let us now see what we have done for drawing the control.

On occurrence of every tick we have drawn the clock UI on a bitmap and displayed the bitmap on
the control. To draw on the bitmap we first need to obtain the graphics context of the bitmap. We
have done this in the constructor of the Clock class. To collect the graphics context we have
added a reference g of type Graphics as a data member of the control. We have also added a
reference mybmp of type Bitmap to this class. Let us now take a look at the constructor.

public Clock( )
{
InitializeComponent( ) ;

Size sz = this.Size ;
mybmp = new Bitmap ( sz.Width, sz.Height ) ;
g = Graphics.FromImage ( mybmp ) ;
Color bkclr = this.BackColor ;
g.Clear ( bkclr ) ;

p = new Pen ( Color.Black ) ;


b = new SolidBrush ( Color.Purple ) ;
}

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

In the constructor, after a call to InitializeComponent( ), we have created a Bitmap object


having the same size as that of the control and collected its reference in mybmp. Then we
obtained a graphics context of the bitmap using the FromImage( ) shared method of the
Graphics class and collected the reference of the context in g. Next using the Clear( ) method
we have painted background of the bitmap with background of the control. We have then
initialized a black pen and purple brush. As you guessed, b and p are added as data members of
type SolidBrush and Pen respectively. Let us now see how the painting is done in the Tick event
handler.

Private Sub mytimer_Tick ( ByVal sender As Object, ByVal e As System.EventArgs ) Handles


mytimer.Tick
{
g.TranslateTransform ( 60, 60 ) ;
for ( int i = 0 ; i<=12; i++ )
{
g.FillRectangle ( b, -2, -45, 4, 5 ) ;
g.RotateTransform ( 30 ) ;
}
g.ResetTransform( ) ;

//seconds
p.Width = 1 ;
p.EndCap = LineCap.Flat ;
p.Color = Color.Red ;
g.TranslateTransform ( 60, 60 ) ;
g.RotateTransform ( s ) ;
g.DrawLine ( p, 0, 0, 0, -40 ) ;
g.ResetTransform( ) ;

//minutes
p.Width = 3 ;
p.EndCap = LineCap.Triangle ;
p.Color = Color.Blue ;
g.TranslateTransform ( 60, 60 ) ;
g.RotateTransform ( m ) ;
g.DrawLine ( p, 0, 0, 0, -30 ) ;
g.ResetTransform( ) ;

//hours
p.Width = 4 ;
g.TranslateTransform ( 60, 60 ) ;
g.RotateTransform ( h ) ;
g.DrawLine ( p, 0, 0, 0, -20 ) ;
g.ResetTransform( ) ;

s += 6 ;
if ( s == 360 )
s=0;
sec = sec + 1 ;

if ( sec == 60 )
{
sec = 0 ;
m += 6 ;

if ( m == 360 )

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

m=0;
min = min + 1 ;

h += 0.5f ;
if ( h == 360 )
h=0;
if ( min == 60 )
{
min = 0 ;
hr += 1 ;
}
}
Size sz = this.Size ;
Rectangle rect = new Rectangle ( 0, 0, sz.Width, sz.Height ) ;
Bitmap bm = mybmp.Clone ( rect, mybmp.PixelFormat ) ;
this.BackgroundImage = bm ;
Color bkclr = this.BackColor ;
g.Clear ( bkclr ) ;
}

We would understand this handler next time. In the next article we would also create a client of
this custom control.

Article – C# - Custom Controls - II

In the last article we had added the Tick event handler for the mytimer control. Let us see what
we have done in this handler. Consider the following code of the mytimer_Tick( ) handler.

g.TranslateTransform ( 60, 60 ) ;
for ( int i = 0 ; i<=12; i++ )
{
g.FillRectangle ( b, -2, -45, 4, 5 ) ;
g.RotateTransform ( 30 ) ;
}
g.ResetTransform( ) ;

Here we have drawn the rectangles that represent the hours. We have used the
TranslateTransform( ) method of the Graphics class to shift the origin to (60, 60). Using the
FillRectangle( ) method we drew 12 rectangles and rotated the graphics world every time by 30°.
After drawing the rectangles we used the ResetTransform( ) method to reset the transform world
to default settings.

Next we have drawn the seconds, minutes and hour hands. To display the current time we need
to calculate the angles of the hands first. For every second, the second hand should be rotated by
6° (360 / 60). For every minute, the minute hand should be rotated by 6° (360 / 60) again and for
every hour the hour hand should be rotated by 30° (360 / 12). Moreover, the hour hand should
also be rotated by 0.5° for every minute. This is because in every 60 minutes the hour hand
rotates by 30°, hence in every minute it would rotate by 0.5°. So while displaying the current time
we need to multiply the seconds, minutes and hours values by the angles and rotate the hands by
the multiplication results. These calculations need to be done before starting the timer and hence
we have written this logic in a method called start( ). We would see this method later.

To draw the hands we have used appropriate Color, Width and EndCap style of the Pen object.
Next we have translated the graphics world by 60, 60 and rotated it by s°. Then we have drawn

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

the hand using the DrawLine( ) method at appropriate co-ordinates. We have again used the
ResetTransform( ) method to reset the transform.

For drawing the minute hand we have used the same logic but rotated the hand by m° and made
the hand shorter, thicker and of blue color. We have also changed the EndCap style to
LineCap.Triangle. After resetting the transform we have drawn the hour hand rotated at an angle
of h° and made it more short and thick than the minute hand. We have used the same EndCap
style as of the minute hand for the hour hand.

With every second we have incremented s by 6°. As soon as the angle becomes 360°, we have
reset it to 0°. With every second we have also incremented the value of sec by 1. As soon as sec
becomes 60 (i.e. after 1 minute) we have done three things-reset sec to 0, incremented angle m
by 6° and incremented the value of min by 1. As soon as the angle m becomes 360°, we have
reset it to 0°.

With every minute we have incremented the value of angle h by 0.5°. Similarly, after completion
of 360°, we have reset the angle to 0°. After min becomes 60 (i.e. after 1 hour) we have reset the
value of min to 0 and incremented the value of hr.

All these would get drawn on the bitmap because the graphics context is of the bitmap. Now we
need to display the bitmap on the control. To do so we created another bitmap object bm using
the Clone( ) method. We created bm with the same size as that of the control and having the
same PixelFormat as of mybmp. PixelFormat represents number of bits associated with one
pixel of data. Next we have displayed the bitmap on the control by setting the BackGroundImage
property of the control to bm. Lastly, we have cleared mybmp with the BackColor of the control
making it ready for painting. Let us now see the start( ) method that was mentioned above.

public void start( )


{
now = DateTime.Now ;
sec = now.Second ;
min = now.Minute ;
hr = now.Hour ;
s = sec * 6 ;
m = min * 6 ;
h = ( ( hr % 12f ) * 30f ) + ( min * 0.5f ) ;
mytimer.Start( ) ;
}

The start( ) method would be called by the client when he wants to start the clock. We must start
the clock and place the second, minute and hour hands according to the present time. To do this
we have first collected the current system time in now of type DateTime. We have added now as
a data member of the class. To collect the seconds, minutes and hours values we have also
added 3 integers named sec, min and hr as data members of the Clock class. According to the
current time we have displayed the hands at different angles. We have used two integer variables
s and m to specify the angles for the second and minute hands respectively and we have used a
single variable h to specify the angle for the hour hand. We have also added s, m and h as data
members of the Clock class.

% (modulus operator) is used to avoid the AM/PM conflict. As soon as we start the timer using the
Start( ) method the Tick event is fired every second. And every second we have painted the
control with the new bitmap and changed the angles. To stop the timer we have added a method
called Halt( ) to the control shown below:

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

public void Halt( )


{
mytimer.Stop( ) ;
}

Using the Custom Control

To use the control we have created 'Windows Form' client called ClockClient. To be able to add
the control to our form, we need to add it first to the Toolbox. For this we need to right click on the
Toolbox and select Customize Toolbox. On doing so the Customize Toolbox window would get
opened. Here we need to select the .NET Framework Components Tab.

Our control would not get displayed in the list of existing controls; we need to browse for its dll.
After selecting the dll we need to click the OK button. This would add our control to the Toolbox as
shown in the following figure.

To add the control to our form we need to drag it on the form. After adding it to the form, we have
changed its name to myclock and set its Locked property to True to lock its size. To start the
ticking, we have called the start( ) method of the control in the constructor of the form as shown
below:

public Form1( )
{
InitializeComponent( ) ;
myclock.start( ) ;
}

This starts the timer and the control starts displaying the time.

Article – C# - Adding Events To Custom Controls

We can also add properties and events to a custom control. In last two articles we saw how to
create and use a clock control. In this article we would add properties and an event to it.

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

The idea is to modify the clock control to an alarm clock control. We plan to add two properties—
AlarmTime and Message to the control. These properties can be set or retrieved
programmatically as well as through the Properties Window. The user can set the AlarmTime
property to some specific time and as soon as the specified time is reached a message gets
displayed. The user can specify the message to be displayed through the Message property. The
form data members-altime (of type DateTime) and almessage (of type string)-are controlled by
these properties. We have added an event called alarm that would be fired as soon as specified
AlarmTime is reached. The AlarmTime and Message properties are given below:

[ Category ( "User Defined" ) , Description ( "Controls the Alarm Time" ) ]


public DateTime AlarmTime
{
get
{
return altime ;
}
set
{
altime = value ;
}
}

[ Category ( "User Defined" ), Description ( "Controls the Alarm Message" ) ]


public string message
{
get
{
return almessage ;
}
set
{
almessage = value ;
}
}

Notice the two attributes that we applied to the properties. The Category attribute specifies the
category under which the property would get displayed in the Properties window. This would be
visible whenever we drag the control on the form and open the Properties window. The
Description attribute accepts a String that would get displayed in a small part of the window
present at the end of the Properties window. This string describes the property. The Properties
window of the control is shown in the following figure.

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

To add the event we have first added a delegate called NotifyAlarm to the control that accepts
two parameters-an object and a TimeEventArgs object.

public delegate void NotifyAlarm ( object sender, TimeEventArgs e ) ;

TimeEventArgs is a user-defined class. In this class we have added a data member named msg
of type String and a one-argument constructor accepting a string that would be stored in msg.
The class is shown below:

public class TimeEventArgs : EventArgs


{
public string msg ;
public TimeEventArgs ( string s )
{
msg = s ;
}
}

Next we added the event as data member of the class as shown below:

public event NotifyAlarm alarm ;

For the alarm to ring at the specified time, with every minute we must check whether the specified
alarm time is equal to the time displayed in our control. We have done the checking in the Tick
event handler. The modified Tick event handler is given below.

private void mytimer_Tick ( object sender, System.EventArgs e )


{
g.TranslateTransform ( 60, 60 ) ;
for ( int i = 0 ; i <= 12 ; i++ )
{
g.FillRectangle ( b, -2, -45, 4, 5 ) ;
g.RotateTransform ( 30 ) ;
}
g.ResetTransform( ) ;

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

//seconds
p.Width = 1 ;
p.EndCap = LineCap.Flat ;
p.Color = Color.Red ;
g.TranslateTransform ( 60, 60 ) ;
g.RotateTransform ( s ) ;
g.DrawLine ( p, 0, 0, 0, -40 ) ;
g.ResetTransform( ) ;

//minutes
p.Width = 3 ;
p.EndCap = LineCap.Triangle ;
p.Color = Color.Blue ;
g.TranslateTransform ( 60, 60 ) ;
g.RotateTransform ( m ) ;
g.DrawLine ( p, 0, 0, 0, -30 ) ;
g.ResetTransform( ) ;

//hours
p.Width = 4 ;
g.TranslateTransform ( 60, 60 ) ;
g.RotateTransform ( h ) ;
g.DrawLine ( p, 0, 0, 0, -20 ) ;
g.ResetTransform( ) ;

s += 6 ;
if (s == 360 )
s=0;
sec = sec + 1 ;

if (sec == 60)
{
sec = 0 ;
m += 6 ;

if (m == 360)
m=0;
min = min + 1 ;

if ( altime.Hour == hr && altime.Minute == min )


{
TimeEventArgs t = new TimeEventArgs ( almessage ) ;
alarm ( this, t ) ;
}

h += 0.5f ;
if ( h == 360 )
h=0;
if ( min == 60 )
{
min = 0 ;
hr += 1 ;
}
}

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

Size sz = this.Size ;
Rectangle rect = new Rectangle ( 0, 0, sz.Width, sz.Height ) ;
Bitmap bm = mybmp.Clone ( rect, mybmp.PixelFormat ) ;
this.BackgroundImage = bm ;
Color bkclr = this.BackColor ;
g.Clear ( bkclr ) ;
}

As soon as altime.Hour becomes equal to hr and altime.Minute becomes equal to min, we


created an object referred to by t of the TimeEventArgs class by passing almessage to it. Next
we raised the event using RaiseEvent and passed the reference of the control to it. We have also
added an attribute called DefaultEvent to the Clock class as shown below:

[ DefaultProperty ( "Message" ) , DefaultEvent ( "alarm" ) ]

As a result, whenever we drag our control on the form and double click on the control in the
Client's Windows Designer, of all the event handlers available the alarm event handler would get
added in the code.

Now let us see what we need to do to handle the event in the client. As soon as we double click
on the control after dragging it on the form the myclock_alarm( ) event handler gets added to the
form class. To display the alarm message we have simply popped a messagebox displaying the
alarm message. The handler is shown below.

private void myclock_alarm ( object sender, ClockCtrl.TimeEventArgs e )


{
MessageBox.Show ( e.msg ) ;
}

In the client on selecting AlarmTime in the Properties window we would get a calendar control.
We have set the values for AlarmTime and Message properties. When the clock would reach the
alarm time it would display the message as shown in the following figure.

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

Article – C# - COM Interoperability

COM components and .NET components are not compatible since they have different internal
architectures. However, there are tools available in the .NET SDK for generating COM proxies for
.NET components and .NET proxies for COM components. Using these proxies we can use COM
components in .NET projects and .NET components in non-.NET projects. Let's now discuss
these two situations.

Using COM Components in .NET Application

Here we would be using a COM component called 'AtlServer' that exposes an interface 'IMath'
containing two methods Add( ) and Sub( ). The component is stored in the file 'AtlServer.dll'.
Note that 'AtlServer.dll' must be registered in you machine. If it is not registered simply build the
'AtlServer' project so that the .NET will make the registration or use the 'regsvr32' utility.
We now plan to use this COM component in a .NET project. For this we have created a console
application and named it as 'AtlClient'. To use the COM component in our project we would have
to create a wrapper class for the COM component. A wrapper class surrounds a class that follows
a different architecture than .NET. This class provides a familiar interface to the .NET architecture.
We can create a wrapper class in two ways. First is to use the 'TlbImp.exe' tool provided in the
.NET SDK. TlbImp stands for 'Type Library Importer'. This EXE is invoked from the command
prompt as shown below:

c:\com_interop\AtlServer\Debug>tlbimp AtlServer.dll /out:NetAtlServer.dll

The /out option will store the newly created wrapper class in the 'NetAtlServer.dll' file. We would
have to copy 'NetAtlServer.dll' in the 'Debug' sub-directory of our .NET project.
The second way to create a wrapper class is to right click in the 'Solution Explorer' and choose
the 'Add Reference' option. Next we must choose the 'COM' tab. On doing so the window shown
below would appear.

To select the file click on the 'Browse' button, locate the file and select it. On clicking 'OK', a file
with the same name i.e. 'AtlServer.dll' would get created in the 'Debug' sub-directory of our
project and would contain the wrapper class called CMath. We can now call the methods of the
class as shown in the following code.

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

using System ;
using AtlServer ;
namespace AtlClient
{
class Class1
{
[ STAThread ]
static void Main ( string [ ] args )
{
CMathClass m = new CMathClass( ) ;
Console.WriteLine ( m.Add ( 10, 20 ) ) ;
Console.WriteLine ( m.Sub ( 20, 30 ) ) ;
}
}
}

Using .NET Components In Non-.NET Projects

To use a .NET component in a non-.NET project we have to use a tool called RegAsm, standing
for 'Registry Assembly'. This tool registers a .NET component into the system registry so that
standard Windows client can bind to the classes in the component.
The .NET component that we have created is just a simple class library called 'NetServer' that
contains the following code.

using System ;

namespace NetServer
{
public interface IMath
{
int Add ( int n1, int n2 ) ;
int Sub ( int n1, int n2 ) ;
}
public class CMath : IMath
{
public int Add ( int n1, int n2 )
{
return n1 + n2 ;
}

public int Sub ( int n1, int n2 )


{
return n1 - n2 ;
}
}
}

Here we have declared an interface called IMath and implemented this interface in the CMath
class. On building this project we get the 'NetServer.dll' file.
Now we need to register this component in the registry using the RegAsm tool as well as create
a corresponding COM type library file ( .tlb file). To create a COM type library file we need to use
the TlbExp tool. TlbExp stands for 'Type Library Exporter'. This tool interrogates the assembly's
manifest and outputs a corresponding COM type library. We have used both the tools as shown in
the following figure.

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

Now let us create a non-.NET project that would use this component. We have created our
project in VC++. To create this project, click on 'Visual C++ Projects' and select 'Win32 Project'.
Name the project as NetClient. On clicking 'OK' the window shown in the following figure would
appear. In the 'Application Settings' tab select the 'Console Application' option and click on the
'Finish' button.

We need to add the following code to our project.

# include "stdafx.h"
# include "iostream.h"
# import "C:\dotnet\c#\com-interop\NetServer\bin\Debug\NetServer.tlb"

using namespace NetServer ;

int _tmain ( int argc, _TCHAR* argv [ ] )


{
CoInitialize ( NULL ) ;
IMathPtr p ;
HRESULT hr = p.CreateInstance ( "NetServer.Math" ) ;
if ( FAILED ( hr ) )
{
cout << "CreateInstance Failed" << endl ;
return 0 ;

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

}
cout << p -> Add ( 10, 20 ) << endl ;
cout << p -> Sub ( 20, 10 ) << endl ;

return 0 ;
}

Here we have imported the Type Library using the #import directive. Then we have created a
pointer called IMathPtr. Using the CreateInstance( ) method we have stored the component
object's address in the interface pointer and then used it to call the Add( ) and Sub( ) methods.
On executing this program we would get the output on the console.

Article – C# - Storing Images

"How to store an image in a database and how to read it back?" is a frequently asked question.
This article gives the answer. In this article we would see how ADO.NET is used to store BLOBs
(images) in a database and read them back. We would create two applications. One that would
store information of books into a database and another that would retrieve this information and
display it. The information consists of the book name, the author name and an image
representing the cover pages of the book. For this we have maintained a database called ‘books’,
having a table called ‘bookinfo’ and having entries such as bookname (char), author (char) and
logo (image). Logo represents the cover page of the book.
Create a WinForm application and design the form as shown in following figure.

The controls and their names are shown in the following table

Book Name Textbox book


Author Textbox author
Image Textbox file
Browse button browse
Insert Button insert

Using the ‘Browse’ button the user would select the image file of the book cover. On clicking the
‘Insert’ button the book information would get stored in the database.
First of all to add entries in the table we need to open the connection to the data source. For this

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

we must declare a connection string and a connection object. We have done it in the Form1
class as shown below:

string constr ;
SqlConnection con ;

Declare the System.Data.SqlClient namespace at the beginning of the program to make


available the SqlConnection class. In the constructor of the Form1 class add the following
statement to initialize the connection string and connection object and also to open the
connection.

constr = "server=kicitsqlserver;database=books;uid=sa;pwd=kicit" ;
con = new SqlConnection ( constr ) ;
con.Open( ) ;

Once the connection is established, user is free to input the book information. The user would
enter the book name and author name and then select the image file by clicking the ‘Browse’
button. So, next we would add the Click event handler for the ‘Browse' button. The handler is
given below:

private void browse_Click ( object sender, EventArgs e )


{
OpenFileDialog ofd = new OpenFileDialog( ) ;
ofd.Filter = "Image files |*.jpg" ;
if ( ofd.ShowDialog( ) == DialogResult.OK )
file.Text = ofd.FileName ;
}

Here, we have first created an object of the OpenFileDialog class and collected its reference in
ofd. Next we have used the Filter property to specify the file type we wish to browse. Here we
have specified that we wish to browse for all the jpg files. We have then displayed the Open File
Dialog by calling the ShowDialog( ) method and checked whether the user clicked on the OK
button of this dialog or not. If he does then we have initialized the Text property of the file text box
with the file name returned by the FileName property.
After filling in all the information, we need to click on the ‘Insert’ button. As soon as we click on
this button the insert_Click( ) handler would get called. This handler is given below:

private void insert_Click ( object sender, EventArgs e )


{
FileStream f = new FileStream ( file.Text, FileMode.Open ) ;
byte[ ] buff = new byte [ f.Length ] ;
f.Read ( buff, 0, ( int ) f.Length ) ;
string cmdstr = "Insert into bookinfo values ( @b, @a, @l )" ;
SqlCommand com = new SqlCommand ( cmdstr, con ) ;
com.Parameters.Add ( "@b", book.Text ) ;
com.Parameters.Add ( "@a", author.Text ) ;
com.Parameters.Add ( "@l", buff ) ;
com.ExecuteNonQuery( ) ;
con.Close( ) ;
}

Here we have first created a FileStream object by passing the file name and FileMode to it. We
have read the file name from the file textbox. Next we have created an array of bytes called buff
having length equal to the length of the data that is in the file stream. Then we have read the file
into the byte array using the Read( ) method. Next, we have created a command string that would

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

insert the information into the database. We have used the parameterized command to add the
values to the fields in the data source. So, in the command string we have specified the
parameters as @b, @a and @l for the book name, author name and cover page logo
respectively. The advantage of using parameterized commands is that we can change the values
of some or all the fields again and again without having to create the command string again and
again. The Parameters property of the SqlCommand class returns the collection of parameters
in the form of a reference to SqlParameterCollection class object. We have added the
parameter to this collection by calling the Add( ) method of the SqlParameterCollection class.
Next we have called the ExecuteNonQuery( ) method that would actually fill the database. Lastly
we have closed the connection with the Close( ) method.
To be able to use the FileStream class we need to use the System.IO namespace in our
application.
Let us now create an application for accessing and retrieving BLOBs stored in the bookinfo table.
Create a Winform application. Add two Labels and one PictureBox to display the book name,
author name and the cover page respectively. The UI is shown in following figure

Change the names of controls as shown in the following table.

Book Name Label bookl


Author Label authorl
Picture Box img
Next Button next

On clicking on the ‘Next’ button the information of the next book stored in the database would get
displayed.
Add the following data members to the Form1 class.

string constr ;
SqlConnection con ;
string cmdstr ;
SqlCommand com ;
SqlDataReader r ;

Initialize them in constructor after the call to the InitializeComponent( ) method as shown below:

constr = "server=kicitsqlserver;database=books;uid=sa;pwd = kicit" ;


con = new SqlConnection ( constr ) ;

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

cmdstr = "Select * from bookinfo" ;


com = new SqlCommand ( cmdstr, con ) ;

Also add the code to open the connection and display the details of first book as shown below:

con.Open( ) ;
r = con.ExecuteReader( ) ;
if ( r.Read( ) )
{
bookl.Text = r [ 0 ].ToString( ) ;
authorl.Text = r [ 1 ].ToString( ) ;
byte[ ] b = ( byte[ ] ) r [ 2 ] ;
MemoryStream st = new MemoryStream( ) ;
st.Write ( b, 0, b.Length ) ;
Image i = Image.FromStream ( st ) ;
img.Image = i ;
}

After opening connection to database we have retrieved the reference of the SqlDataReader
object in r by making a call to the ExecuteReader( ) method. Then we have checked whether the
Read( ) method returns a true or false depending on the existence of a row. If it returns a true, we
have extracted the book name and the author name and displayed them in the corresponding
textboxes. Now we need to retrieve the BLOB. We have collected the BLOB in a byte array b.
Realize that we cannot directly display the contents of b in the PictureBox because it is in not in
a bitmap format. Hence we must first convert the byte array into a bitmap. To do so we have
created an object of the MemoryStream class and collected its reference in st. MemoryStream
class is used when the backing store is memory. Recall how we had created a FileStream object
in the previous example where we had read from a file. Next, using the Write( ) method of the
MemoryStream class we have written the contents of the byte array into the stream. Then we
have created a bitmap by passing the reference of the MemoryStream object to the constructor
of the Image class. Next we have displayed the image on the PictureBox.
As soon as the user clicks the ‘Next’ button the next_Click( ) handler gets called. This handler is
shown below:

private void next_Click ( object sender, EventArgs e )


{
if ( r.Read( ) )
{
bookl.Text = r [ 0 ].ToString( ) ;
authorl.Text = r [ 1 ] .ToString( ) ;
byte[ ] b = ( byte[ ] ) r [ 2 ] ;
MemoryStream st = new MemoryStream( ) ;
st.Write ( b, 0, b.Length ) ;
Image i = Image.FromStream ( st ) ;
img.Image = i ;
}
}

In this handler we have used the same logic. Every time the user would click this button
information of the next book stored in the database would get displayed.

Article – C# - Miscellaneous .NET Features...

Language Interoperability

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

Language Interoperability is a key feature of the .NET environment. Language Interoperability


means that we can use an assembly written in any .NET compliant language in a program written
in another .NET compliant language. This is all possible because all .NET compliant languages
compile into IL (Intermediate Language). Language Interoperability supports code-reuse, which is
the most sought after feature in today's programming world.

To illustrate language Interoperability we would created an assembly in Managed C++ and then
see how to use it through C#. Let's first take a look at the assembly written in Managed C++. To
create this select "Visual C++ Projects" and choose the "Managed C++ Class Library" template.
Name the class library as 'McppServer'. The code to be written in it is given below.

#include "stdafx.h"
namespace McppServer
{
public __gc class fact
{
public:
int factorial ( int n )
{
int j = n ;
for ( int i = 1 ; i < n ; i++ )
j=j*i;
return j ;
}
};
}

In the fact class we have written a method called factorial( ) that accepts a number and returns
the factorial value of that number. The __gc stands for garbage collected. It specifies that the
underlying type would be treated as a managed type. It is necessary to mention this because in
Managed C++ by default a type is unmanaged. On building this program an assembly called
"McppServer.dll' would get created.

Now let's look at the C# program. We have created a console application called 'CSharpClient'.
To be able to use 'McppServer.dll' in this project, we have to add its reference through the
'Solution Explorer' window.

using System ;
using McppServer ;

namespace CSharpClient
{
class Class1
{
[ STAThread ]
static void Main ( string [ ] args )
{
fact f = new fact( ) ;
Console.WriteLine ( f.factorial ( 5 ) ) ;
}
}
}

We have added the statement using McppServer at the beginning of the program. This gives us
access to the classes defined in this namespace. Here we have created an object of the fact

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

class and used it to call the methods of this class. On executing this program we get the output as
120.

Using Pointers in .NET

Pointers can be used in C# only in the blocks of code that we have specifically marked for pointer
use. The keyword to do so is unsafe. 'Unsafe' because there are potential risks associated with
pointers such as memory leaks, overwriting of important information, stack overflow, etc. Code
that uses pointers is difficult to debug and will fail the memory type safety checks imposed by the
Common Language Runtime. We can mark individual methods, classes, structures, blocks of
code or even local variables as unsafe. For example we can write:

unsafe float myfunction( )


{
// can use pointers
}

unsafe class myclass


{
unsafe int *x ;
}

unsafe
{
// unsafe block
}

Declaring pointers is different in C# than in C/C++. For example, if we want to declare two
pointers to ints, we write:

int *x, y ;

in C# as, against

int *x, *y ;

in C/C++.

Once we've declared the pointers, we can use them as normal pointer variables using the
'address of' (&) and the 'value at address' (*) operators.

For the most part, C# relies on references of instances of classes, and the language has been
designed in such a way that pointers are not required as often as they are in C/C++.

The checked and unchecked operators

The checked and unchecked operators can be used to control overflow checking for arithmetic
operations and conversions of integer types. If a statement is marked as checked, the CLR
enforces overflow checking and throws an exception if an overflow occurs. On the other hand if it
is marked unchecked, and overflow occurs, the overflowing bits (higher) are discarded and
exception is not thrown. For example, consider the following snippet:

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

byte b = 255 ;
checked
{
b++ ;
}

Here an exception would be thrown. But the following would not throw an exception:

byte b = 255 ;
unchecked
{
b++ ;
}

Here the overflowing bits would be lost and b would contain 0. By default, all the operations are
unchecked.

Article – C# - Serialization

Serialization is the process of writing objects on a persistent storage media such as a file on the
disk. Complementary to serialization is Deserialization using which we can restore objects. Let
us see an example where we have used serialization and deserialization to store and retrieve
objects of a class to/from a file.

Let us discuss the application first. We would create a WindowsApplication and add two menus
‘File’ and ‘Generate’ to the form. The ‘File’ menu would have two menu items. ‘Open’ and ‘Save’.
On clicking ‘Generate’ ten shapes would get generated randomly. We can save them in a file. To
save the shapes drawn we would use serialization. While saving the shapes, we should not save
the images of the shapes. Instead we should save the relevant information of the shapes using
which we should be able to regenerate them again when the file is loaded. This means that we
must write the object containing the information about the shape (coordinates of the shape and
the color) in the file while saving it and load it back while opening the file. This is done using
serialization and deserialization.

To be able to represent the shapes we would create three classes-line, rectangle and ellipse. To
generate the shapes we would call the draw( ) method of these classes. To be able to call the
draw( ) methods of the line, rectangle and ellipse classes using the same call, we would use
virtual mechanism. We would declare a class called shapes having an abstract method draw( ).
The above mentioned three classes would be derived from the shapes class. These classes
would override the draw( ) method.

To save the objects on a disk we would create an ArrayList and store the objects of the shapes
class in it in the order in which they are drawn. We can then write this array list to the disk.

The names of menu items are given in the following table.

Menu Name
Open open
Save save
Generate generate

Also add the following data members to the Form1 class.

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

ArrayList s = new ArrayList( ) ;


BinaryFormatter b = new BinaryFormatter( ) ;

We would now write the shapes class and derive three classes—line, rectangle and ellipse
from it. Here are the classes.

[ Serializable( ) ]
abstract class shapes
{
protected int r, g, b ;
public shapes( )
{
Random rd = new Random( ) ;
r = rd.Next ( 256 ) ;
g = rd.Next ( 256 ) ;
b = rd.Next ( 256 ) ;
Thread.Sleep ( 5 ) ;
}
abstract public void draw ( Graphics g ) ;
}

In this class we have declared three data members r, g, and b representing red, green and blue
components to store the color of the shapes. We have also declared an abstract method in this
class called draw( ). The classes derived from shapes class would have to implement the
draw( ) method to be able to create their objects.

In the constructor of the shapes class we have generated random numbers using an object of the
Random class. The Next( ) method of the Random class generates a positive random number
less than the number passed to it. Using this method we have initialized the r, g and b data
members.

The statement [Serializable( )] written before the class declaration is known as an attribute.
Attributes are attached to classes, methods, data member or any such entities. Any class that is
attached with this attribute indicates that all the data members of the class can be serialized i.e.
can be written in a file, except for the data members that are marked with <NonSerialized( )>
attribute. We have not marked any data members as <NonSerialized( )> hence all data
members of the class would get written in a file.

The derived classes are given below:

[ Serializable( ) ]
class line : shapes
{
int x1, y1, x2, y2 ;
public line ( int i, int j, int k, int l )
{
x1 = i ;
y1 = j ;
x2 = k ;
y2 = l ;
}
override public void draw ( Graphics gr )
{

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

Color c = Color.FromArgb ( r, g, b ) ;
Pen p = new Pen ( c, 4 ) ;
gr.DrawLine ( p, x1, y1, x2, y2 ) ;
}
}

[ Serializable( ) ]
class rectangle : shapes
{
int x1, y1, x2, y2 ;
public rectangle ( int i, int j, int k, int l )
{
x1 = i ;
y1 = j ;
x2 = k ;
y2 = l ;
}
override public void draw ( Graphics gr )
{
Color c = Color.FromArgb ( r, g, b ) ;
Pen p = new Pen ( c, 4 ) ;
gr.DrawRectangle ( p, x1, y1, x2, y2 ) ;
}
}

[ Serializable( ) ]
class ellipse : shapes
{
int x1, y1, x2, y2 ;
public ellipse ( int i, int j, int k, int l )
{
x1 = i ;
y1 = j ;
x2 = k ;
y2 = l ;
}
override public void draw ( Graphics gr )
{
Color c = Color.FromArgb ( r, g, b ) ;
Pen p = new Pen ( c, 4 ) ;
gr.DrawEllipse ( p, x1, y1, x2, y2 ) ;
}
}

In these classes we have declared four integers that are used to store the coordinates of the
shapes. It also consists of a constructor used to initialize these data members. We have
implemented the draw( ) method in these classes that contains the logic to draw the line. We
have attached the [Serializable( ) ] attribute to all the classes also indicating that objects of this
class can be serialized.

Add the Click event handlers for all the menu items. We would first see the ‘Generate’ menu
handler. It is given below:

private void generate_Click ( object sender, EventArgs e )


{

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

Graphics g = CreateGraphics( ) ;
g.Clear ( BackColor ) ;

Size sz = ClientSize ;
Random rd = new Random( ) ;
int i ;
int shapeno, x1, y1, x2, y2 ;
for ( i = 0 ; i <= 9 ; i++ )
{
shapeno = rd.Next ( 3 ) ;
x1 = rd.Next ( sz.Width ) ;
y1 = rd.Next ( sz.Height ) ;
x2 = rd.Next ( sz.Height - y1 ) ;
y2 = rd.Next ( sz.Width - x1 ) ;
switch ( shapeno )
{
case 0 :
s.Add ( new line ( x1, y1, x2, y2 ) ) ;
break ;
case 1 :
s.Add ( new rectangle ( x1, y1, x2, y2 ) ) ;
break ;
case 2 :
s.Add ( new ellipse ( x1, y1, x2, y2 ) ) ;
break ;
}
}
Invalidate( ) ;
}

When we click the ‘Generate’ menu item this handler gets called. In this handler an object of the
Random class is created. We have used the Next( ) method of this class to not only decide
which shape should be generated but also the coordinates of this shape. The coordinates of the
shapes to be generated should not be greater than the coordinates of the form. Hence the
coordinates are generated using the size of the form, which is available in the ClientSize property
of the form. Using these coordinates we have created ten random objects of rectangle, ellipse or
line class. While creating these objects the constructors of the respective classes get called.
Since all these classes are derived from the shapes class, firstly the base class constructor gets
called. This constructor selects a random color. The references of objects of line, rectangle and
ellipse are stored in the ArrayList using the Add( ) method. Lastly, we have called the
Invalidate( ) method, which results in the Form1_Paint( ) event handler getting called. This
handler id given below.

private void Form1_Paint ( object sender, PaintEventArgs e )


{
Graphics g = e.Graphics ;
foreach ( shapes ss in s )
ss.draw ( g ) ;
}

As the line, rectangle and ellipse classes are derived from shapes, it is perfectly legitimate for a
reference variable of shapes such as ss to hold a reference of the derived class. Using this
reference we have called the draw( ) method. To this method we have also passed an object of
the Graphics class. Depending upon which reference is present in ss, the draw( ) method of the
appropriate class gets called and the corresponding shape gets drawn. This was the reason

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

behind deriving all the three classes from a common class shapes.

The handler for ‘Save’ menu item is given below.

private void save_Click ( object sender, EventArgs e )


{
SaveFileDialog sd = new SaveFileDialog( ) ;
sd.Filter = "dat files | *.dat" ;
if ( sd.ShowDialog( ) == DialogResult.OK )
{
FileInfo f = new FileInfo ( sd.FileName ) ;
Stream st ;
st = f.Open ( FileMode.Create, FileAccess.ReadWrite ) ;
foreach ( shapes ss in s )
b.Serialize ( st, ss ) ;
st.Close( ) ;
}
}

Here, we have created an object of the SaveFileDialog class and used a '*.dat' filter for it. When
we type in a file name and click OK, a FileInfo object gets created with the selected filename.
The Open( ) method returns a Stream object associated with the file. We have collected it in a
Stream reference. Then we have used a BinaryFormatter object to serialize the objects. This
binary formatter is added as a data member of the form class. The BinaryFormatter serializes
and deserializes an object, in binary format. To be able to use this class we need to use the
System.Runtime.Serialization.Formatters.Binary namespace in our program. The Serialize( )
method of this class serializes the object to the given stream. After serializing all the elements of
the array, we have closed the stream using the Close( ) method.

Lastly, here is the handler for ‘Open’ menu item.

private void open_Click ( object sender, EventArgs e )


{
OpenFileDialog od = new OpenFileDialog( ) ;
od.Filter = "dat files | *.dat" ;
if ( od.ShowDialog( ) == DialogResult.OK )
{
s.Clear( ) ;
Graphics g = CreateGraphics( ) ;
g.Clear ( BackColor ) ;

FileInfo f = new FileInfo ( od.FileName ) ;


Stream st = f.Open ( FileMode.Open ) ;

while ( st.Position != st.Length )


s.Add ( b.Deserialize ( st ) ) ;
st.Close( ) ;
Invalidate( ) ;
}
}

Here we have first created an object of the OpenFileDialog class. This class represents the
common ‘Open File’ dialog. Next, we have set the Filter property of this class to .dat files. This
means that this dialog will display only the .dat files. The ShowDialog( ) method displays the
open file dialog. If we select the ‘OK’ button, then this method returns the DialogResult.Ok

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

member of the DialogResult enumeration. If the user selects a file and clicks on the ‘OK’ button,
we have firstly cleared the shapes, if any, drawn in the client area. The statement s.Clear( )
clears the array list in which shapes objects are stored.

Next, we have created a FileInfo object and collected the corresponding Stream object of the
specified file. Next we have used a while loop to deserialize the objects until the end of stream is
reached. The Deserialize( ) method deserializes the specified stream into an object. We have
collected these objects into our array by using the Add( ) method, closed the stream and called
Invalidate( ) function for painting these shapes.

Add the following declarations at the beginning of the program.

using System.Threading ;
using System.Runtime.Serialization ;
using System.Runtime.Serialization.Formatters.Binary ;
using System.IO ;

Execute the program and click the ‘Generate’ menu item. You would see ten shapes in different
colors. Try saving and opening the shapes.

Article – C# - Visual Inheritance

In Visual Studio 6.0, to display a dialog box, we derive a class from a pre-defined MFC class. The
event handlers and variables associated with controls get added to this user-defined class. All the
information about controls get stored in a separate '.rc' file. The compiler creates and displays
controls using information stored in the '.rc' file. Visual Studio 6.0 IDE provides facilities for adding
controls, variables for controls and handlers. So far so good. Now, consider a situation where an
extensive user interface on a dialog comprising of several controls exists and we want to reuse
this user interface in other application. What we would try is to inherit the dialog class creating the
user interface to create a new class. Major problem with this is that although we get access to the
base dialog class members, we don't get controls placed on the new dialog. This is because IDE
of Visual Studio 6.0 has no means to access the '.rc' file and render the controls according to the
information stored in it. So, our next step would be to copy all the controls from existing dialog
template and to paste them on the new dialog. Now we get the controls and the variables and
event handlers. But the problem here is that the code that associates controls with their variables
and handlers remains missing. So, reusing an existing user interface is far more different and
difficult than reusing an existing class.

Through 'Inheritance' we create a new class by using an existing class. Through 'Visual
Inheritance' we create a new form by using an existing form. When we inherit a form from an
existing form we also inherit controls, their properties, events and methods. So, the user interface
that is already created can be reused in a new application thereby reducing the repetitive
designing of controls. This makes Visual Inheritance a powerful weapon in this era of Rapid
Application Development. We can use visual inheritance in cases where we need to use the
same set of controls again and again.

Visual Studio.NET has incorporated visual inheritance as a part of .NET framework. Visual
inheritance is so called because it gives the visual expression of the inherited control objects.
Using Visual inheritance is a two-step process:

1. Creating Base Form


2. Creating Derived Form

These steps are explained below.

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

Creating Base Form

Carry out the following steps to create a Base Form.

(a) Create a Windows Application named 'baseform'.

(b) Add a button having label as "Click" and Name as b. Also add a text box having Name as t. By
default, these variables get
added as private data members. Change the access modifiers to public through the Modifiers
property. If we change the
Modifiers property of a control to protected or public we would be able to change its
properties in the derived form. The controls
marked as private in the base form will be visible on derived form but will not be accessible
through its Name. This seems
relevant because in OOP inheritance also only protected and public members of a base class
are visible to its derived classes.
In any case, we would not be able to delete the derived controls from the form.

(c) Add the Click event handler for the button and add following statement in it.

MessageBox.Show ( t.Text ) ;

(d) Now since our form stands ready we can build it into a class library so that we can export the
form. Note that we cannot import
a form from an exe file. To build the project in a class library, right click the solution name in
Solution Explorer and select
Properties. The 'baseform Property Pages' would get displayed. Select the Output Type as
Class Library as shown in the
following figure.

Now build the project to create 'baseform.dll'. This assembly contains the baseform.Form1 class
that we can inherit.

Creating Derived Form

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

(a) Create another Windows Application named 'derivedform'.

(b) Right click the solution name in Solution Explorer and select 'Add | Add Inherited Form' menu
option. The 'Add New Item' dialog
box gets displayed.

(c) Select the 'Inherited Form' from the 'Templates' list and provide a name of your choice in the
'Name' text box. We have kept the
default name 'Form2.cs'. This is shown in the following figure.

(d) The 'Inheritance Picker' dialog would get displayed. This dialog allows us to select an
assembly that contains the form we want
to inherit. For this, click the 'Browse' button. A dialog would appear from where we can select
the 'baseform.dll' file and click the
'Open' button.

(e) Clicking the 'Open' button dismisses the dialog and displays the forms exported by the
assembly (an assembly can export any
number of forms) in 'Specify the component to inherit from' list control.

(f) Select the form name from the 'Specify the component to inherit from' list control and click the
'OK' button. As soon as we click
the 'OK' button, a new form derived from the 'baseform' gets displayed in the design editor. The
file 'Form2.cs' also gets
displayed in the Solution Explorer as shown in the following figure.

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

The figure also displays reference of 'baseform.dll' being added in the 'References' tree in the
Solution Explorer. The derived form displays the derived controls being added to the base form.
These controls are accompanied by a small icon at the top left corner to distinguish between the
derived controls and the new controls.
(g) Open the 'Form1.cs' file. Change form name in Application.Run( ) method to Form2 as
shown below.

Application.Run ( new Form2( ) ) ;

This ensures that when we would execute the application, the new form, i.e. Form2, would get
displayed. If we enter the text in the textbox and click the button the text would get displayed in a
message box.

Let us now see how the whole thing works. To begin with the statement Application.Run ( new
Form2( ) ) gets executed. Here we are creating an object of the Form2 class which is derived
from the baseform.Form1 class. When we create an object of derived class, base class's
constructor gets called. So, in our case constructor of the baseform.Form1 class would get
called. This class is accessible to us since a reference to the 'baseform.dll' assembly is already
being added to our project. The compiler adds a call to the InitializeComponent( ) method in the
constructor of every form class. The InitializeComponent( ) method contains the code for
creating and customizing the controls. Once this method gets executed and controls get created,
the control returns to the constructor of the Form2 class. This constructor again calls the
InitializeComponent( ) method. This time the InitializeComponent( ) method of the Form2
class gets called. This is the reason why derived form contains the derived controls (initialized by
InitializeComponent( ) method of the baseform.Form1 class) and the new controls (initialized
by InitializeComponent( ) method of the Form2 class).

We have already added the Click event handler for the 'Click' button. We can override this
handler in the Form2 class and add our code in it. Now if we click the button, firstly, event handler
of the base class gets executed and then the overridden handler gets executed. This is because,
the InitializeComponent( ) method of the baseform.Form1 class gets executed first, wherein,
an address of the Click event handler defined in the baseform.Form1 class gets stored in the
Click delegate. Next the InitializeComponent( ) method of the Form2 class gets executed. In it,
the address of the Click event handler defined in the Form2 class gets added to the Click
delegate.

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

Article – C# - Getting Management Information using WMI

As the enterprise systems, applications, and networks became larger and more complex, the
challenge in front of the managers to manage them also increased. In order to solve these
problems, Microsoft developed WMI, a scalable management infrastructure and shipped it with
Windows 2000. When we implement WMI on Windows platforms, the technology enables the
Common Information Model (CIM) designed by the Distributed Management Task Force (DMTF)
to represent systems, applications, networks, and other managed components. The CIM
Specification describes the modeling language, naming, and mapping techniques used to collect
and transfer information from data source and other management models. The CIM schema
provides the actual model descriptions and information framework. It defines a set of classes with
properties and associations, making it possible to organize information about the managed
environment.

The key features of WMI are discussed below:

(a) Uniform Scripting API: WMI uses the CIM object model to create the managed objects. So,
scripts only need to use a single
API of WMI to access information for numerous disparate sources.

(b) Remote Accessibility: Objects managed within WMI can be used by the applications and
scripts running on the local machine
as well as on the remote machine.

(c) Discovery: Applications and scripts are able to discover what information is available about a
system by enumerating the
classes that are available.

(d) WMI Queries: WMI allows SQL queries to be executed on its objects.

(e) Powerful Event Publication: Events can be requested for any change in the managed
objects in the system, regardless of
whether they support an internal event capability.

If you have used WMI in the past, you might be daunted by its complexities as it exposes COM
interfaces. You would be happier to know that .NET provided easy to use namespaces and
classes that encapsulate the WMI API. We would start with a simple program that displays
information of the drive entered by the user.

Create a Windows Forms application and design the form as shown below:

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

We have added few labels and read only text boxes to the form. Give suitable Names to the text
boxes. The user would enter the drive name, for example, C: in the text box names as 'Enter
Drive Name'. To get the information of the specified drive the user would click the 'GetInfo' button.
Add the Click event handler for the button. This handler is given below:

private void binfo_Click ( object sender, System.EventArgs e )


{
ManagementClass mc = new ManagementClass
( "Win32_LogicalDisk" ) ;
ManagementObjectCollection disks = mc.GetInstances( ) ;

foreach ( ManagementObject disk in disks )


{
if ( disk [ "Name" ].ToString( ) == tdrive.Text )
{
text1.Text = disk [ "DeviceID" ].ToString( ) ;
text2.Text = disk [ "DriveType" ].ToString( ) ;
text3.Text = disk [ "FileSystem" ].ToString( ) ;
text4.Text = disk [ "FreeSpace" ].ToString( ) ;
text5.Text = disk [ "MediaType" ].ToString( ) ;
text6.Text = disk [ "Size" ].ToString( ) ;
text7.Text = disk [ "VolumeName" ].ToString( ) ;
text8.Text = disk [ "VolumeSerialNumber" ].ToString( ) ;
}
}
}

Here, we have firstly declared a reference mc to the ManagementClass object. To the


constructor of this class we have passed the name of the management class

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

Win32_LogicalDisk. The Win32_LogicalDisk WMI class represents a data source that resolves
to an actual local storage device on a Windows system. The idea is to obtain the objects of the
logical disk class at run time and use its properties to obtain the management information. Then
we have used the GetInstances( ) method to retrieve all the instances of the logical disk class. It
returns the reference to the collection of the class instances. We have then applied the foreach
loop to enumerate all the instances. The object of the ManagementObject class represents a
management data object. Using the Name property of the logical disk class we have retrieved the
name of the drive. If this name matches the name of the drive entered by the user, then we have
obtained the information of the drive using various properties of the Win32_LogicalDisk class.
We have displayed this information in the text boxes.

Declare the System.Management namespace at the beginning of the program. Also add the
reference to 'System.Management.dll' through the Solution Explorer window.

Run the program. Enter the drive name as C: and click the 'GetInfo' button the drive information
would get displayed as shown in the following snap shot.

What we saw in this article is only a tip of the iceberg. In the coming few article we would study
the WMI architecture and use more WMI classes to explore the management information.

Article – C# - Viewing Processes Using WMI

Microsoft had invented Web-Based Enterprise Management (WBEM), to develop a standardized


technology for accessing management information. Management information includes details
about the state of system memory, inventories of currently installed client applications, and other
information about client status. WMI can handle many tasks, ranging from simple workstation
configuration to full-scale enterprise management across multiple platforms. WMI uses Common
Information Model (CIM) designed by the Distributed Management Task Force (DMTF) to
represent systems, applications, networks, and other managed components. CIM can model
anything in the managed environment regardless of data source location.

In addition to data modeling, WMI allows query-based information retrieval and event notification.

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

Let's first study the architecture of WMI. Following figure describes the three-layer model of WMI
comprising of providers, the CIM Object Manager (CIMOM), and consumers of WMI information
(applications).

The first tier in the WMI architecture is the provider. A provider is a mediator between the system
to be managed (for example, operating system, service, application, device driver, and so on) and
the CIM object manager. The job of a provider is to extract management information from the
underlying data source using whatever interfaces that software presents for management.

The management information and interfaces are then mapped by the provider into the object
classes that WMI presents to WMI consumers. Moving forward, new and updated managed
systems will use providers as a direct way to expose management APIs without significant
intermediate conversions.

Next is CIMOM, the CIM Object Manager has its own storage repository. It acts as a broker for
object requests. CIMOM and its repository are represented on the system by the system service
called WinMgmt. Providers plug into CIMOM via a published set of COM interfaces. CIMOM
keeps track of what classes are available and what provider is responsible for supplying
instances of those classes. When an application requests for management information to
CIMOM, it evaluates the request, identifies which provider has the information, and upon getting it
returns the data to the consumer.

Finally, there are consumers of WMI data. These are the applications requesting for the
management information. These consumers, as previously noted, only need to know about the
classes of the objects about which they wish to get information.

Thus an application or script can call one WMI API function and get a wealth of information about
the computer, operating system, applications, devices and even information available via other
management protocols like SNMP and DMI.

A WMI class exposes properties, methods, events and associations. An application can make use
of them for obtaining the management information. Properties supply descriptive information
about a particular object of a class. For example, the object of Win32_Process class has a
property called Caption that contains the name of the process. The WMI classes provide
methods, that an application can call using the object of that class. The WMI object can throw

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

events that are the notifications a consumer can request to receive for occurrences or failures in
the system.

We would now see a program that uses the Win32_Process WMI class for enumerating the
processes currently running on system.

Create a WinForm application. Place a list box and a button on the form. Name the button as
m_browse and list box as m_list. Add the Click event handler for the button and write code in it
as shown below.

ManagementClass mc = new ManagementClass (


@"root\cimv2:Win32_Process" ) ;
ManagementObjectCollection mobjects = mc.GetInstances( ) ;

foreach ( ManagementObject mo in mobjects )


m_list.Items.Add ( mo [ "Caption" ].ToString( ) ) ;

Here, firstly we have created a reference to the ManagementClass object passing to it the WMI
class name. 'root\cimv2' is the default namespace for System.Management API. Most of the
system instrumentation classes reside here.

We have retrieved the managed objects by calling the GetInstances( ) method of the
ManagementClass class. This method would return the instances of the Win32_Process class,
which is the class that represents a Windows process. The instances are returned in a collection,
each instance would represent one process.

We have then run a foreach loop to access the objects in the collection. We have obtained the
name of the process by using the Caption property of the Win32_Process class. Note that we
can access the property of this class because an object of ManagementObject class represents
the instance of the Win32_Process class.

Declare the System.Management namespace at the beginning of the program and add the
reference to the 'System.Management.dll' to the project. Now run the program and click the
'Browse' button. All the processes would get listed as shown in the following snap shot.

Article – C# - Tapping the Processes Using WMI - I

In the last article we saw how to list the processes currently running on the local machine. In this
article we would see a similar application that displays the processes currently running on the
machine but with additional functionality. We would display more information of each process and
also extend the program to view the processes running on a remote machine. The application
would also allow us to terminate the running process.

Create a WinForm application and place controls on it as shown below:

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

Change the names of controls as shown in the following table.

Control Name
ListView m_plist
Machine Name
m_mname
TextBox
Username TextBox m_uname
Password TextBox m_password
Refresh Button m_brefresh
Terminate Process
m_bterminate
Button

When the application is executed, it would display the list of processes and their information of
local machine. To view the processes of remote machine, the user should enter the machine
name, username and password and click the Refresh button. To terminate the process, the user
should select the process from list view control and click the ‘Terminate Process’ button.

Let us first add code to the constructor of the Form1 class after the call to
InitializeComponent( ) method to display processes of the current machine.

ManagementClass mc = new ManagementClass ( @"root\cimv2:Win32_Process" ) ;


ManagementObjectCollection mobjects = mc.GetInstances( ) ;

addprocesses ( mobjects ) ;

The object collection returned by the GetInstances( ) method is passed to a user-defined


function addprocesses( ). We have separated code to add the processes in a function, because
we need to execute the same code again when user clicks the ‘Refresh’ button. The
addprocesses( ) function is given below:

public void addprocesses ( ManagementObjectCollection moc )


{
m_plist.Items.Clear( ) ;

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

string[ ] items = new string [ 5 ] ;


foreach ( ManagementObject mo in moc )
{
items [ 0 ] = mo [ "Caption" ].ToString( ) ;
items [ 1 ] = mo [ "ProcessId" ].ToString( ) ;

int vs = Int32.Parse ( mo [ "WorkingSetSize" ].ToString( ) ) ;


vs = vs / 1024 ;
items [ 2 ] = vs.ToString( ) + " Kb" ;

if ( mo [ "ExecutablePath" ] == null )
items [ 3 ] = "NA" ;
else
items [ 3 ] = mo [ "ExecutablePath" ].ToString( ) ;

items [ 4 ] = mo [ "Priority" ].ToString( ) ;

ListViewItem lvitems = new ListViewItem ( items ) ;


m_plist.Items.Add ( lvitems ) ;
}
}

In this function, at first, we have removed all the previously added list items from the control by
calling the Clear( ) method. Next, we have enumerated the objects from the collection passed to
this function in a foreach loop. Each object in the collection represents a process. We would
display the process name, process ID, memory the process is using, path of the EXE and priority
of process in the list control. To obtain this information of the process, we have used various
properties of the Win32_Process class. They are given below:

Caption: It returns the name of the process.

ProcessId: It returns the ID of the process.

WorkingSetSize: It returns the amount of memory (in bytes) the process is required to run
efficiently.

ExecutablePath: It returns the path of the process.

Priority: It returns the priority of the process.

To display the values returned by these properties, firstly we have created an array of five strings.
Since the properties return value of type object we have converted them to strings. The
WorkingSetSize property returns memory size in bytes. We have converted bytes into kilobytes
before converting them to string.

After populating the string array, we have created an object of the ListViewItem and passed the
array to its constructor. The 0th element in the array will be treated as new list item, and rest of
the elements as its sub-items. Then we have called the Add( ) method to add the new list item to
the list control.

So, when we execute the application, it would look as shown in the following figure.

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

We can now enter the machine name, user name and password and click the ‘Refresh’ button to
view the processes of that machine. We would see the ‘Refresh’ button handler next time.

Article – C# - Creating Owner Drawn Menus

Most of the times menu items are strings, but sometimes picture make more sense than text
strings. For example, a color menu should show colors rather than text strings containing names
of various colors. It would make more sense for the user if the colors like magenta and cyan are
shown as they are going to look like rather than as strings saying “Cyan” and “Magenta”. If the
colors were shown, their meaning would be crystal clear. Unfortunately, the MenuItem class does
not provide a standard way to display pictures/icons. For example, there is no Icon property you
set to display an icon automatically. However, the MenuItem class provides the capability for non-
standard drawing, often called “owner-drawing”.

Every menu item has a property called OwnerDraw. When the OwnerDraw property is set to
true, it indicates that the user, not Windows, will handle all drawing of the menu item. .NET IDE
gives full support for creating the owner drawn menus.

In this article we would create a WinForm application with owner drawn menu. The menu titled
‘Color’ will display three menu items having icons plus text. The icons will represent colors ‘Red’,
‘Green’ and ‘Magenta’. On clicking the menu items background of the form will get filled with the
selected color.

Create a WinForm application and add a Menu control to the form. Name the control as m. Add
the menu item ‘Color’ to the menu m. Add three menu items to the ‘Color’ menu item. Name them
as m1, m2 and m3 respectively. Set the OwnerDraw property of these menu items to True.
When a menu is pulled down, the Framework first calls the MeasureItem event handler for each
owner-drawn menu item to determine how big the menu needs to be. Then it calls the DrawItem
event handler for each owner-drawn menu item to actually do the drawing. That’s why we need to
add event handlers for both these events. We must add the event handlers for all the three menu
items. This will add total of six functions to the Form1 class. Lets now add code to these
handlers. Look at the MeasureItem event handler for the m1 menu item.

private void m1_MeasureItem ( object sender, MeasureItemEventArgs e )


{
e.ItemHeight = 20 ;
e.ItemWidth = 80 ;
}

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

The MeasureItemEventArgs class provides data for the MeasureItem event. The properties we
need to set are ItemHeight and ItemWidth. We will need the height of the menu item, which is
the greater than the icon height or the font height plus a few pixels, and the width of the menu.
We will do the actual drawing in the DrawItem event handler. The handler is given below.

private void m1_DrawItem ( object sender, DrawItemEventArgs e )


{
e.Graphics.FillRectangle ( SystemBrushes.Control, e.Bounds ) ;
e.Graphics.DrawIcon ( new Icon ( "C:\\icon1.ico" ), e.Bounds.Left + 3, e.Bounds.Top + 3 ) ;
Brush br = new SolidBrush ( Color.Blue ) ;
e.Graphics.DrawString ( "Red", new Font ( "Courier New", 9 ), br, ( float )( e.Bounds.Left +
35 ), ( float ) ( e.Bounds.Top + 2 ) ) ;
}

The DrawItemEventArgs class contains all the information needed for the user to paint the
specified item, including the item index, the Rectangle and the Graphics on which the drawing
should be done. In this handler, firstly, we have filled the bounds of the menu item with the
standard control color. This is necessary to display the bounding rectangle around the icon.
Otherwise the icons will get mixed up. Next, we have drawn the icon on the menu item using the
DrawIcon( ) method. We have left the suitable number of pixels from left and top of the icon. Next
to the icon we have displayed the string mentioning the color name. While drawing the string, we
must leave the space where icon has been drawn. We must also keep suitable distance from
icon. That’s why we have left 35 pixels from left side of the menu item bounds.

The MeasureItem and DrawItem event handlers for the other two menu items are same. Only
the icon files are different.
Add the Click event handlers for the menu items and set the BackColor property of the form to
respective color.

Creating one menu item having three owner drawn menu items is quite manageable, although it
is resulting into repetition of code. We can avoid this by inheriting a class from the MenuItem
class and handling the event handlers in it.

Create our own iconmenuitem class derived from the MenuItem class. This class is given
below.

class iconmenuitem : MenuItem


{
Icon m_icon ;
string mtext ;

public iconmenuitem( )
{
}

public iconmenuitem ( string menutext, EventHandler eh, Shortcut sh, Icon ico ) : base
( menutext, eh, sh )
{
this.OwnerDraw = true ;

this.DrawItem += new DrawItemEventHandler ( drawitem ) ;


this.MeasureItem += new MeasureItemEventHandler ( measureitem ) ;

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

m_icon = ico ;
mtext = menutext ;
}

private void drawitem ( object sender, DrawItemEventArgs e )


{
e.Graphics.FillRectangle ( SystemBrushes.Control, e.Bounds ) ;
e.Graphics.DrawIcon ( m_icon, e.Bounds.Left + 3, e.Bounds.Top + 3 ) ;
Brush br = new SolidBrush ( Color.Blue ) ;
e.Graphics.DrawString ( mtext, new Font ( "Courier New", 10 ), br, ( float )( e.Bounds.Left +
this.m_icon.Width + 5 ),
( float ) ( e.Bounds.Top + 2 ) ) ;
}

private void measureitem ( object sender, MeasureItemEventArgs e )


{
e.ItemHeight = 20 ;
e.ItemWidth = 80 ;
}
}

In this class we have provided the default constructor and a four-argument constructor. To this
constructor we have passed the menu text and the icon to be displayed. We have set the
OwnerDraw property to true and added the DrawItem and MeasureItem event handlers. We
have stored the icon and menu text passed to the constructor to some data members of
iconmenuitem class. The event handlers drawitem( ) and measureitem( ) contains the same
code we saw above.

We would have a Menu control named m. The menu m will have one menu item m1 titled ‘Color’
and ‘Color’ menu item will have menu items m2 and m3. The m1 menu item is created by calling
default constructor as shown below.

m1 = new ownerdrawn.iconmenuitem( ) ;

Now create the menu items m2 and m3 using the iconmenuitem class as shown below. Add this
code to the constructor of the Form1 class after the call to the InitializeComponent( ) method.

Icon i1 = new Icon ( "C:\\icon1.ico" ) ;


m2 = new iconmenuitem ( "Red", new EventHandler ( m2_click ), new Shortcut( ), i1 ) ;

Icon i2 = new Icon ( "C:\\icon2.ico" ) ;


m3 = new iconmenuitem ( "Green", new EventHandler ( m3_click ), new Shortcut( ), i2 ) ;

m1.MenuItems.AddRange ( new System.Windows.Forms.MenuItem[ ] { m2, m3 } ) ;

Add m1, m2 and m3 as data members of type iconmenuitem to the Form1 class.

The Click event handler for the m2 menu item is given below. In the same way add the event
handler for the m3 menu item.

private void m2_click ( object sender, System.EventArgs e )


{

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

BackColor = Color.Red ;
}

The output of the program is shown below.

Article – C# - Creating UI for an XML Document

There are two purposes of this article. First, to show how to work with a tree control in .NET and
second, to create a user interface for an XML document. To fulfill these purposes, we have
created a WinForm application that displays the elements and nodes of an XML document in a
tree view control.

Firstly we would understand the structure of a tree view control.

The TreeView control displays tree items, called nodes, in a hierarchical manner. A parent node
contains child nodes. The child nodes can be parent nodes for other nodes. Two child nodes
having same parent node are called sibling nodes. The first parent node of a tree is called the
root node. There can be multiple root nodes in a tree, just like a system has multiple root drives.

The nodes displayed in a tree are instances of the TreeNode class. Each TreeNode has a
Nodes collection stored in the TreeNodeCollection. This collection stores the list of other
TreeNodes, its children. The Parent property returns the reference to the parent node.

Now, place a TextBox, Button, TreeView, Label and an ImageList control on the form. Name the
control as shown in the following table.

Control Name
TextBox txtfile
Button bload
TreeView xmltree
ImageList imglist
Label lblpath

We would display different images for XML elements and nodes in the tree control. For this,
create four bitmap files. Add these files to the Images collection of the ImageList control. The first
two images would be used for elements and nodes, whereas, next two images would be used as
selected images for elements and nodes

The user should enter an XML file name in the text box and click the ‘Load’ button. This would

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

display the XML document in the tree control. Add the Click event handler for the ‘Load’ button.
This handler is given below.

private void bload_Click ( object sender, System.EventArgs e )


{
try
{
XmlDocument doc = new XmlDocument( ) ;
doc.Load ( txtfile.Text ) ;
xmltree.Nodes.Clear( ) ;
additem ( doc.DocumentElement, null ) ;
}
catch ( Exception e1 )
{
MessageBox.Show ( e1.Message ) ;
}
}

Here, we have loaded the document in memory by calling the Load( ) method of the
XmlDocument class. It may happen that the user would first load one document and then
another. In such case, we must delete the nodes of first document before adding new nodes to it.
We have done so by calling the Clear( ) method of the TreeNodeCollection class. We have
accessed the collection using the Nodes property of the TreeView class.

To add the new item, we have called the user-defined additem( ) method. We have passed two
parameters to it—the node of the XML document loaded in memory as first parameter and node
of the tree control as second parameter. The root node in the document is represented by the
DocumentElement property. We have passed null as the tree control’s node because there are
no nodes in the tree control yet.

We have written the code in try-catch block because the Load( ) method throws an exception if it
fails instead of returning an error value.

Let’s write the additem( ) method.

public void additem ( XmlNode xnode, TreeNode tnode )


{
TreeNode child = addnode ( xnode, tnode ) ;
if ( xnode.Attributes != null )
{
string text ;
foreach ( XmlAttribute attr in xnode.Attributes )
{
text = attr.Name + " = " + attr.Value ;
child.Nodes.Add ( new TreeNode ( text ) ) ;
}
}
if ( xnode.HasChildNodes )
{
foreach ( XmlNode node in xnode.ChildNodes )
additem ( node, child ) ;
}
}

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

The additem( ) method is used to traverse the document structure loaded in memory. It would
start traversing from the node that is passed to it in xnode. For the first time, xnode would
contain the root document node. From this method we have called another user-defined method
called addnode( ). The addnode( ) method actually adds the XML node to the tree control at
appropriate place and returns its reference. We have collected this reference in child. If the XML
node that has been added to the tree has attributes, we must add them to the newly added tree
node. To retrieve the attributes we have used the Attributes property. It returns all the attributes
of the node in a collection. We have retrieved an attribute from collection in a foreach loop and
added its name and value to the tree node. For this, we have used the Add( ) method.

If the XML node has child nodes then this procedure should repeat for each child node. We have
checked whether the XML node has children or not using the HasChildNodes property. Then for
each node we have called the additem( ) method recursively. This time we are passing reference
to the child node as first parameter and reference to the newly added tree node as the second
parameter to the additem( ) method.

The addnode( ) method is given below.

public TreeNode addnode ( XmlNode xnode, TreeNode tnode )


{
string txt ;
TreeNode child = new TreeNode( ) ;
TreeNodeCollection tnodes ;
if ( tnode == null )
tnodes = xmltree.Nodes ;
else
tnodes = tnode.Nodes ;
switch ( xnode.NodeType )
{
case XmlNodeType.Element:
child = new TreeNode ( xnode.Name ) ;
child.ImageIndex = 0 ;
child.SelectedImageIndex = 2 ;
tnodes.Add ( child ) ;
break ;
case XmlNodeType.Text:
txt = xnode.Value ;
if ( txt.Length > 128 )
txt = txt.Substring ( 0, 128 ) + "..." ;
child = new TreeNode ( txt ) ;
child.ImageIndex = 1 ;
child.SelectedImageIndex = 3 ;
tnodes.Add ( child ) ;
break ;
}
return child ;
}

Let us now see the addnode( ) method. Here, firstly we have declared child as a reference of
type TreeNode and tnodes of type TreeNodeCollection. The TreeNodeCollection object
represents a collection of tree node objects. If the tree control is empty we must add the XML
node as the root node of the control. Otherwise we must add the XML node as a child of tnode.
We have achieved this by applying if condition on tnode.

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

We have checked the type of XML node in the switch-case block. If the node type is element we
have added its name to the tree node. Before adding, we have created the new node and
collected its reference in child. This node is then added to the tree control. We have provided
proper images using the ImageIndex and SelectedImageIndex properties.

If the node type is text content we must add its value to the tree node.

Before adding text content, we have checked whether its length exceeds 128. If it does, we have
extracted first 128 characters and added ellipses (…) to it indicating the incomplete string. We
have then created a new node child and added it to the tree control. Lastly, we have returned the
reference to the newly created node.

We have added a handler for the AfterSelect event of the TreeView control. This event is thrown
when tree item selection is changed. In this handler we have obtained the path of the tree node
and displayed it in the label.

private void xmltree_AfterSelect ( object sender, TreeViewEventArgs e)


{
lblpath.Text = xmltree.SelectedNode.FullPath ;
}

We have obtained currently selected tree node using the SelectedNode property. The FullPath
property of the TreeNode class returns the path of the node with respect to the root node.

Article – C# - Deploying .NET Applications - I

Though distributing libraries in the form of DLLs was a major step forward, it suffered from the
now in-famous DLL hell. COM could avoid this but it had no versioning mechanism. Moreover a
COM component had foot-prints at so many places that if one of them got modified/corrupted, the

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

application used to break down. .NET has come up with more sophisticated approaches for
deployment and versioning.

Deployment Issues

Deployment is a process by which you distribute a finished application or component to be


installed on other computers. In Visual Studio .NET, deployment is based on Microsoft Windows
Installer technology. Microsoft Windows Installer is a service shipped with Windows Me, Windows
2000, and Windows XP. It is used for installation and configuration of applications to be installed.
Every .NET application is deployed in the form of one or more assemblies. Assemblies may be
deployed as regular standalone files (DLL or EXE files), or they may be deployed using CAB,
MSI, or MSM files. The simplest way of deploying a private assembly is to use an XCOPY, i.e.
copying the assembly in the desired folder. On the other hand we can deploy shared assemblies
by installing them in the Global Assembly Cache of the target machine by using the Gacutil.exe.

To help programmers develop setup and deployment solutions, Visual Studio .NET provides
several templates and wizards. We can create a setup or deployment project by selecting ‘Setup
and Deployment Projects’ in the ‘New Project’ dialog box shown in the following figure.

Let us first discuss the types of projects shown in the dialog box and see the usage of each. Later
we have illustrated how to deploy different types of applications using these projects.

Setup Project

A setup project builds a Windows Installer file or an MSI file with the .msi extension. This file is
used to install the specified files and resources on the target machine automatically. The .msi file
contains the application, any dependent files, information about the application such as registry
entries, and instructions for installation. When the .msi file is distributed and run on another
computer, you can be assured that everything necessary for installation is included; if for any
reason the installation fails (for example, the target computer does not have the required
operating system version), the installation will be rolled back and the computer returned to its pre-
installation state.

CAB Project

A CAB project creates a cabinet file with the .cab extension. It is much like a Zip file, compressing

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

a number of specified files into an easy to use and easy to deploy package. The resulting cabinet
(.cab) file can then be deployed or downloaded. The files present in the .cab file can be extracted
by double-clicking the .cab file.

Merge Module Project

A Merge Module project produces a merge module file having a .msm extension. A Merge
Module is a single package that contains all files, resources, registry entries, and setup logic
necessary to install a component.

Merge Modules are used to install components that are shared by multiple applications. The
basic distinction between a Merge Module (.msm) and a Windows Installer (.msi) is based on the
user using these components. Whatever we wish to deploy directly to the end user of the
application (executable files, documents, HTML pages) should be packaged in a Windows
Installer, whereas, whatever we wish to deploy to the developer (DLLs, controls, resources)
should be packaged in a Merge Module. The developer can then repack it in a Windows Installer
for distribution to the end user. It is possible to put multiple components into a single Merge
Module but it's best to create a Merge Module for each component in order to handle versioning
problems. Once you have distributed a Merge Module it should never be modified; instead you
should create a new Merge Module for each successive version of your component.

Web Setup Project

Web Setup Project helps us to deploy web-based applications. In addition to this any Windows
application or its installer can be deployed to a web server so that users can later download and
run them from a web site. In order to deploy web-based application we will have to build a Web
Setup Project, copy it to the web server and run the installer to install it on the server.

Setup Wizard

The Setup Wizard is used to help us start creating any of the above-discussed projects in a fast
and simple manner. We just have to follow some simple steps the wizard leads us through and
the wizard does the initial job for us. Next we may extend the project further as per our
requirements. Now let us understand the projects discussed above in detail.

Setup Projects

We know that a Setup Project creates an .msi file, which actually installs the application on the
target computer. To demonstrate this we plan to deploy a simple Windows application using the
Setup Project. Here we have assumed that the Windows application stands created and the .EXE
named windowsapp1.exe is ready. To deploy this Windows application we need to select ‘New |
Project’ and select ‘Setup and Deployment project’ from the available options. Next we must
select ‘Setup Project’ as the project template and specify the name (say winsetup) and the
location of the setup project and click OK. Then we are taken to the File System Editor. The File
System Editor is shown in the following figure.

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

The File System Editor has three folders—the Application Folder, the User’s Desktop folder and
the User’s Programs Menu folder. These folders actually represent the folders on the target
machine. For example, whatever you put in User’s Desktop will be deployed on the desktop of the
target machine. From the three folders in the file system editor, files from Application Folder would
be deployed in the Program Files folder; typically it is ‘C:\Program Files\Company
Name\Application Name’ of the target machine. User’s Desktop folder contains files and folders
that would appear on the desktop of the target machine on a per-user basis. Typically the path is
‘C:\Documents and Settings \username\Desktop’. User’s Programs Menu folder contains user’s
program groups that would usually get deployed in ‘C:\Documents and Settings \username\Start
Menu\Programs’.

Now we need to add the Windows application EXE file into this project. For this we must right
click on the Application Folder. A menu is popped. We must select Add | File and on doing so an
‘Add Files’ dialog is popped. Now we need to browse for ‘windowsapp1.exe’ file so that it gets
added to the Application Folder. We can add the EXE to User’s Desktop and User’s Programs
Menu as well but while doing so we must keep in mind that these two folders are on per-user
basis. This means that only the user who installs the application would be able to access the file
on his desktop and not the other users.

This completes the basic steps needed to build an installer. We can now build this project and an
installer called ‘winsetup.msi’ would get created in the debug folder. Now all we need to do is to
distribute this installer and on running the installer on the target machine the application would get
installed there.

On running the installer we get a series of screens depicting different stages of installation. Note
that if our application needs more files than just the ‘windowsapp1.exe’ then we can copy them to
any of the above-mentioned folders.

There is much more to a Setup Project than what we discussed above. We saw the simplest form
and there are several more features that we need to explore. All the deployment capabilities
discussed below are not mandatory and we can customize our installation process according to
the needs of our application.

Adding Shortcuts

We can add shortcuts to our application in any of the 3 folders. For this we need to right click on

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

the application file (‘windowsapp1.exe’) that we added to the project and select ‘Create shortcut
to windowsapp1.exe’. On doing so a shortcut for our application would get created. Now we must
drag this shortcut in the User’s Desktop Folder. If we wish to add a shortcut in User’s Programs
Menu also, we need to create another shortcut in the same manner discussed above and drag it
in the folder. On building and installing the application, the shortcuts get added in the specified
folders of the target machine.

Adding Registry Entries

We can make a provision that some registry entries would be added for a particular application
during installation of the application. We can then access these entries later through our
application’s code at run-time. To add the registry entries we must right click on winsetup in the
Solution Explorer and select View | Registry. On doing so we will be presented with the Registry
Editor shown in the following figure.

Article – C# - Deploying .NET Applications - II

Suppose we wish to add a key-value pair to HKEY_CURRENT_USER | Software |


[Manufacturer]. For this we must right click on it and select New | Key. We can rename the key as
per our wish. To add a value we need to right click on the newly formed key and select the type of
value we wish to add, i.e. whether it should be a String value, a DWORD value, a Binary value,
etc. We can set it to some value using the Properties Window. Now if we build winsetup and
install the application, the entry would be made in the registry. We can verify this by executing the
Registry Editor RegEdit through the ‘Start | Run’ dialog box.

Adding Custom Installation Dialog Boxes

Once the MSI file is built and we double click on it, the installation starts. The user is presented
with five dialog boxes during installation. These dialog boxes are predefined dialog boxes that get
added to our project by default. We can customize these dialogs or new dialog boxes to our
project using the User Interface Editor. This editor can be opened by right clicking on the project
in Solution Explorer and selecting ‘View | User Interface’.

The User Interface Editor shows a tree control containing two sections—Install and Administrative
Install. The Install section contains dialog boxes that will be displayed when any end user runs

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

the installer. Administrative installation is a feature of Microsoft Windows Installer that allows us to
install a source image of an application on a network share. Users in a workgroup who have
access to the network share can then install the application from the source image. The User
Interface Editor allows us to specify a different set of installation dialog boxes that will be
displayed when an administrator installs the application to a network share via the command line
as shown below:

Msiexec.exe /a Setup1.msi

This will start the installer of our application and dialog boxes specified for the Administrative
Install will be displayed.

The default set of predefined dialog boxes is displayed in the User Interface Editor; we can
rearrange or delete these if we wish. The default set of dialog boxes varies according to the type
of deployment project. Predefined dialog boxes are divided into three categories:

Start Dialog Boxes

Start dialog boxes are displayed before the installation begins. Commonly they are used to gather
customer information or to allow the user to change the installation directory.

Progress Dialog Boxes

A progress dialog box is displayed to provide feedback on the progress of an installation.

End Dialog Boxes

End dialog boxes are displayed once the installation has finished successfully. Common uses are
notifying the user that the installation is complete or to allow the user to launch the application.

We can remove dialog boxes from the default set as per our wish or reposition them using the
right click | Move Up/Move Down options. Note that all combinations are not possible here. For
example, we cannot remove the Progress dialog box and place it in the Start dialog boxes
category after the Welcome dialog box.

Now in addition to these dialog boxes we can add and configure our own custom dialog boxes
that would get displayed during the installation. To do so we need to right click on the desired
category and select ‘Add Dialog’. On doing so the Add Dialog Box gets displayed.

Here we are presented with several ready-made dialog boxes that we may want to get displayed
during installation. Following table indicates the use of these dialog boxes.

Dialog Box Purpose


RadioButtons (2 Gives the user a choice between two options through two
buttons) radio buttons.
RadioButtons (3 Gives the user a choice between three options through
buttons) three radio buttons.
RadioButtons (4 Gives the user a choice between four options through four
buttons) radio buttons.
Checkboxes A, B, or Gives the user a choice to add 1, 2, 3 or 4 checkboxes in
C the same dialog.
Customer Information Used to retrieve information including name, company, and

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

serial number.
Used to retrieve custom information using 1, 2 or 3 text
Textboxes A, B, or C
boxes.
Displays a license agreement for the user to read and
License Agreement
acknowledge.
Read Me Allows the user to view any Read me file in .rtf format.
Register User Allows the user to submit registration information.
Displays a Splash Screen in .bmp format during
Splash
installation.

Out of the several dialog boxes listed in this table we would discuss only the ones that are likely
to be used more commonly. These include the Checkbox dialog box, Read Me Dialog box and the
Splash dialog box.

The Checkbox Dialog Box

Suppose during installation we plan to ask the user whether he wants to add the ‘Disclaimer.txt’
file along with ‘windowsapp1.exe’ or not. To control this we plan to add the Checkbox dialog box.
If the user checks the Checkbox, the text file gets installed. To add this custom dialog box we
have followed the same steps discussed above and added the Checkboxes (A) Dialog. This
dialog box would get added as the last dialog box of the Start dialog boxes category. So we can
move it up by two positions. Next we have changed some properties of the Checkboxes (A)
dialog box. These are shown in the following table.

Property Changed to...


BannerText Disclaimer
Do you want to install the Disclaimer
BodyText
text file?
Checkbox1Label Install Disclaimer
Checkbox1Value Unchecked
Checkbox1Visible True
Checkbox2Visible False
Checkbox3Visible False
Checkbox4Visible False

Note that we have changed the visible property of the remaining checkboxes to false because we
need just one checkbox. Now we need to add a folder in the Application Folder named
Disclaimer. For this we must right click on the Application Folder and select ‘Add | Folder’. This
would add a new folder we have renamed it to Disclaimer. Next we added a text file called
‘Disclaimer.txt’ to this folder. Hence the Application Folder would contain the ‘windowsapp1.exe’
along with the Disclaimer folder holding the ‘Disclaimer.txt’ file. Then comes the most important
step of setting the Condition property of the ‘Disclaimer.txt’ file so that it would only get installed
when the checkbox is checked. To do this we need to open the Properties Window of the
‘Disclaimer.txt’ and set its Condition property to CHECKBOXA1=1. On building the winsetup.msi
project, and double clicking it we are presented with this dialog box in the second step of the
installation process. The Disclaimer dialog box is shown in the following figure.

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

The Read Me Dialog box

This dialog box displays the Read Me file during installation procedure and installs it along with
the application. To demonstrate this we must add the Read Me dialog box in the Start dialog
boxes category. Next we need to associate a Rich Text File (rtf) with this dialog box. For this we
have to create a ‘ReadMe.rtf’ file and add it to the Applications Folder. Next we have to set the
ReadmeFile attribute of the Read Me Dialog box to this file. We can browse for this file and since
we had added it to the Applications Folder we will find it there. Note that we cannot browse
beyond the three folders (Application Folder, User’s Program and User’s Programs Menu), hence
if we wish to make any file available in the project we have to first get it copied in one of these.
Now after re-building the project and installing it we are presented with this Read Me dialog box
as the 5th step of installation and this file gets copied along with the folder.

The Splash Dialog Box

We added the Splash dialog box just after the Welcome dialog box. The User Interface Editor
after addition of all the dialog boxes is shown in the following figure.

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

To display a splash screen in the Splash dialog box, all we need to do is to set the SplashBitmap
property of the dialog to a ‘.bmp’ file. To make the file available we must first add it to the
Application Folder. On re-building this project and running the installer we are presented with the
Splash dialog box.

In the next part we would see how to add launch conditions to the setup project.

Article – C# - Using the FileSystemWatcher Component

In this article we would walk through the process of using the FileSystemWatcher component and
watching the changes made to a subfolder/files of a selected folder.

The FileSystemWatcher component can keep track of creation, deletion, changing and renaming
of a file/folder. It conveys the application about changes done to the file system by throwing
events. It throws the Created, Deleted, Changed and Renamed events respectively. The name
and path of the file/folder being changed is also made available in the event handlers.

The FileSystemWatcher component can watch files on a local computer, a network drive, or a
remote computer. We can specify which files to watch by setting the appropriate value in the
Filter property. If we wish to watch all the files we must set the Filter property to an empty string
(“”). To watch a specific file, we must assign that file name to the Filter property. We can also use
wildcards to specify certain type of file. For example, to watch for changes in EXE files, we can
set the Filter property to “*.exe”.

The component has a property called NotifyFilter that can be used to specify the types of
changes viz. changes in attribute, last write date and time, size, etc.

Having this much of knowledge about FileSystemWatcher component in hand, we can now use
the component in our application.

We would create an application that uses the FileSystemWatcher control to keep watch on the
folder selected by the user. We would watch whether a file/folder is created, changed or deleted.

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

Create a WinForm application and put the controls on the form as shown in Figure 1.

Figure 1

We have added three list boxes to list the files/folders being created, changed or deleted. The
‘Watch Folder’ button allows user to select a folder to watch. The path of the selected folder gets
displayed on the label placed next to the ‘Watch Folder’ button. The ‘Clear’ button allows to delete
the items listed in the list box having input focus.

In addition to these controls, add the FolderBrowserDialog control from the ‘Windows Forms’ tab
and FileSystemWatcher component from the ‘Components’ tab of the ToolBox. The controls, their
names and event handlers are given in the following table.

Controls Name Handler


‘Created’ list box listcreate -
‘Changed’ list box listchange -
‘Deleted’ list box listdelete -
‘Watch Folder’ button butwatch butwatch_Click
‘Clear’ button butclear butclear_Click
FileSystemWatcher watcher -
FolderBrowserDialog browser -

Add handlers for the Created, Deleted and Changed events. Also Set the
IncludeSubdirectories property of the FileSystemWatcher component to true.

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

When the application is run, the user has to first select a folder to watch. He can do so by clicking
the ‘Watch Folder’ button. We have displayed the ‘Browse For Folder’ standard dialog box in
which user can select the folder. The dialog is displayed by calling the ShowDialog( ) method as
shown below.

private void butwatch_Click ( object sender, System.EventArgs e )


{
if ( browser.ShowDialog( ) == DialogResult.OK )
{
watcher.Path = browser.SelectedPath ;
label1.Text = browser.SelectedPath ;
}
}

We have specified the folder to watch by setting the Path property of the FileSystemWatcher
class to the path of selected folder. The path of selected folder is retrieved from the SelectedPath
property of the FolderBrowserDialog class. We have displayed the path on the label.

The handlers added for the FileSystemWatcher events are given below.

private void watcher_Changed ( object sender, System.IO.FileSystemEventArgs e )


{
listchange.Items.Add ( e.FullPath ) ;
}

private void watcher_Created ( object sender, System.IO.FileSystemEventArgs e )


{
listcreate.Items.Add ( e.FullPath ) ;
}

private void watcher_Deleted ( object sender, System.IO.FileSystemEventArgs e )


{
listdelete.Items.Add ( e.FullPath ) ;
}

In these handlers we have only added the full path of the file/folder being changed, created or
deleted in the respective list boxes.

To clear a list box, the user has to select an item in that list box and click the ‘Clear’ button. The
handler for the ‘Clear’ button is given below.

private void butclear_Click ( object sender, System.EventArgs e )


{
if ( listcreate.SelectedIndex != -1 )
listcreate.Items.Clear( ) ;
else
{
if ( listchange.SelectedIndex != -1 )
listchange.Items.Clear( ) ;
else
if ( listdelete.SelectedIndex != -1 )

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

listdelete.Items.Clear( ) ;
}
}

The SelectedIndex property returns –1 if no item is currently selected. If any item is selected, the
condition becomes true and the list box gets cleared.

Figure 2 shows our application at work. The list boxes seem to have trapped few files being
changed.

Article – C# - Deploying .NET Applications - III

In the last article we saw how to add custom dialog boxes to the setup project. We would now
add the launch conditions to it.

Sometimes our application may require some pre-requisites before installation. For example, our
application may demand that Internet Explorer 5.0 or higher must be installed on the target
machine. This calls for a check that must be satisfied for successful installation of the application.
We can apply Launch Conditions in such cases. If the condition specified during this step (here,
Internet Explorer installed) is not fulfilled then the installation halts. Note that here this step is
intended to demonstrate the concept of launch conditions and ‘windowsapp1.exe’ has no actual
dependency on Internet Explorer.

To add launch conditions we need to right click on the project in the solution explorer and select
View | Launch Conditions. On doing so a Launch Condition Editor will get opened. Next we need
to right click on the Requirements on Target Machine node and we would be presented with 5
options to choose from—Add File Launch Condition, Add Registry Launch Condition, Add

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

Windows Installer Launch Condition, Add .NET Framework Launch Condition, and Add Internet
Information Services Launch Condition. As the names suggest we can check for the specified
entities on the target machine and if these entities are present on the target machine, the
installation proceeds otherwise it halts.

Here we have added the Add File Launch Condition. On doing so two nodes called Search For
File1 and Condition1 would get added in the Search Target Machine and Launch Conditions
nodes respectively falling under the Requirements on Target Machine node. We changed the
properties shown in the following table for the Search For File1 entity.

Property Changed to... Used


Search For Internet Specifies the name used in Launch Condition
Name
Explorer Editor.
FileName Iexplore.exe Specifies the name of a file to search for.
Folder [ProgramFilesFolder] Specifies the folder where a file search will start.
Specifies the number of levels of subfolders to
Depth 3
search for a file.
Specifies the minimum version number for a file in
MinVersion 5.00
the file search.

Now we need to specify the launch condition. To do so we must set the Condition property of the
Condition1 entity to FILEEXISTS1. Note that in the Properties window of Search For File1 the
Property property is set to FILEEXISTS1. We can also specify a message through the Properties
window that would be displayed if the condition evaluates to false (i.e. if file is not found) at
installation time.

Changing Icons

We can change icons for our application using the Properties window. To change the icon for the
shortcuts we must select the shortcut file and set the Icon property of the file to any .ico file. Note
that we need to first copy this file to the Application Folder to make it available.

On the same lines we can change the icon of the setup file that would be displayed in the
Add/Remove Programs Window. To do so, we must right click on winsetup in Solution Explorer
and select Properties. This would display the Properties window of the whole solution. Here we
need to set the AddRemoveProgramsIcon to any desired file.

Adding File Associations

Suppose our application creates files having the user–defined extension (for example, we can
serialize data in a file having the .mine extension) and now we wish that on double clicking such
a file it should automatically get opened in our application. To achieve this we must use file
associations. File Associations allows the developer to associate user-defined file types with his
or her application. Assume that we need to deploy a file called myfile.mine with our application.
To deploy it along with the application we first need to copy it in the Applications Folder. After
installation whenever the user double clicks on this file it should get opened with
windowsapp1.exe. Note that here too we have made an assumption for demonstration purpose
that our application is creating files having .mine extension. Actually windowsapp1.exe is too
simple and does not do any serialization or file I/O.

Now to associate this file with our application we must right click on the project name in the
Solution Explorer and select View | File Types. On doing so we are presented with the File Types
Editor. Next we need to right click on the node and select Add File type. Now we need to give any

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

file name (here we have used file1) along with the extension (.mine) in the Properties window.
This ensures that any file with the .mine extension would get opened with our application. Note
that we need not specify the dot ( . ) while mentioning the extension. After this we have to set the
Command property of the file to windowsapp1.exe. The File Types Editor along with the
Properties window is shown in the following figure.

Now on re-building the project and running the installer, myfile.mine would get deployed along
with the application. And moreover whenever the user double clicks on this file it gets opened with
our application.

Adding Custom Actions

Custom actions allow us to run code at the end of an installation to perform actions that cannot be
handled during installation. For example, if we wish to create a database after installation and
before running the deployed application, we need to add the DLL or EXE, which would create a
database, as a custom action. We can add custom actions through the Custom Actions Editor.
The Custom Actions Editor can be opened by right clicking on the project name and selecting
View | Custom Actions. The Custom Actions Editor is shown in the following figure.

This editor contains four folders, each corresponding with a phase of installation—Install, Commit,
Rollback, and Uninstall. Custom actions are run in the same order that they are displayed in the
editor. They can be reordered by dragging with the mouse or through the Cut and Paste
commands on the Edit menu. All the Custom Actions run at the end of installation. In addition to
the custom actions we add, there are 5 pre-defined custom actions included in Visual Studio
.NET—Event Log, Message Queue, Performance Counter, Service, and Service Process
components. We can also add these pre–defined Custom Actions in our project.

Deploying to Special Folders

In addition to the folders mentioned in the previous section—Application Folder, User’s Desktop,
and User’s Programs Menu—we can add more folders to the File System Editor through the ‘Add
Special Folders’ menu. If we right click on the left pane of the File System Editor we get a popup
menu offering fourteen folders from which we can select the ones that we can add.

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

On selecting a folder from this menu it gets added to the ‘File System on Target Machine’ tree.
This provision is made so that we can deploy our files to these specific folders on the target
machine. For example, if we have a signed assembly and we wish to deploy it in the Global
Assembly Cache of the target machine, all we need to do is add the Global Assembly Cache
folder in the File System Editor and copy our signed assembly to it. On installing the application
on the target machine one can find the assembly installed in the Global Assembly Cache.

That brings us to the end of discussion on how we can customize our MSI project according to
the requirement of the application we want to deploy. If we wish to deploy the application on the
development computer while building it, we have to right click on the project name in the Solution
Explorer and select Install. And if we wish to deploy it on another computer then, as it might be
very obvious to you by now, we need to distribute the winsetup.msi file.

Article – C# - Deploying .NET Applications - IV

Merge Modules are a feature of Windows Installer that provides a standard method for delivering
components, ensuring that the correct version of a component is installed. Merge Modules is
something that we would give to a developer and not the end user. For example, if we want to
distribute our DLL to another developer, we’ll create a Merge Module for it and distribute our DLL
in a Merge Module. While deploying a finished product the developer will include this Merge
Module in his MSI project and give it to the end user. Merge Modules are used to install
components that are shared by multiple applications.

Now let us proceed with creation of a Merge Module. Here we have assumed that a Class Library
stands created and the .DLL named ‘mylib.dll’ is ready. To create a merge module we need to
select Merge Module from the project templates available and name it, say mergesetup. On
doing so we are taken to the File System Editor. The File System Editor is shown in the following
figure.

The File System Editor has two folders—Common Files Folder and Module Retargetable Folder
falling under ‘File System on Target machine’. Files present in a Merge Module are generally
sharable files hence Common Files Folder is a good option to deploy the files. Whichever file we
copy in this folder gets deployed to the Common Files folder of the target machine. Here too we
have an option of adding special folders to the File System Editor by right clicking on the left pane
and selecting the desired folder. Files deployed in these folders would get deployed to
corresponding folders on the target machine.

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

The other folder, i.e. the Module Retargetable Folder, offers a lot of flexibility in deciding where
files should be installed. Let us see how. Now suppose the author of the merge module is not
sure where the developer wants the file to get deployed on the end user’s machine. In such a
case the author of the Merge Module must copy this undecided file into the Module Retargetable
Folder and set a default location for this file using the Properties window. This gives the developer
a chance to change or retarget the location of the file later while deploying the whole application
to the end user. Let us see how it is done.

For this we need to copy ‘mylib.dll’ in the Module Retargetable Folder and set the DefaultLocation
property of the Module Retargetable Folder to [GAC]. Next we must build the Merge Module. On
doing so a ‘mergesetup.msm’ file would get created in the debug folder. We can now give this
‘.msm’ file to the developer.

Now assume that the developer creates a Setup project called ‘msimerge.msi’. To add the Merge
Module to the project he needs to right click on the project name in the Solution Explorer and
select Add | Merge Module. He can then browse for ‘mergesetup.msm’ and add it to his project.
Now to retarget the file all he needs to do is open the Properties window of the ‘mergesetup.msm’
and set the Module Retargetable Folder property to any desired location. For example, if he
wants the file to get installed in Common Files Folder and not GAC as specified by the author of
the Merge Module then he might change the property. The Module Retargetable Folder property
falls under the MergeModuleProperties in the Properties window.

Now whenever the end user installs the ‘msimerge.msi’, ‘mylib.dll’ gets installed in the Common
Files Folder. Note that the developer can (and surely will) add his own application and associated
files in ‘msimerge.msi’ along with ‘mergesetup.msm’ for deployment.

CAB Projects

Unlike the other deployment project types, there are no editors provided for working with CAB
projects. Files and project outputs can be added to a CAB project through Solution Explorer, and
properties can be set in the Properties window or in the Project Property pages.

For .NET deployment, a CAB file can contain only one assembly, and the CAB file must be
assigned the same name as the contained assembly, but with the ‘.cab’ extension. For example, if
we create a cabinet file for ‘mylib.dll’, we need to name the cabinet file as ‘mylib.cab’. Creating a
cab file is very simple. Let us see how to create it.

To create a Cabinet or CAB project we select the Cabinet Project template from the New Project
dialog and name it, say mylib. To add files to this project, we need to right click on the project
name and select Add | Files. This would add the specified files in the project and on building the
project the ‘mylib.cab’ file would get created which can be deployed to target machines. Double
clicking on the cab file extracts the files compressed in it.

Deploying Windows Applications On Web

We have discussed two cases here. First we have explained the method by which a Windows
application (.exe) can be executed directly on the web and second by which an installer (.msi) of
the Windows Application can be downloaded from the web. For both the scenarios we have
assumed that ‘windowsapp1.exe’ stands created. And for both we first need to create a Web
Setup project.

To create a Web Setup project we selected the Web Setup Project from the project templates and
named it websetup. On doing so, the File System Editor of websetup would get opened. Now we
need to add ‘windowsapp1.exe’ to the Web Application Folder as shown in the following figure.

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

Next we need to change two of the properties of the Web Application Folder. First we have to set
the AllowDirectoryBrowsing property to True. This property determines whether users can see
a hypertext listing of files and subdirectories in a virtual directory. If it is set to True, users can
browse for it. Next we have to set the VirtualDirectory property to myweb. Now we need to build
websetup and copy the ‘websetup.msi’ file to the web server. On double clicking the MSI file the
project would get installed. To test the project we need to start Internet Explorer and type the
‘http:\\computername\myweb’ URL. You will see the name of the ‘windowsapp1.exe’ file in the
browser window. On clicking filename the EXE would get executed. For the second scenario we
need to follow the same steps as given above, but instead of copying the EXE to the Web
Application Folder, we need to copy an MSI (winsetup.msi) project, which includes the EXE to the
folder. Then on deploying and installing ‘websetup.msi’ we would get the window displaying the
name of the ‘websetup.msi’ file. On clicking it we would be presented with a dialog box that gives
us options to install or download the MSI. On installing or downloading the MSI we would be able
to execute the Windows application.

Setup Wizard

As told to you earlier the Setup Wizard helps us to start the deployment projects. The wizard
guides us through the steps of creating setup program that contains all information required for
installation. The steps in the Setup Wizard are self-explanatory. As soon as we select Setup
Wizard, give the project a name (say wizsetup) and press OK, we are presented with a Welcome
dialog.

On clicking ‘Next’ we are presented with the Step 2 window of the wizard. It asks us type of
project we intend to make. Suppose we select the first option and click ‘Next’, we get the third
dialog box. Here the Wizard asks us to add the files we wish to deploy. We can add the files by
clicking on the ‘Add’ button and browsing for the desired files. On clicking the ‘Next’ button the
Wizard presents us with the summary of the project. We had selected the first option and hence
on clicking the ‘Finish’ button the Wizard takes us to the File System Editor of the project. We can
now build the project as we would build any deployment project.

Article – C# - Binding Data With WinForm Controls

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

Gone are the days when we required to read records from a data source, separate the values of
a record in a set of variables and display the values in controls by writing page full of code. .NET
provides an ability that binds a control with a field in the data source. ADO.NET provides a
common set of classes for data binding for WebForm and WinForm controls. In this article we will
see data binding with the WinForm controls.

Create a WinForm application and design the form as shown below.

We will bind the controls to the data source of a hospital management system. The list box will
display patient IDs. On selecting the ID, patient’s name, his address and doctor’s name will get
displayed in text boxes. The patient’s photograph will get displayed in the picture box. The
controls, their names and handlers are given in the following table.

Control Name
ListBox list
Name TextBox name
Address TextBox address
Picture Box photo

Add the following data members to the Form1 class.

private SqlDataAdapter m_da ;


private DataSet m_ds ;
private BindingManagerBase m_bman ;

We will first fill the dataset with the data we wish to bind with the control. For this, add the
following statements to the constructor of the Form1 class.

m_da = new SqlDataAdapter ( "SELECT * FROM PatientInfo",


"SERVER=localhost;database=hospital;uid=sa;" ) ;
m_ds = new DataSet( ) ;
m_da.Fill ( m_ds, "PatientInfo" ) ;

We have read the ‘hospital’ database and filled the dataset with the ‘PatientInfo’ table. Fill the list
box with patient IDs using the following statements.

DataTable dt = m_ds.Tables [ "PatientInfo" ] ;


for ( int i = 0 ; i < dt.Rows.Count ; i++ )

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

list.Items.Add ( dt.Rows [ i ][ 0 ].ToString( ) ) ;

Lets now see how data binding works.

Binding data with control actually means binding a property of a control with a column of a data
source. When the form is loaded the data bound property gets evaluated and the value returned
is displayed in the control. For example, the Text property of TextBox control can be bound to a
column of a data source. A WinForm control maintains a collection of its data bindings in the
ControlBindingsCollection class. The data bindings in the collection are maintained using the
DataBindings property. The DataBindings list is set once, stays up forever. The list is defined in
a position-agnostic fashion. In fact, the control does not know about the current row to which it is
bound. We will see how to select the row to be displayed later.

Firstly, we would see how to bind the control property with data source. Consider the following
statements.

Binding bname = new Binding ( "Text", m_ds, "PatientInfo.PatientName" ) ;


name.DataBindings.Add ( bname ) ;

Here, we have created a new data binding using the Binding class. We have passed three
parameters to its constructor. The first parameter is the binding property. Second parameter is the
data source and third specifies the ‘table.column’ in the data source. So, we are binding the Text
property with the ‘PatientName’ column of ‘PatientInfo’ table. We have added this data binding to
the collection of data bindings of the ‘Name’ text box using the Add( ) method. The property does
not always evaluate to the required data type. The Binding class enables us to format the values
for display through the Format event. We will see how to use this event while binding data to the
Image property of the Picture Box control.

Also bind the rest of the controls as shown below.

Binding baddress = new Binding("Text", m_ds, "PatientInfo.PatientAddress") ;


address.DataBindings.Add ( baddress ) ;

Binding bdname = new Binding ( "Text", m_ds, "PatientInfo.DoctorName" ) ;


dname.DataBindings.Add ( bdname ) ;

Binding bphoto = new Binding ( "Image", m_ds, "PatientInfo.Photograph" ) ;


bphoto.Format += new ConvertEventHandler ( convertpicture ) ;
photo.DataBindings.Add ( bphoto ) ;

Add these statements in the constructor after the call to the InitializeComponent( ) method. Note
that we have added a handler to the Format event. We need to add this handler because the
required type is Image, whereas, the contents of the ‘Photograph’ field resolve to Byte[ ]. The
Format event is raised when the data is transferred from data source to control and when the
data is transferred from control to data source. The event handler convertpicture transforms an
array of bytes into a Bitmap object that can be safely assigned to the Image property of a
PictureBox control. The handler is given below.

void convertpicture ( Object sender, ConvertEventArgs e )


{
Byte[] b = ( Byte[] ) e.Value ;
MemoryStream ms = new MemoryStream( ) ;

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

ms.Write ( b, 0, b.Length ) ;
Bitmap bmp = new Bitmap ( ms ) ;
ms.Close () ;
e.Value = bmp ;
}

The Value property contains the data, the image in our case, read from the data source. We have
first written the chunk of bytes containing the image into a memory stream. This is necessary
because we cannot create a bitmap using the Bitmap class directly from a byte array. The
memory stream object is then passed to the constructor of the Bitmap class and the bitmap
object is assigned as the new contents of the Value property.

The BindingContext property of the Form class returns bindings involved for a particular data
source. However, it does not return an object of the Binding class. Instead it returns a
supervisory object of the BindingManagerBase class. The BindingManagerBase class handles
a specific data source and provides a property called Position that maintains the row index. We
are going to use this property to select the data to be displayed in the controls. We would first
collect the object of the BindingManagerBase class. Write the following statement in the
constructor.

m_bman = BindingContext [ m_ds, "PatientInfo" ] ;

This line selects all the bindings that involve the m_ds data source and ‘PatientInfo’ data member
from the form’s binding context.
As said earlier, we would select the patient’s ID from the list box. The record containing this ID will
be displayed in the controls. For this purpose, we need to change the position in the binding
context using the Position property. Add the handler for the SelectedIndexChanged event and
change the position as shown below.

private void list_SelectedIndexChanged ( object sender, EventArgs e )


{
m_bman.Position = list.SelectedIndex ;
}

When the application is executed, the data at zeroeth position would get displayed in the controls.
For this, set the selected index to 0 in the constructor after collection the binding manager base
object.

list.SelectedIndex = 0 ;

Article – C# - Application Domains

Under Windows it is not possible to access data of one application from another application. This
is because Windows creates process boundaries for each application. The code as well as the
data of an application is stored in its process boundary. Windows provides security by not
allowing one application to enter into the process boundary of another application. Hence data
cannot be shared. In general, communication is not possible across process boundaries making
the application more secured.
Note that using sockets we can communicate between two separate applications/processes. But

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

this communication is purely text based, means we cannot pass integers, floats, etc. through
sockets. Also, we cannot call methods across process boundaries.

If we want to pass the data or call methods across process boundaries without affecting the
security of applications, we need to use the DCOM protocol. This protocol uses a concept called
marshalling to pass the data and unmarshalling to accept the data. But marshalling/unmarshalling
is time consuming and hence is slow. There is a need for a way that would provide both—security
as well as performance.

.NET uses a concept called ‘Application Domain’ using which two separate applications can
safely communicate with each other without affecting the performance. In .NET when an
application is loaded in memory a process is created and within this process an application
domain is created. The application is actually loaded in the application domain. If this application
communicates with another application, .NET loads the other application in a different application
domain. This application domain may belong either to the same process or to a different process.
Thus one process can host multiple application domains. If loaded in the same process then the
communication between the two applications is more efficient because the overheads involved in
inter-application domain communication are less as compared to inter–process communication.
In Remoting the communication happens between two application domains running in same or
different processes on physically same or different machines connected to an intranet or internet.
Following figure demonstrates two applications loaded in different application domains.

Communication between application domains is encapsulated in the AppDomain class. Lets


create a simple application called ‘firstdomain’ that uses the AppDomain class.

static void Main ( string[ ] args )


{
AppDomain a = AppDomain.CurrentDomain ;
Console.WriteLine ( a.FriendlyName ) ;
}

The AppDomain class is used to create and terminate application domains and load and unload
assemblies. The CurrentDomain property holds reference to the current domain. The
FriendlyName property gets the friendly name of this application domain. The friendly name of
the default application domain is the name of the application loaded in the application domain.
This program just extracts the name of the exe running in the current domain.
Now write another program named ‘seconddomain’.

static void Main ( string[ ] args )


{

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

AppDomain sec = AppDomain.CurrentDomain ;


Console.WriteLine ( sec.FriendlyName ) ;

AppDomain first ;
first = AppDomain.CreateDomain ( "mydomain" ) ;
first.ExecuteAssembly ( "firstdomain.exe" ) ;
}

In the second program we have first extracted the name of the EXE running in the current
domain. Then we have created a new domain, loaded and executed another EXE in that domain.
The CreateDomain( ) method of the AppDomain class creates a new application domain called
mydomain. The ExecuteAssembly( ) method executes the specified executable file. The
‘firstdomain.exe’ runs in the newly created domain called mydomain. Before running the second
application we must make sure that we copy the ‘firstdomain.exe’ in the ‘bin’ folder of the current
project.

Now let’s look at a more complex program in which we share data between two applications
running in the same process but different application domains.

Suppose we have a class Stack containing methods to push and pop elements. A program in the
same project uses this class. When compiled, the program gets converted to an EXE. If the
developer of this program wants to make the Stack class residing in an EXE reusable, the
developer needs to expose the class implementation through an interface. To do this the
developer needs to declare an IStack interface containing push( ) and pop( ) methods in a
library project and compile it to a DLL. Then adding the reference of this DLL in the project having
the Stack class the developer needs to implement the IStack interface in the Stack class.

Here is the IStack interface declared in ‘StackLib’ library.

public interface IStack


{
void push ( int item ) ;
int pop( ) ;
}

Design the Stack class and use it in the ‘StackDemo’ project as shown below.

public class Stack : MarshalByRefObject, IStack


{
int [ ] arr = new int [ 10 ] ;
int top ;

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

public Stack( )
{
top = -1 ;
}

public void push ( int item )


{
if ( top >= 9 )
{
Console.WriteLine ( "Stack is Full" ) ;
return ;
}

top += 1 ;
arr [ top ] = item ;
}

public int pop( )


{
if ( top == -1 )
{
Console.WriteLine ( "Stack is Empty" ) ;
return -1 ;
}

int data = arr [ top ] ;


top -= 1 ;
return data ;
}
}

static void Main ( string[ ] args )


{
Stack s = new Stack( ) ;
s.push ( 20 ) ;
s.push ( 5 ) ;
s.push ( 15 ) ;
s.push ( 12 ) ;
s.push ( 6 ) ;
Console.WriteLine ( s.pop( ) ) ;
Console.WriteLine ( s.pop( ) ) ;
Console.WriteLine ( s.pop( ) ) ;
Console.WriteLine ( s.pop( ) ) ;
}

Here the Stack class has been derived from MarshalByRefObject class that allows data
marshalling. Hence, we can now send data from one application domain to another. This class
also implements the IStack interface.

Now we wish to use the Stack class in another EXE. Recall that we cannot create an object of
the Stack class in another EXE because we cannot add a reference of an EXE in another project,
and hence we have no access to this class. So, to use an object of the Stack class in an EXE we
must execute the EXE containing the Stack class in another application domain and then gain
access to the object of this class.

Create another project named ‘seconddemo’ and write the code as shown below.

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

using stacklib ;
using System.Runtime.Remoting ;

static void Main ( string[ ] args )


{
AppDomain a ;
a = AppDomain.CreateDomain ( "mydomain" ) ;
ObjectHandle o ;
o = a.CreateInstance ( "stackdemo”, "stackdemo.Stack" ) ;
IStack s = ( IStack ) o.Unwrap( ) ;
s.push ( 10 ) ;
s.push ( 5 ) ;
s.push ( 3 ) ;
Console.WriteLine ( s.pop( ) ) ;
Console.WriteLine ( s.pop( ) ) ;
Console.WriteLine ( s.pop( ) ) ;
AppDomain.Unload ( a ) ;
}

First of all we would have to copy the ‘stackdemo.exe’ in the ‘bin’ folder of the current project.
Here we have first created a reference of AppDomain class called a and created a new
application domain. Then we have used the CreateInstance( ) method to create an instance of a
class that is passed as the second parameter to this method. The assembly in which the class is
present is passed as the first parameter. The object of the specified class would get created in the
domain mydomain. This method returns the object of type ObjectHandle. This returned object is
nothing but a wrapper around the object of the class Stack. To extract the actual object, we must
unwrap it using the Unwrap( ) method. Here the reference that we need to create to store the
reference of the unwrapped object must be of type Stack. Realize that we cannot create a
reference of the Stack class in this EXE. Hence we have created a reference s of its base class
IStack and stored the reference of the Stack object in it. The IStack reference can be created
here because we can easily add a reference of the DLL, containing the definition of IStack, in the
EXE. This is the reason why we created another DLL for the IStack interface. Now using this
reference we have called methods from the application domain. Next we have unloaded the
application domain using the Unload( ) method.

Article – C# - Grooming the DataGrid Control

Programmers are never satisfied with what is shipped with a development environment. They
always require something else than what is available to create an application using that
environment. For example, instead of normal menus, we may want menus to appear sliding.
Instead of the blue colored menu selection bar, we may want to change it to suit the current skin
of the application window. In short, developers try to customize the available controls to suit their
requirements. If you are thinking of customizing the DataGrid control to give it a different look
then this article will prove helpful to you.

In this article we will change the background and foreground color of the currently selected row in
the DataGrid control. We will also rearrange the sequence of the columns before displaying the
data in the table.

Create a WinForm application and place the DataGrid control on it. Open the Server Explorer
window. Go to the table, which you want to provide as data source. Drag and drop the table on
the DataGrid control. If it requires password to access the data source, a message box will be
popped up to ask you whether you want the password to get displayed in source code or not. Say

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

yes to it otherwise connection string will lack the password and connection to the data source will
not get established. The following references will get added as data members of the Form1 class.

private.SqlCommand sqlSelectCommand1;
private SqlCommand sqlInsertCommand1;
private SqlConnection sqlConnection1;
private SqlDataAdapter sqlDataAdapter1;

The command string for SELECT and INSERT statements as well as the connection string also
get created.

Now right-click on the SqlDataAdapter1 component and select ‘Generate DataSet’ from the pop-
up menu. The ‘Generate DataSet’ dialog box appears. Change the DataSet name to ds1 and
click ‘OK’. This adds a DataSet reference to the component tray.

Add the Load event handler and write the following statement in it.

sqlDataAdapter1.Fill ( ds1 ) ;

The InitializeComponent( ) method contains the code to connect to the data source. Check
whether the connection string is constructed properly and then run the program. You will see the
datagrid control filled with data as shown in the following figure.

The control in our form shows records of the ‘bank’ database. For the field having datatype bit (or
boolean) DataGrid control displays a checkbox. Records having value 1 (or true) in that field
appear checked.

Let us now start the customization work. Firstly, we would arrange the order in which columns
should appear. By default DataGrid shows the columns in order specified in the SQL query. If we
want to change this order we can change the query. However, what if the order of columns is
dependent on an action taken by the user? This can be managed by using the
DataGridTableStyle class. Don’t confuse this class with the table (datasource) displayed in the
DataGrid control. The DataGridTableStyle class represents the grid drawn in the control.

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

Therefore, to customize the appearance of the grid for a DataTable, we can use the
DataGridTableStyle class. To associate the name of the table with a table style the
MappingName property of the DataGridTableStyle class is initialized with the table name i.e. the
name of the data source. Name of our table happens to be ‘account’.

The DataGrid class has a property called TableStyles. It returns a reference to the object of the
GridTableStylesCollection class. An object of the GridTableStylesCollection class holds a
collection of the objects of DataGridTableStyle class. Each object can specify different table
styles.

The DataGridTableStyle class has a property called GridColumnStyles. It returns a reference


to an object of the GridColumnStylesCollection class. This collection holds objects of the
DataGridColumnStyle class. We can customize the appearance of a column through the
DataGridColumnStyle class. To associate a column style with a column in the data table, we
must initialize the MappingName property of the DataGridColumnStyle class with the column
name. We cannot instantiate the DataGridColumnStyle class because it is an abstract class.
Instead we use the derived classes DataGridTextBoxColumn or the DataGridBoolColumn. The
DataGridBoolColumn makes the column look and behave like a check box. This class is useful
when we have a field of type bool in the data source.

We would now write the code to customize the columns, add the column styles in the columns
style collection maintained in the table style object, and then add the table style to the datagrid
control. This code is to be written in the Load event handler.

DataGridTableStyle ts = new DataGridTableStyle( ) ;


ts.MappingName = "account" ;

DataGridBoolColumn bcol = new DataGridBoolColumn( ) ;


bcol.MappingName = "ATM" ;
bcol.Width = 30 ;
bcol.AllowNull = false ;
ts.GridColumnStyles.Add ( bcol ) ;

DataGridTextBoxColumn column = new DataGridTextBoxColumn( ) ;


column.MappingName = "accno" ;
column.HeaderText = "Account No." ;
column.Width = 80 ;
ts.GridColumnStyles.Add ( column ) ;

column = new DataGridTextBoxColumn( ) ;


column.MappingName = "name" ;
column.HeaderText = "Name" ;
column.Width = 110 ;
ts.GridColumnStyles.Add ( column ) ;

column = new DataGridTextBoxColumn( ) ;


column.MappingName = "bal" ;
column.HeaderText = "Balance" ;
column.Width = 110 ;
ts.GridColumnStyles.Add ( column ) ;

dataGrid1.TableStyles.Add ( ts ) ;

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

We have changed the order of columns as ATM, accno, name and bal. Here, we have used the
properties like HeaderText and Width to change the column heading and width of the columns
respectively. The Add( ) method is used to add the column and table style to the respective
collections. Now run the program. You will see the columns arranged in the order set in the table
style.

Next week we will customize the background and foreground color of the selected row.

Article – C# - Grooming the DataGrid Control - II

Continued from last week...

Last week we customized the DataGrid control by rearranging the order of columns and applying
styles to them. We would now see how to change the background and foreground colors of the
cells.

The DataGridTextBoxColumn class is responsible for drawing every cell in the DataGrid control.
The background and foreground brushes are passed to the Paint event handler in this class. So,
to color the cells with desired brushes, we can change the brushes in the Paint event handler.
For this, we must derive a class from the DataGridTextBoxColumn class. We would add an
event to this class that would be fired when a cell is about to be painted. The handler of this event
would receive the current row and current column. Here is the derived class, formatcolumn.

class formatcolumn : DataGridTextBoxColumn


{
public event formateventhandler format ;

protected override void Paint ( Graphics g, Rectangle bounds, CurrencyManager source, int
row, Brush backbrush,
Brush forebrush, Boolean alignToRight )
{
int col = DataGridTableStyle.GridColumnStyles.IndexOf ( this ) ;

formateventargs e = new formateventargs ( row, col ) ;


format ( this, e ) ;

backbrush = e.Backbrush ;
forebrush = e.Forebrush ;

base.Paint ( g, bounds, source, row, backbrush, forebrush, alignToRight ) ;


}
}

The class declares the event named format of type formateventhandler. Declare the
formateventhandler delegate outside the classes as shown below:

public delegate void formateventhandler( object sender, formateventargs e ) ;

This delegate specifies that the handler of the format event would accept two parameters, first
the reference of type object and second reference of type formateventargs. We cannot pass a
reference to the predefined EventArgs class because we have to pass the row and column to the
format event handler. We would see the formateventargs class later.

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

In the formatcolumn class we have overridden the Paint event handler. To this handler, the
brushes along with the current row are passed. We have obtained the current column using the
IndexOf( ) method. After this, we have fired the format event. The format event handler would
initialize the brushes with the desired colors. We have obtained these colors from the
formateventargs class by calling its properties Backbrush and Forebrush. We have then called
the base class’s Paint handler for doing the painting job.

The formateventargs class contains the constructor and few properties. This class is given
below.

public class formateventargs : EventArgs


{
private Brush backbrush, forebrush ;
private int r, c ;

public formateventargs ( int row, int col )


{
Row = row ;
Col = col ;
}
public int Row
{
get
{
return r ;
}
set
{
r = value ;
}
}

public int Col


{
get
{
return c ;
}
set
{
c = value ;
}
}

public Brush Backbrush


{
get
{
return backbrush ;
}
set
{
backbrush = value ;
}

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

public Brush Forebrush


{
get
{
return forebrush ;
}
set
{
forebrush = value ;
}
}
}

Only thing remaining is handling the event. Add the event handler in the Form1 class. The
handler is given below.

private void column_formathandler ( object sender, formateventargs e )


{
if ( e.Row == dataGrid1.CurrentRowIndex )
{
e.Backbrush = Brushes.Aqua ;
e.Forebrush = Brushes.Red ;
}
else
{
e.Backbrush = new SolidBrush ( dataGrid1.BackColor ) ;
e.Forebrush = new SolidBrush ( dataGrid1.ForeColor ) ;
}
}

This handler would get called for every cell of the grid. So, we have checked whether the cell that
is getting painted belongs to the currently selected row.

Now modify the Load event handler as shown below. Here, instead of
DataGridTextBoxColumn, we have created reference of type formatcolumn class. We have
also added the format event to each column added to the control.

private void Form1_Load ( object sender, System.EventArgs e )


{
sqlDataAdapter1.Fill ( ds1 ) ;

DataGridTableStyle ts = new DataGridTableStyle( ) ;


ts.MappingName = "account" ;

DataGridBoolColumn bcol = new DataGridBoolColumn( ) ;


bcol.MappingName = "ATM" ;
bcol.HeaderText = "" ;
bcol.Width = 30 ;
bcol.AllowNull = false ;
ts.GridColumnStyles.Add ( bcol ) ;

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

formatcolumn column = new formatcolumn( ) ;


column.MappingName = "accno" ;
column.HeaderText = "Account No." ;
column.Width = 80 ;
column.format += new formateventhandler ( column_formathandler ) ;
ts.GridColumnStyles.Add ( column ) ;

column = new formatcolumn( ) ;


column.MappingName = "name" ;
column.HeaderText = "Name" ;
column.Width = 110 ;
column.format += new formateventhandler ( column_formathandler ) ;
ts.GridColumnStyles.Add ( column ) ;

column = new formatcolumn( ) ;


column.MappingName = "bal" ;
column.HeaderText = "Balance" ;
column.Width = 110 ;
column.format += new formateventhandler ( column_formathandler ) ;
ts.GridColumnStyles.Add ( column ) ;

dataGrid1.TableStyles.Add ( ts ) ;
}

Execute the program and select a row. The selected row would appear as shown in the following
figure.

Article – C# - Transformation in GDI+ - I

As compared to GDI, GDI+ provides greater support for graphics, images and transformation.
GDI+ allows following operations to be performed.

Translation: On translating an object the size of the object remains fixed but it moves along any
one of the axes along which the translation takes place. Moving object 10 units in x direction is an
example of translation transformation.

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

Rotation: On rotating an object, the object moves about one of the axes.

Scaling: On scaling an object, its size gets increased or decreased but the shape does not
change.

Shearing: On shearing an object, it moves in some direction but its base remains fixed.

Transformations are always applied using matrices. It is a two-step process. The steps involved
are:

(a) Creating a transformation matrix and coordinate matrix.


(b) Multiplying the coordinate matrix with transformation matrix.

Translation Transformation

Let us understand this form of transformation with the help of an example.

We plan to translate a triangle shown in this figure by three units in x direction and two units in y
direction. For doing this we need to change all the three coordinates of the triangle. The new
coordinates can be obtained by multiplying the transformation matrix with the coordinate matrix.
In the transformation matrix the elements 3 and 2 are the units by which we wish to translate the
shape in the x and y directions respectively. The coordinate matrix has three elements. The first
element consists of the x coordinate of the vertex, which is to be transformed. The second
element consists of y coordinate of the vertex and the last element consists of the z coordinate of
the vertex. Hence the first and the second elements of the coordinate matrix would be 2, 2
respectively and as a triangle does not have any z order, the last element of the coordinate matrix
would contain 1. After the multiplication is performed the coordinates (2, 2) would get transformed
into (5, 4) respectively.

Rotation Transformation

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

Suppose we want to rotate the triangle shown in the above figure by 90 degrees. To do so, we
need to replace the transformation matrix angle A by 90 degrees. The coordinate matrix would
contain the coordinates of the triangle to be transformed. The figure shows the transformation of
only one of the coordinates of the triangle i.e. (2, 4). As the triangle does not have any z order the
third element of the coordinate matrix would be 1. The resultant matrix shows that the coordinate
(2, 4) has changed to (-4, 2). Similarly we need to transform other two coordinates of the triangle.

Scaling Transformation

Following figure shows the transformation matrix for scaling.

Suppose the triangle is to be scaled by two units in x direction and two units in y direction. Hence
sx and sy in the transformation matrix would be two units each. The coordinate matrix would
contain the particular coordinate of the triangle to be transformed, which in our case happens to
be (4, 1). On multiplying the coordinate matrix with the transformation matrix we get the resultant
matrix which shows that the coordinate (4, 1) has been transformed into (8, 2). The effect of

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

scaling is that the figure either enlarges or reduces in size.

Shearing Transformation

The following figure shows the shearing transformation

Suppose the triangle is to be sheared two units in x direction only. Hence sx in the transformation
matrix would be 2 whereas sy would be 0. The coordinate matrix would contain the particular
coordinate of the triangle to be transformed, which in our case happens to be (1, 4). On
multiplying the coordinate matrix with the transformation matrix we get the resultant matrix, which
shows that the coordinate (1, 4) has been transformed into (9, 4). On performing similar shearing
operation on all other coordinates we would get the resultant triangle as shown in the figure.

We would see how to perform all these transformations programmatically in the next article.

Article – C# - Transformation In GDI+ - II

In the last article we discussed various forms of transformations. We would now see how to
perform these transformations programmatically. Look at the following Paint event handler.

private void Form1_Paint ( object sender, PaintEventArgs e )


{
Graphics g = e.Graphics ;
Image myimg = Image.FromFile ( "C:\\palace.jpg" ) ;
Matrix mymat = new Matrix( ) ;
mymat.Scale ( -1, 1 ) ;
mymat.Translate ( -350, 0 ) ;
g.Transform = mymat ;
g.DrawImage ( myimg, 50, 50 ) ;
g.ResetTransform( ) ;
}

This code creates a mirror image. Here we have used a Static method FromFile( ) of the Image
class, which returns a reference to the image, which we have collected in myimg. Next in order to
create a transformation matrix we have first created an object of the Matrix class. Since the

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

Matrix class is declared in the System.Drawing.Drawing2D namespace, we must declare this


namespace in our program. We have scaled the matrix by passing a –1 as the first parameter to
the Scale( ) method. Due to this all the x coordinates would be multiplied by –1. After multiplying
this matrix with the coordinates of the image the resultant image would be the mirror image of the
original. When we scale the coordinates of an image by multiplying them with –1 the resulting
coordinates become negative. Hence they would not be visible as top left corner of the form is (0,
0). To bring the image back in the form we have to translate it by some x and y values. Next we
have assigned this resultant transformation matrix to the Transform property of the Graphics
object. There onwards everything that gets drawn would be multiplied with the transformation
matrix. For drawing the image we have used the DrawImage( ) method.

Next, we would create an application that would display the string “KICIT” and its shadow on a
WinForm. In this program we shall draw the shadow of the text before drawing the text, so that
the text overlaps the shadow making the shadow appear as if it is behind the text. We shall draw
the shadow using the same font as the original text and shall use gray color for it. The shadow
size would then be required to keep half the size of the original text and also to be sheared in the
x direction.

private void Form1_Paint ( object sender, PaintEventArgs e )


{
Graphics g = e.Graphics ;

Matrix mymat = new Matrix( ) ;


mymat.Shear ( -1.4f, 0f ) ;
mymat.Scale ( 1, 0.5f ) ;
mymat.Translate ( 236, 170 ) ;

g.Transform = mymat ;

Font myfont = new Font ( "Times New Roman", 100 ) ;


SolidBrush mybrush = new SolidBrush ( Color.Gray ) ;
g.DrawString ( "K", myfont, mybrush, 50, 50 ) ;
g.DrawString ( "I", myfont, mybrush, 150, 50 ) ;
g.DrawString ( "C", myfont, mybrush, 200, 50 ) ;
g.DrawString ( "I", myfont, mybrush, 300, 50 ) ;
g.DrawString ( "T", myfont, mybrush, 350, 50 ) ;
g.ResetTransform( ) ;

mybrush.Color = Color.DarkMagenta ;
g.DrawString ( "K", myfont, mybrush, 50, 50 ) ;

mybrush.Color = Color.FromArgb ( 150, 0, 255, 255 ) ;


g.DrawString ( "I", myfont, mybrush, 150, 50 ) ;

LinearGradientBrush lgb = new LinearGradientBrush ( new Point ( 200, 50 ), new Point ( 350,
200 ),Color.Brown, Color.Yellow ) ;
g.DrawString ( "C", myfont, lgb, 200, 50 ) ;

HatchBrush hb = new HatchBrush ( HatchStyle.DiagonalCross, Color.Blue, Color.Red ) ;


g.DrawString ( "I", myfont, hb, 300, 50 ) ;

Image myimg = Image.FromFile ( @"C:\test.bmp" ) ;

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

TextureBrush tb = new TextureBrush ( myimg ) ;


g.DrawString ( "T", myfont, tb, 350, 50 ) ;
}

To create a transformation matrix we have firstly created an object of the Matrix class. This object
represents an identity matrix of size 3 x 3. We intend to perform shearing, scaling and translation
transformations. For this we have called the methods Shear( ), Scale( ) and Translate( ) using
the mymat object. These methods manipulate the object by doing matrix multiplication as
discussed earlier. At the end of these calls, mymat object represents the transformation matrix.
Next, we have set the Transform property of the Graphics class object g to mymat object. Now
whenever a shape would be drawn, the corresponding shape’s coordinate matrix would get
multiplied with the transformation matrix stored in mymat. Next we have selected a SolidBrush
of gray color and used the DrawString( ) method of the Graphics class to display the string. We
have called ResetTransfrom( ) method that resets the world transformation matrix of this
Graphics object to the identity matrix. The identity matrix represents a transformation with no
scaling, rotation, or translation.

To display “K” we have used a solid brush of dark magenta color. To display “I” we have used a
transparent brush. A brush can be made transparent by using the FromArgb( ) method and
passing an alpha component as its first parameter. The alpha component specifies how opaque
or transparent a color should be. The alpha value ranges from 0 (fully transparent) to 255 (fully
opaque). The default value is 255 and hence if we do not pass any value the color created is
always opaque. In our program we have passed 150 as the first parameter to the FromArgb( )
method. This results in a semi-transparent color. The string “I” gets drawn with semi-transparent
blue color. Next we have displayed “C” using a linear gradient brush. Here the y coordinate of the
second point passed to the constructor of the LinearGradientBrush class does not match with
the y coordinate of the first point and hence the gradient fill is not horizontal. The “I” is displayed
using a hatch brush and lastly to display “T”, we have used a texture brush. To the constructor of
the TextureBrush class a reference to an image, which is to be filled, is passed. We have used
the Static method FromFile( ) of the Image class to load the image. If you run the program, you
will see the string “KICIT” written as shown below.

Article – C# - The Timezone Application - I

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

We have started the timezone application in the last article. Just to revise, we have drawn two
lines, intersecting each other at the cursor position.

Add the following data members to the Form1 class.

Point hstart, hend, vstart, vend ;


Image img ;
Label l ;

The hstart and hend objects would contain starting and ending coordinates of the horizontal line.
The vstart and vend objects would contain starting and ending coordinates of the vertical line.
The Image object would be used to load and draw the world map image. The label would be
popped up to show the day of week, time and city name.
Add the Load event handler. Add the initialization code as shown below.

private void Form1_Load ( object sender, System.EventArgs e )


{
img = Image.FromFile ( "World.gif" ) ;
hstart = new Point ( 0, ClientSize.Height / 2 ) ;
hend = new Point ( ClientSize.Width, ClientSize.Height / 2 ) ;
vstart = new Point ( ClientSize.Width / 2, 0 ) ;
vend = new Point ( ClientSize.Width / 2, ClientSize.Height ) ;
}

Here, we have loaded the ‘world.gif’ file containing the map image. The Point objects are
initialized with the proper values.
Add the Paint event handler wherein we would draw the image on the form. We would also draw
the lines using the Point objects initialized just now.

private void Form1_Paint ( object sender, PaintEventArgs e )


{
Graphics g = e.Graphics ;
g.DrawImage ( img, 0, 0, img.Width, img.Height ) ;

Pen p = new Pen ( Brushes.Red ) ;


g.DrawLine ( p, hstart, hend ) ;
g.DrawLine ( p, vstart, vend ) ;
}

Run the program, you would see the output as shown in the following figure.

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

You must have noticed the grayed maximized box of the form. We have set the MaximizeBox
property of the form to false so that the size of the form won’t change. We have hidden the cursor
by adding the following statement to the Load event handler

Cursor.Dispose( ) ;

The lines should move as the mouse moves. We have already written the code to draw new lines
and erase previous ones in the Form1_MouseMove( ) handler. Update that code as shown
below.

private void Form1_MouseMove ( object sender, MouseEventArgs e )


{
Graphics g = CreateGraphics( ) ;
hend.Y = hstart.Y = e.Y ;
vend.X = vstart.X = e.X ;
g.DrawImage ( img, 0, 0, img.Width, img.Height ) ;
Pen p = new Pen ( Brushes.Red ) ;
g.DrawLine ( p, hstart, hend ) ;
g.DrawLine ( p, vstart, vend ) ;
}

Here, we have updated the coordinates stored in the Point objects according to the mouse
position and drawn lines at new position.
We must keep checking the mouse position. If the mouse is placed over a city that is present in
our city database, we must display the label carrying day, time and city. In our program the
application data is the name of the city, its coordinates and the time at that place with respect to
the Indian Standard Time. To keep things simple we have stored this data in an array of objects.
The objects are of type location. location is a user-defined class. We would first declare this class.

class location
{
public int hours, minutes ;
public string city ;
public int x, y ;

public location ( int h, int m, String c, int xx, int yy )


{
hours = h ;
minutes = m ;
city = c ;
x = xx ;
y = yy ;
}
}

The location class contains data members to hold hours, minutes, city name and x-y coordinates
of the city on the map. The data members are initialized through constructor.
Populate the array in the Form1 class as shown below. This is only a part of the array.

location[ ] loc =
{

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

new location ( 0, 0, "NewDelhi", 245, 90 ),


new location ( 0, 0, "Calcutta", 254, 99 ),
new location ( 0, 0, "Mumbai", 240, 107),
new location ( 0, 0, "Nagpur", 245, 100),
new location ( 0, 0,"Chennai", 245, 110),
new location ( -5, -30, "Lisbon", 160, 79),
new location ( -4, -30, "Madrid", 165, 74),
new location ( -3, -30, "Athens", 192, 84),
new location ( -3, -30, "Cairo", 202, 91),



};

Article – C# - The Timezone Application - I

Now comes the real part.

private void Form1_MouseMove ( object sender, MouseEventArgs e )


{
// Previous code

int i = search ( new Point ( e.X, e.Y ) ) ;


Rectangle m_rect = new Rectangle( ) ;
if ( i != -1 )
{
m_rect = this.ClientRectangle ;
Point dpt = new Point ( 0, 0 ) ;
if ( e.X + 150 < m_rect.Width )
dpt.X = e.X + 5 ;
else
dpt.X = e.X - 155 ;
if ( e.Y + 20 < m_rect.Height )
dpt.Y = e.Y + 5 ;
else
dpt.Y = e.Y - 20 ;
string str = calculate ( i ) ;

l.Left = dpt.X ;
l.Top = dpt.Y ;
l.Size = new Size ( 150, 20 ) ;
l.Text = str ;
l.Visible = true ;
}
else
l.Visible = false ;
}

We have called the search( ) method that returns the index of the array element whose
coordinates match with the coordinates of the current mouse position. We have then calculated
the suitable place where the label of size 150 x 20 can be displayed. The left-top position is
stored in the dpt object. Next we have called the calculate( ) method. This method customizes
the string containing information of the city and returns the same.
Once we have the information, what remains is to display this information on the label. We must
first create the label. For this, add the following code in the Load event handler.

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

l = new Label( ) ;
l.Visible = false ;
Controls.Add ( l ) ;

The following statements specify the position, size and text of the label. The label would be
invisible initially. We have to make it visible using the Visible property.

l.Left = dpt.X ;
l.Top = dpt.Y ;
l.Size = new Size ( 150, 20 ) ;
l.Text = str ;
l.Visible = true ;

If The mouse is positioned at some obscure place in the world whose entry is not present in the
array the search( ) method returns a value -1. In such a case the label is hidden by setting the
Visible property to false.
Lets now look at the two helper functions search( ) and calculate( ). They are given below.

int search ( Point p )


{
Rectangle r = new Rectangle ( p.X , p.Y , 5, 5 ) ;
Point pt ;
for ( int i = 0 ; i < loc.Length ; i++ )
{
pt = new Point ( loc [ i ].x, loc [ i ].y ) ;
if ( r.Contains ( pt ) )
return i ;
}
return -1 ;
}

To this method we have passed the current mouse position. We have run a for loop to see
whether coordinates of any city fall within the specified area. If they do, we have returned the
index of the element.
This index is then passed to the calculate( ) method.

string calculate ( int i )


{
int m_hour = loc [ i ].hours ;
int m_minute = loc [ i ].minutes ;

DateTime t = DateTime.Now ;

t = t.AddHours ( m_hour ) ;
t = t.AddMinutes ( m_minute ) ;
string week_day = t.DayOfWeek.ToString( ) ;

string str = week_day + " " + t.Hour + ":" + t.Minute + " " + loc [ i ].city ;
return str ;
}

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

In this method, we have read the hour and minutes of the specified array element. Remember
that these hour and minute values specify the time with respect to the Indian Standard Time. We
have added this time to the current time to get the exact time at the city. Lastly, we have obtained
the day of week and constructed the string with all the information we have. This string is returned
back to the MouseMove event handler.
Run the program and move the mouse on the form. You will get the pop-ups as shown in the
following snap shot.

Article – C# - E-Mail Enabled Windows Application

Want to send e-mail from a .NET Framework application? You could do it the hard way by using
sockets to establish a connection to a mail server and then transmit a mail message using Simple
Mail Transfer Protocol (SMPT). Or you could do it the easy way and rely on classes in the
System.Web.Mail namespace. System.Web.Mail provides a simple managed interface to
SMTP. The core classes are MailMessage, which helps preparing an e-mail message;
MailAttachment, which helps sending attachments; and SmtpMail, which places a friendly
wrapper around the host system’s SMTP mail service. These classes construct and send
messages using the CDOSYS (Collaboration Data Objects for Windows 2000) message
component. To send the mail either the SMTP mail service of Microsoft Windows 2000 or the
specified SMTP server is used. In our application we would use ‘localhost’ as the SMTP server.

Although mail facility would be required mainly by Web applications, even the WinForm
applications need to send mails. TODO

We would create a WinForm application that is capable of sending mail and/or an attachment.
Design the form as shown in the following screen capture.

We have placed several labels and text boxes along with two buttons. The textboxes are
respectively given names as txtto, txtfrom, txtcc, txtbcc, txtsubject, txtattach and txtbody.
The buttons are named as butsend and butattach respectively.

Declare a reference msg to the MailMessage class as data member of the Form1 class and
initialize it in the constructor as shown below.

msg = new MailMessage( ) ;

Add the Click event handler for both the buttons. These handlers are given below.

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

private void butattach_Click(object sender, System.EventArgs e)


{
if ( filedlg.ShowDialog( ) == DialogResult.OK )
{
MailAttachment ma = new MailAttachment ( filedlg.FileName ) ;
txtattach.Text = filedlg.FileName ;
msg.Attachments.Add ( ma ) ;
}
}

To enable the user to select a file for attaching to the mail, we have displayed the OpenFile
dialog with name filedlg. We have passed the selected file name and path to the constructor of
the MailAttachment class. The attachment represented by an object of the MailAttachment
class is then added to the Attachments collection of the MailMessage object.

After attaching the file, click the ‘Send’ button. In the ‘Send’ button handler we have filled various
properties of the MailMessage class with respective values. Here, mentioning To and From
properties are mandatory.

private void butsend_Click ( object sender, System.EventArgs e )


{
if ( txtto.Text != null )
msg.To = txtto.Text ;
else
return ;
if ( txtfrom.Text != null )
msg.From = txtfrom.Text ;
else
return ;
msg.Cc = txtcc.Text ;
msg.Bcc = txtbcc.Text ;
msg.Subject = txtsubject.Text ;
msg.Body = txtbody.Text ;

try
{
SmtpMail.SmtpServer = "localhost" ;
SmtpMail.Send ( msg ) ;
}
catch ( Exception ex )
{
MessageBox.Show ( "Error in sending mail" ) ;
}
}

The SmtpServer property specifies the SMTP server through which mail will be sent. If the
SmtpServer Property is not set, mail is by default queued on a Windows 2000 system. We can
check this mail in the ‘C:\Inetpub\mailroot\Queue’ folder.

Add reference to the System.Web.Mail namespace at the beginning of the program. Also add the
reference to the ‘System.Web.dll’ in the Solution Explorer. Run the program and enjoy mailing.

If the application throws an exception when you click the ‘Send’ Mail button, make sure your
machine’s SMTP service is running. You can do that in the IIS configuration manager or in the
‘Administrative Tools | Services’ Control Panel applet. Second, make sure the SMTP service is

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

configured to allow relaying from localhost. To do that, open the IIS configuration manager from
the Administrative Tools, right-click ‘Default SMTP Virtual Server’, select ‘Properties’, click the
‘Access’ tab, click the ‘Relay’ button, select ‘Only List Below’, and use the Add button to add
127.0.0.1 to the list of computers allowed to relay

Article – C# Using the FileSystemWatcher Component

In this article we would walk through the process of using the FileSystemWatcher component and
watching the changes made to a subfolder/files of a selected folder.

The FileSystemWatcher component can keep track of creation, deletion, changing and renaming
of a file/folder. It conveys the application about changes done to the file system by throwing
events. It throws the Created, Deleted, Changed and Renamed events respectively. The name
and path of the file/folder being changed is also made available in the event handlers.

The FileSystemWatcher component can watch files on a local computer, a network drive, or a
remote computer. We can specify which files to watch by setting the appropriate value in the Filter
property. If we wish to watch all the files we must set the Filter property to an empty string (“”). To
watch a specific file, we must assign that file name to the Filter property. We can also use
wildcards to specify certain type of file. For example, to watch for changes in EXE files, we can
set the Filter property to “*.exe”.

The component has a property called NotifyFilter that can be used to specify the types of
changes viz. changes in attribute, last write date and time, size, etc.

Having this much of knowledge about FileSystemWatcher component in hand, we can now use
the component in our application.

We would create an application that uses the FileSystemWatcher control to keep watch on the
folder selected by the user. We would watch whether a file/folder is created, changed or deleted.

Create a WinForm application and put the controls on the form as shown in following figure.

We have added three list boxes to list the files/folders being created, changed or deleted. The
‘Watch Folder’ button allows user to select a folder to watch. The path of the selected folder gets
displayed on the label placed next to the ‘Watch Folder’ button. The ‘Clear’ button allows to delete
the items listed in the list box having input focus.

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

In addition to these controls, add the FolderBrowserDialog control from the ‘Windows Forms’ tab
and FileSystemWatcher component from the ‘Components’ tab of the ToolBox. The controls, their
names and event handlers are given in the following table.

Control Name Handler


‘Created’ list box listcreate -
‘Changed’ list box listchange -
‘Deleted’ list boxlistdelete -
‘Watch Folder’ button butwatch butwatch_Click
‘Clear’ button butclear butclear_Click
FileSystemWatcher watcher -
FolderBrowserDialog browser -

Add handlers for the Created, Deleted and Changed events. Also Set the
IncludeSubdirectories property of the FileSystemWatcher component to true.

When the application is run, the user has to first select a folder to watch. He can do so by clicking
the ‘Watch Folder’ button. We have displayed the ‘Browse For Folder’ standard dialog box in
which user can select the folder. The dialog is displayed by calling the ShowDialog( ) method as
shown below.

private void butwatch_Click ( object sender, System.EventArgs e )


{
if ( browser.ShowDialog( ) == DialogResult.OK )
{
watcher.Path = browser.SelectedPath ;
label1.Text = browser.SelectedPath ;
}
}

We have specified the folder to watch by setting the Path property of the FileSystemWatcher
class to the path of selected folder. The path of selected folder is retrieved from the SelectedPath
property of the FolderBrowserDialog class. We have displayed the path on the label.

The handlers added for the FileSystemWatcher events are given below.

private void watcher_Changed ( object sender,System.IO.FileSystemEventArgs e )


{
listchange.Items.Add ( e.FullPath ) ;
}

private void watcher_Created ( object sender,System.IO.FileSystemEventArgs e )


{
listcreate.Items.Add ( e.FullPath ) ;
}

private void watcher_Deleted ( object sender, System.IO.FileSystemEventArgs e )


{
listdelete.Items.Add ( e.FullPath ) ;
}

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

In these handlers we have only added the full path of the file/folder being changed, created or
deleted in the respective list boxes. To clear a list box, the user has to select an item in that list
box and click the ‘Clear’ button. The handler for the ‘Clear’ button is given below.

private void butclear_Click ( object sender, System.EventArgs e )


{
if ( listcreate.SelectedIndex != -1 )
listcreate.Items.Clear( ) ;
else
{
if ( listchange.SelectedIndex != -1 )
listchange.Items.Clear( ) ;
else
if ( listdelete.SelectedIndex != -1 )
listdelete.Items.Clear( ) ;
}
}

The SelectedIndex property returns –1 if no item is currently selected. If any item is selected, the
condition becomes true and the list box gets cleared.

Following figure shows our application at work. The list boxes seem to have trapped few files
being changed.

Article – C# - Using The Splitter Control

In earlier version of Visual Studio, we used to create splitter windows by calling methods of an
MFC class. The main application window actually used to get split in panes. Each pane
represented a separate view window. .NET’s concept of splitting windows is different. .NET
provides a Splitter control, which is used to resize docked controls at run time. It does not actually
splits a window. The control to be resized must be just before the splitter control in z-order.

This article shows how to use the Splitter control in a WinForm application. We intend to display a
form window as shown in the following snap shot.

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

The blue horizontal bar is a label control. We have changed its BackColor, ForeColor and Font
properties. The control placed at the left hand side is the ListBox control. The control placed on
the right hand side is the ListView control. The program is to list the currently running processes
in the list box. If a process is selected its information is displayed in the list view control. Here, our
aim is to show how to use the Splitter control. Our stress is not on browsing and retrieving
information of processes.

When we place the Splitter control on a container, it divides the entire container in two parts—left
and right (or top and bottom if placed horizontally). But, we don’t want to show the vertical bar of
the Splitter control on the label. We want that the effect of splitter should be felt only on the
remaining part of the form. For this, we have placed a Panel on the form so as to cover the
remaining part of the form. This is shown in the following snap shot.

Now, place the ListBox and change its Dock property to Left. Name the control as list. Drag the
Splitter control on the form. It will get docked to the left side indicating that it has to resize the
control placed on the left. Run the program and place the cursor on the splitter bar. When the
cursor changes, drag it to left or right. You would see the list box resizing. We want to place a
ListView control as well as button on the right side of the splitter. If user moves the splitter, both
the controls should be relocated properly. For this, we have again placed a Panel covering the
right side of the form and placed the ListView and Button controls on it. Name the Panel control
as panel, ListView control as listview and Button control as kill. Clicking this button would kill the
process selected from the list box. Again note that our aim is to show you how to relocate the
multiple controls if Splitter control is moved, not to kill the process. Lastly, add the Process
component from the ‘Components’ tab on ToolBox and name it process.
The designing part is over, lets move on to the coding part. Firstly, add the Load event handler.
The handler is shown below.

private void Form1_Load ( object sender, System.EventArgs e )


{

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

Process[ ] parr = Process.GetProcesses( ) ;


foreach ( Process p in parr )
list.Items.Add ( p.ProcessName ) ;
}

Here, we have browsed the processes and listed them in the list box
.
Now add the Click event handler for the button. In this handler we have checked whether any
process is selected. If it is, then we have closed the process using the kill( ) method.

private void kill_Click ( object sender, System.EventArgs e )


{
if ( list.SelectedItem == null )
return ;

Process[ ] p = Process.GetProcessesByName (
list.SelectedItem.ToString( ) ) ;
p [ 0 ].Kill( ) ;
list.Items.Remove ( list.SelectedItem ) ;
list.SelectedIndex = -1 ;
listview.Items.Clear( ) ;
}

After the process is closed, we have deleted the process name from the list box, set the selected
index to –1 and cleared the list view control. When the user selects a process, its information is
displayed in the ListView control. The code to fill the ListView control is written in the
SelectedIndexChanged event handler.

private void list_SelectedIndexChanged ( object sender, EventArgs e )


{
if ( list.SelectedIndex != -1 )
{
listview.Items.Clear( ) ;
Process[ ] p = Process.GetProcessesByName
( list.SelectedItem.ToString( ) ) ;
listview.Items.Add ( p [ 0 ].BasePriority.ToString( ) ) ;

listview.Items [ 0 ].SubItems.Add ( p [ 0 ].Id.ToString( ) ) ;


listview.Items [ 0 ].SubItems.Add ( p [ 0 ].StartTime.ToShortTimeString( ) ) ;
listview.Items [ 0 ].SubItems.Add ( ( p [ 0 ].WorkingSet / 1024 ).ToString( ) ) ;
}
}

Here, firstly we have checked whether the handler has got called because of the change in
selected index in the kill_Click( ) event handler. Then we have used various properties of the
Process class to obtain information of the process.

Moving the splitter would resize the list control, but it would not change the width of the Panel
control hosting the ListView and button. We have to do it ourselves.

Add a handler for the SplitterMoved event for Splitter control and adjust the size and left
coordinate of the Panel control as given below.

private void splitter_SplitterMoved ( object sender, SplitterEventArgs e )


{

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

panel.Width = Width - e.X ;


panel.Left = e.X ;
}

Run the program. The form after moving the splitter to the right would look as given below.

Article – C# - DirectX 3-D Basics

DirectX is immensely powerful library that supports multimedia programming. The new version of
this library, known as DirectX 9.0 provides multimedia functionality for managed applications.
DirectX 9.0 supports managed languages like C#, Visual Basic.NET, VC++.NET and JScript.NET.
Components

DirectX 9.0 for Managed Code provides following components

Direct3D – Used for 3-D graphics programming.

DirectDraw – Enables direct access to video memory, specially used for high-speed rendering.

DirectInput – Used for programming with various input devices.

DirectPlay – Used for creating network enabled multiplayer games.

DirectSound – Used for capturing sounds from input devices and playing sound through
playback devices.

Audio Video Playback – Used for working with audio-video files.

Direct3D Concepts

We will start our journey through DirectX 9.0 by understanding the terms and concepts involved in
it.

Direct3D uses a left-handed cartesion coordinate system. The values on the x-axis increase from
left to right. The values on the y-axis increase from bottom to top and the values on the z-axis
increase from back to front. This is shown in following Figure.

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

Consider your left hand with the palm up as shown in the above figure. Then the thumb would
represent the z-direction, which is traveling away from the body.

In the left handed coordinate system we can position 3D objects in one of the three different types
of space coordinates.

Model Space: Suppose we are drawing different 3D entities like a cube, a sphere, a pyramid etc.
Each such object can be called a model. In the model space each such model has a different
origin.

World Space: In the world space there is a fixed origin. The world transformation matrix changes
coordinates from model space, where vertices are defined relative to a model's local origin to
world space where vertices are defined relative to an origin common to all the objects in a scene.
In essence, the world transformation places a model into the world and hence its name.

Camera Space (View Space): This view of the world places the viewer (user) at the origin and
faces him or her in the direction of the positive z-axis. The view matrix is used to transform
vertices from the world space to the Camera space. Above figure and following two figures
depicts these three spaces.

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

Let us now take an example and combine these three spaces together. If we want to spin two
cubes the first thing that we need to do is create the tow cubes using the model coordinates. In
the above figure for depicting the model space the two cubes have their own coordinate separate
coordinate systems. We have placed both the cubes at origin in their respective coordinate
systems. Then using the world transformation matrix we place the cubes into the world space.
The origin of the model space and world space may be same or different. (In the above example
the origin of the model space and the camera space are the same). Then we have translated the
cube 2 in the world space using transformations because had we done that the two cubes would
have got overlapped. Note that the camera is placed at (-200,100) in the world space. In the
world space to rotate scale and translate the cube various transformation matrices are used. Next
to look at the cube we have to indicate the position of the eye/camera in the world space. When
we do so the origin of the world space is mapped to the eye position (Camera space origin). Due
to this the camera or the eye is placed at the origin and the two cubes are reoriented with respect
to the camera. Now if we display the cubes on the screen they would hardly appear like real
cubes. To make the cubes appear more realistic we need to make some more effort.

There are two facts involved when a human eye sees an object

(a) A human eye sees what falls in the conical volume as shown in following figure.

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

(b) That part of the object that is nearer to the eye appears bigger than the part that is farther
away from it. This way of looking at an object is known as perspective projection.

Let us now see how Direct3D uses these facts to generate realistic shapes. Instead of using a
cone Direct3D uses a close approximation of it — a pyramid — to represent the viewing volume.
In principle we can see an object which is present on any distance, even at infinity. But in reality
we can see an object present only upto a particular distance. Hence instead of a pyramid of
infinite length we need to use a frustrum of a pyramid to represent a viewing volume. This is
shown in the following figure.

A front and back clipping plane intersects the pyramid. The volume within the pyramid between
the front and back clipping planes is the viewing frustum. Objects are visible only when they are
in this volume. The viewing frustum is defined by fov (field of view) and by the distances of the
front and back clipping planes, specified in z-coordinates. Once the viewing volume is specified
we need to create a projection matrix which would apply the perspective projection to the
coordinates of the cube. These modified coordinates are then used to render the shape on the
screen (2D-plane). While actually rendering shapes using Direct3D it relieves us of the burden of
forming the projection matrix. we need to only specify fov and the distances of the front and back
plane from the eye. The entire process is illustrated in following figure.

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

Transformations

There are three basic transformations that can be applied to any 3D objects. These are
translation, rotation and scaling. These transformations are discussed below. The Translation
transformation involves movement of the object in the x, y, or z direction. When we move the
object in these directions the coordinates of the object at the new position would be different from
the original coordinates. We can calculate the new coordinates using simple equations. However,
from the point of view of programming convenience if we store the coordinates in one matrix and
the distance by which the object is being translated ( in x, y, and z direction ) in another and carry
out simple matrix multiplication then the resultant matrix would contain the new set of
coordinates. Similar matrix operations can be performed on Rotation and Scaling operations.

1) Translation

If x, y, and z are the coordinates of a point which is to be translated by a distance Tx, Ty and Tz,
then the matrix multiplication that would be carried out is as under:

Here x', y' and z' are the new coordinates of the point.

2) Rotation

This transformation involves rotation of an object around x, y or z axis.

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

For example, the following transformation rotates the point (x, y, z) around the x-axis, producing a
new point (x', y', z').

The following transformation rotates the point around the y-axis

The following transformation rotates the point around the z-axis.

3) Scaling

The scaling transformation involves increasing or decreasing the size of an object.

The following transformation scales the point (x, y, z) by values Sx, Sy and Sz in the x, y, and z
directions to a new point (x', y', z').

Other than programming convenience using matrices for performing transformations offers one
more advantage. We can combine the effects of two or more transformation matrices by
multiplying the matrices representing these transformations. This means that, to rotate a object
and then translate it to some location, we don't need to apply two multiplication's. Instead, we can
multiply the rotation and translation matrices to produce a composite matrix that contains effects
of rotation and translation. This resultant matrix is then multiplied with the coordinate matrix to
yield new coordinates.

Direct3D provides us methods to set up all the matrices for translation, rotation and scaling as
well as it provides a method that provides a matrix that represents the cumulative effects of all the

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

applied transformations. Thus Direct3D helps the user to concentrate on the logical aspect of the
game relieving him from the burden of performing complex mathematical operations.

3D Objects

Let us have a look at how a simple cube is formed in 3D. Before building the cube lets take a look
at the basic 3D primitives which serve as the building blocks to create a cube and more complex
objects. A 3D primitive is a collection of vertices (points in 3D space identified by x, y and z) that
form any 3D entity. Often, 3D primitives are polygons. A polygon is a closed 3D figure drawn by
connecting at least three vertices. The simplest polygon is a triangle. Direct3D uses triangles to
compose most of its polygons because all three vertices in a triangle are guaranteed to be
coplanar. If three points are connected they always lie in the same plane. Consider a pyramid. It
has four points and when they are connected all the three triangles do not lie in the same plane
i.e. the vertices are non-coplanar. Rendering of non-coplanar vertices is inefficient. Hence every
3D object be it a pyramid or a sphere, is built out of triangles due to their coplanar nature. Below
is a sphere that is built from triangles.

Two triangles are used to create each face of the cube. A cube has a total six faces i.e. 12 such
triangles are used to compose the complete cube. This is shown in following figure.

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

System Management Using WMI...

WMI (Windows Management Instrumentation) was previously available as a COM based API that
was obviously complicated to use. .NET has provided an object-oriented, managed wrapper
around this API and made the usage of WMI easy. .NET has provided a separate namespaces
called System.Management and System.Management.Instrumentation to enable our
application to browse and monitor processes, events, etc. Using the power of WMI in conjunction
with .NET we can create a system utility like SPY++.

The new Modifier...

We can use the new modifier for a method in the derived class that has the same signature
(prototype declaration) as the base class method. Using the new modifier we can declare
that a method is not an override of the base class method, but it is the new method that
belongs to this class. Declaring the method as new hides the base class implementation of
the method. The new modifier can be applied on non-virtual as well as virtual methods
but not on abstract methods.

How do I read/write binary data from/to a file?

Ans: To read binary data from a file we can use the BinaryReader class. To write binary data to a
file we can use the BinaryWriter class. The Write( ) method of the BinaryWriter class writes
data of type int, long, float, etc. to the file. Similarly, Read( ) method reads the data from file.
Binary I/O is useful while reading or writing records.

How to perform custom validation?

Ans: While creating ASP.NET application we often require to validate the input data. We
can use various validation controls provided by the .NET for this purpose. There are
controls to check whether fields are empty, to compare two values and to validate a value
using regular expression. But what if we want that user should enter only numeric value
in a text box? There is no built-in validation control for this purpose. In such a situation
we can use CustomValidator control. To this control, we need to specify a function that
is used for validating the value of the control. Whether value is right or wrong can be
specified using the IsValid property of the control.

Binding Data With Controls...

We often need to populate controls like combo box, list box, etc. using a data source. Instead of
reading data from the data source and then adding it to items' collection of these controls, we can
directly bind data sets to these controls so that the controls get populated with the data from
specified dataset. Following code snippet shows how to bind data to a combo box named
myCombobox.

string ConnectionStr = System.Configuration.ConfigurationSettings.AppSettings [ "DbConnect" ] ;


SqlConnection Connection = new SqlConnection ( ConnectionStr ) ;

SqlDataAdapter DAdapter = new SqlDataAdapter ( "select Id from mytable", Connection ) ;


DataSet ds = new DataSet( ) ;
DAdapter.Fill ( ds, "mytable" ) ;

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

myCombobox.DataSource = ds.Tables [ "mytable" ].DefaultView ;


myCombobox.DataBind( ) ;
COM Interoperability...

COM components and .NET components are not compatible since they have different
internal architectures. However, there are tools available in the .NET SDK for generating
COM proxies for .NET components and .NET proxies for COM components. Using these
proxies we can use COM components in .NET projects and vice versa.

For using COM components in .NET application we can create the wrapper class either
by using the 'TlbImp.exe' tool provided in the .NET SDK or by adding the COM
reference through the Solution Explorer.

To use a .NET component in a non-.NET project we have to first register the component
using the RegAsm tool as well as create a corresponding COM type library file ('.tlb'
file). To create a COM type library file we need to use the TlbExp tool.

Using Pointers In .NET...

Pointers can be used in C#, but only in the blocks of code that we have specifically marked for
pointer use. The keyword to do so is unsafe. We can mark individual methods, classes,
structures, blocks of code or even local variables as unsafe. For example we can write:

unsfae float myfunction( )


{
// Can use pointers
}

unsfae class myclass


{
unsafe int *x ;
}

unsafe
{
// unsafe block
}
Creating A Splash Screen...

.NET by default does not expose any feature similar to the VC++ SplashScreen, but it can
easily be replicated using a simple trick. The trick is to add a form to the application, strip
it off all the borders and title bar, also disable it to have any presence on the task bar.
Once this is done, wrap your Splash screen bitmap on to this form.
Add a timer control to the form and set it to the necessary delay. On the timer_click
event, dispose the form.
Your authentic splash screen is ready. Now make sure that this form is displayed every
time your application starts. Best way to do this is to show the splash screen in the Load
event of the application window.

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

Structure Of Manifest...

The assembly metadata that describes the assembly is called the Manifest. A manifest
contains:

(a) The identity of the assembly, consisting of its name, version and culture.
(b) Names of all the files in the assembly.
(c) Whether all the types defined in the assembly are visible to other assemblies or private
to one.
(d) A hash of all files in the assembly.
(e) Details of any security permissions that clients need to have in order to be able to run
the assembly.

The With - End With keywords...

The keywords With - End With execute a series of statements written between With and End
With making repeated reference to a single object of the structure or class. For example the
statements

e.name = "Satish"
e.age = 25
e.sal = 4500

can be written using With - End With as

With e
.name = "Satish"
.age = 25
.sal = 4500
End With

How to invoke two handlers for one event?

Ans: For one event we can add two handlers. For example, if we click on a button, by default
Click event handler gets called. If we want to call some other handler also, we can do so by
writing the handler as

sub Funname ( ) Handles ControlName.Click.


---
---
End Sub

Painting On Form...

Suppose we want to display a string at the center of the form. We would do so in Paint event
handler as shown below:

private void Form1_Paint ( object sender, System.Windows.Forms.PaintEventArgs e )


{
Graphics g = e.Graphics ;
Font font = new Font ( "Arial", 20 ) ;

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

g.DrawString ( "Hi", font, Brushes.Blue, ClientRectangle.Width / 2, ClientRectangle.Height / 2 )


;
}

We want that if we resize the form, the text at previous position should get erased and should get
displayed at the new center of the form. Actually, when the form is resized, Paint event gets
generated and form gets invalidated. Then why doesn't the string get displayed at new position?
This is because, only that portion of the form gets invalidated, which is being resized. Hence,
string remains at its original position. To correct this problem, we must add the Resize event
handler and call Invalidate( ) from it. Invalidate( ) invalidates the entire form.

Of Paths & Regions...

A graphics path is a shape constructed from complex curves and straight lines. The object of
GraphicsPath class represents a path. In the following code snippet, we have created a shape of
a telephone and added the path object gp to an object of Region class. This object of Region
class specifies the area of the window. Add this code in the constructor after call to
InitializeComponent( ) method and execute the program. You would appreciate the output.

GraphicsPath gp = new GraphicsPath( ) ;


gp.AddLine ( 495, 175, 565, 300 ) ;
gp.AddLine ( 565, 340, 70, 340 ) ;
gp.AddLine ( 70, 300, 140, 175 ) ;
gp.AddLine ( 210, 175, 210, 170 ) ;
gp.AddLine ( 135, 170, 122, 195 ) ;
gp.AddLine ( 70, 195, 55, 155 ) ;
gp.AddLine ( 55, 120, 580, 120 ) ;
gp.AddLine ( 580, 155, 565, 195 ) ;
gp.AddLine ( 513, 195, 500, 170 ) ;
gp.AddLine ( 425, 170, 425, 175 ) ;
Region = new Region ( gp ) ;

How to run another application from current running application?

Ans: To run an application from within a currently running aplication call Start( ) method as
shown below:

Imports System.Diagnostics
Public Class Form1
Private Sub Button1_Click ( ByVal sender As System.Object, ByVal e As System.EventArgs )
Handles Button1.Click
Process.Start ( "IExplore", "http://www.funducode.com/" )
End Sub
End Class

How do I write code to get the list of fonts available on machine in a combo-box?

Ans: Create a Windows application. Add a combo box on form. Add code to Load event as
shown below:

Private Sub Form1_Load ( ByVal sender As System.Object, ByVal e As System.EventArgs )


Handles MyBase.Load

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

Dim f( ) As FontFamily = FontFamily.Families


Dim l As FontFamily
For Each l In f
ComboBox1.Items.Add ( l.GetName ( 0 ) )
Next
End Sub

Thread State...

A thread can be in more than one state at any given time. For example, suppose a thread is in the
WaitSleepJoin state because a Sleep( ) method was called on it. Now if another thread calls
Suspend( ) on this thread, the thread will be in both the WaitSleepJoin and the
SuspendRequested states at the same time. In this case, as soon as the sleep time expires
instead of moving to the Running state, the thread goes into the Suspended state.

Creating TextBox That Accepts Only Digits......

.NET IDE provides various properties that let us change the behavior of controls. For example,
we can specify whether a textbox should be a multiline text box or a single line text box. However,
there is no property using which we could specify that a textbox would take only digits and would
reject any other character. If we want to create such a textbox, we must write code for it. We must
check whether the character being typed in the text box is a digit or not. If it is a digit, then only
we would show the character in the text box, otherwise we won't.

Here is the code that achieves this.

private int m_k ;


private void textBox1_KeyDown ( object sender, KeyEventArgs e )
{
m_k = e.KeyValue ;
}

private void textBox1_KeyPress ( object sender, KeyPressEventArgs e )


{
if ( m_k >= 48 && m_k <= 57 )
e.Handled = false ;
else
e.Handled = true ;
}

How do I add a property to a user control that allows user to select a value from combo
box?

Ans: Almost every WinForm control has properties that allow us to select a value from a combo
box. We can add such property to a user control by defining an enum in the control class and
declaring a property of that type. For example, in the following code, we have declared a property
named Message of type MSGVALUE. MSGVALUE is an enum that defines enumerated types A,
B and C. When the type of a property is an enum, .NET adds a combo box to display the
enumerated values.

public enum MSGVALUE


{
A = 0, B = 1, C = 2

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

};

MSGVALUE msg ;
public MSGVALUE Message
{
get
{
return msg ;
}
set
{
msg = value ;
}
}

We can use the Process component to start a process from our application or browse the
processes running on the system. The Process component can be dragged from the
'Components' tab of the ToolBox. Following code starts the 'explorer.exe' process.

process1.StartInfo.FileName = "C:\\WINNT\\explorer.exe";
process1.Start( ) ;

We can browse the processes using the GetProcesses( ) static method.

Data Binding With WinForm Controls...

.NET provides an ability that binds a control with a field in the data source. Binding data with
control actually means binding a property of a control with a column of a data source. When the
form is loaded the data bound property gets evaluated and the value returned is displayed in the
control. For example, the Text property of TextBox control can be bound to a column of a data
source. Following statements bind data of the 'PatientName' column of 'PatientInfo' table with
Text property. Data of zeroth row will get displayed in the text box named txtname.

Binding bname = new Binding ( "Text", m_ds, "PatientInfo.PatientName" ) ;


txtname.DataBindings.Add ( bname ) ;

Here, m_ds is a reference to DataSet object that is filled with data of a data source.

Difference Between Server-activated & Client-activated Objects...

Server–activated objects are so called because when the client calls new to create an instance of
the remote class, only a proxy gets created in the client. The object does not get created or
activated. The object gets created only when a method call is placed through the proxy. So, the
server actually decides when the object should get created.

Client–activated objects, on the other hand, are created on the server the moment the client calls
new. Thus here the client decides when the object should get created. Another difference
between the two is that client–activated objects can be activated using non–zero–argument
constructors but server–activated objects cannot. This is because for server–activated objects,
the calls to new don’t map with the actual creation of the object. On the other hand client–
activated objects can be instantiated with any constructor as both the proxy and the object are
created at the same time.

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

How to copy an ASP.NET project?

Ans: When we create a Web application, its project files get created in the ‘C:\Inetput\wwwroot’
folder, whereas, the solution files get created in the ‘My Documents\Visual Studio Projects’ folder.
If we want to copy a Web application to some other machine, then copy the project folder in
‘C:\Inetput\wwwroot’ folder of that machine and make the project folder as ‘virtual folder’. To
declare it as a ‘virtual folder’ run IIS, you will see the folder name under the ‘Default Web Site’
tree. Right click on the folder name and select ‘Properties’. From the ‘Execute Permissions’
combo box and select ‘Scripts and Executables’.

After this, open the project by selecting 'File | New | Project' in the .NET IDE.
Splitter Windows In .NET

Earlier, we used to split the frame window using an MFC class. Each pane of the split window
was represented by a separate view window. Moving the splitter actually resized the view
windows. In .NET, working of splitter is totally different. .NET provides a Splitter control. This
control allows the user to resize the docked control that is immediately before it in z-order.
Therefore, to use the splitter control, place a control and dock it to the left/right side of the form.
Then dock a splitter control to the same side of that container.

How do I write code to shift focus on next control on pressing the Enter key?

Ans: If form’s KeyPreview property is set to true it receives the keyboard events first and then
the control having focus also receives the events. We can use the KeyPreview property to filter
the keys before a control receives it. For example, we want to design a registration form having
many text boxes. If user enters a value and presses the Enter key, next textbox should get the
focus. For this, instead of adding keyboard events to each textbox and check for the Enter key
press, we can add the KeyDown event handler to the form and check whether the Enter key is
pressed. Of course KeyPreview must be set to true. The code to shift the focus is given below.

private void Form1_KeyDown ( object sender, KeyEventArgs e )


{
if ( e.KeyCode == Keys.Return )
{
Control c = GetNextControl ( ActiveControl, true ) ;
c.Focus( ) ;
}
}

The ActiveControl property returns the reference of the control that is currently selected. The
GetNextControl( ) method returns the control next to the specified control in tab order. The focus
is set on the next control using the Focus( ) method.

The DateTime class offers an interesting feature. It allows us to add number of hours and
minutes to the given DateTime instance. What a big deal? It does not add the values blindly. It
updates the hour element if minutes exceed the value 60, and day if hours exceed the value 24.
Previously, we had to do this manually by writing pair of ifs and elses. Following code snippet
shows how to add 10 hours 45 minutes to the current time.

DateTime t = DateTime.Now ;
t.AddHours ( 10 ) ;
t.AddMinutes ( 45 ) ;

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

How to check whether a key is pressed in combination with Shift or Toggle keys?

Ans: The KeyEventArgs class has a property called Modifiers that contains the status of the
modifier keys such as ‘Ctrl’, ‘Alt’ and ‘Shift’. So, to check whether Ctrl + A is pressed, we can write
the if condition as follows.

private void textBox1_KeyPress ( object sender, KeyPressEventArgs e )


{
if ( ( e.KeyCode == Keys.A ) && ( e.Modifiers == Keys.Control ) )
MessageBox.Show ( "Ctrl + A pressed" ) ;
}

Where e is of type KeyEventArgs class. Keys is an enum that specifies the key codes and
modifiers.

Code Access Security...

The Code access Security is a new concept brought in by the .NET framework. Code access
security essentially involves granting permissions to an assembly. Code access security uses the
location of assembly and other information about the identity of code as a primary factor in
determining permissions to be granted to the assembly. This information about the identity of an
assembly is called evidence. Once loaded in runtime, the code starts executing in the restricted
environment depending upon permissions granted to it. If the code is not trusted enough to run or
runs but performs an action for which it has no permissions, then a security exception is thrown.
The code access security system means we can stop running of malicious code and also restrict
the code to run in a restricted environment where we are sure that it won’t do any damage to the
resources.

Industrial softwares are complex to create and involve work of several programmers. If one
programmer is supposed to understand and use a class designed by another programmer, proper
documentation of that class should exist. The documentation should reveal the role of that class
in the software, functionality of each class member, meaning of parameters of every method of
the class and so on. To facilitate the creation of such documentation, Visual Studio.NET provides
XML documentation tool. This tool recognizes comments given in the source code. These
comments should contain information programmer wishes to provide. Following example shows
such a comment.

/// <summary>
/// Your documentation goes here
/// </summary>

Setting Security Policies...

Sometimes it is necessary to turn off security for whichever reason. Security can be turned OFF
by simply typing the following at command prompt.

C:\>caspol –security off

To turn security back ON type ‘on’ instead of ‘off’. The caspol utility can also be used to change
the code group’s membership condition, permission set, etc. This is shown in the following
command.

C:\> caspol.exe –chggroup 1.2 FullTrust

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

Here, 1.2 specifies the label of the code group. It can be any number like 1or 1.1. Instead of label
we can mention the name of the group. FullTrust is name of the permission set to associate with
the code group. The addgroup flag adds a new code group to the existing code group list. In the
command

C:\> caspol.exe –addgroup –1.2.3 –strong –file \bin\Debug\trusted.dll –noname –noversion


FullTrust

1.2.3 is the label of the parent code group. Next argument specifies the code that has a specific
strong name, as designated by the file name, the assembly name as a string, and the assembly
version. noname — noversion indicates that no assembly name and version is used.

How to add controls programmatically?

Ans: We would add a button to the form and add a Click event handler to it. Firstly, declare a
reference of the Button class.

private Button btn = new Button( ) ;

Then assign properties to the button in the InitializeComponent( ) method as shown below. We
have also built a delegate for the Click event of the button.

btn.Text = "OK" ;
EventHandler e = new EventHandler ( btnClick ) ;
btncont.Click += e ;

Now add the control to the form by calling the Add( ) method.

this.Controls.Add ( btn ) ;

The Controls property returns a collection of child controls. The Add( ) method adds our control
to that collection. We can write the Click event handler as shown below.

private void btnClick ( object sender, EventArgs e )


{
}

How do I write code that displays a form as a modal dialog?

Ans: Use ShowDialog( ) method which shows the form as a modal dialog box. Following code
snippet demonstrates the use of this method.

Private Sub Button1_Click ( ByVal sender As Object, ByVal e As System.EventArgs) Handles


Button1.Click
Dim test As New Form2
test.ShowDialog( )
End Sub

The Handled Property...

The Handled property can restrict the controls placed on the form from handling the keyboard
events and allow them to be handled only at the form level. For this, form’s Handled property

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

should be set to true. Setting the Handled property to true in the OnKeyPress( ) method
indicates that the KeyPress event is already handled. The Handled property is also useful in a
situation when we want that only certain characters should get entered in the textbox, others
should not. For example, we want that a textbox should take only alphabets and should ignore
digits and special symbols then the Handled property should be set to false if alphabets are
entered and to true otherwise. This is to be done in the KeyPress event handler added for the
textbox as shown below.

private void textBox1_KeyPress ( object sender, KeyPressEventArgs e )


{
if ( ( e.KeyChar >= 97 && e.KeyChar <= 122 ) ||
( e.KeyChar >= 65 && e.KeyChar <= 91 ) )
e.Handled = false ;
else
e.Handled = true ;
}

The Buffer Class...

The term buffer is related to memory, the Buffer class works on direct memory. This class can be
used for arrays of primitive types and does not apply to objects. This class provides methods to
copy bytes from one array of primitive types to another array of primitive types.

In case of System.Array class, it carries an index to index copy. But in the Buffer class, it's from
offset to offset. The Buffer class copies a specified number of bytes from a source array starting
at a particular offset to a destination array starting at a particular offset.

In the System.Buffer class we have the BlockCopy( ) member to copy from one array to
another. We can also get a byte from an array, set a byte in an array, and obtain the length of an
array. This class provides better performance for manipulating primitive types as comapred to
those in the System.Array class.

Integer Types in VB.NET...

Integer types in VB.Net are used to represent whole numbers. Depending on the amount of
memory required to store an integer the data type in VB.net is categorized as, Byte, Short,
Integer and Long. The following table lists the data type and its size.

Data
Size in Bytes
Type
Byte 1
Short 2
Integer 4
Long 8

Following statement shows how we can declare an integer variable in VB.NET.

Dim x, y As Integer

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

Here x and y are two integer variables and as they are not initialised with any number, they would
be initialised to 0.

Dim i As Short = 12

The variable i declared in this statement would hold value 12.

VB.NET provides logical operators, And and AndAlso that can be used to help evaluate
expressions. Consider following statement,

If age < 10 And number > 4 Then


// code
End If

Here we want that if the value of age is greater than 10, then the second condition should not be
evaluated. Since the conditions given above are connected using And, both the conditions would
get evaluated. In other words, even if the first condition evaluates to false, And evaluates the
second condition. However, in case of AndAlso operator, it evaluates the second condition only if
the first condition evaluates to true. For example,

If age < 10 AndAlso number > 4 Then


// code
End If

If the value of age is greater than 10, the evaluation of the expression stops and the operator
would return false. Thus, using AndAlso helps evaluating expressions efficiently.

There are two types of procedures in VB.NET-Functions and Subroutines. The basic
difference between the two is that a subroutine does not return a value whereas a function
returns a value. Function is a collection of logical statements which perform a specific
task and return some value. Hence whenever you want to return something to a calling
function use a function and to display something use a subroutine. Thus, for displaying a
menu we would use a subroutine and for calculating a factorial of a number and returning
it to the calling function we would use a function.

Constructor in VB .NET

In VB.NET the constructor name is not same as the name of the class. A keyword New is used to
define a constructor. Following code snippet shows how to declare a constructor:

Class sample
Dim i As Integer
Sub New( )
i=5
End Sub
End Class

Module Module1
Sub Main( )
Dim obj As sample
obj = New sample( )
End Sub

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

End Module

In the above example in the class sample we have defined a constructor to initialise the data
member i. In main( ) we have created an object obj of the class sample. As soon as the object
gets created the constructor gets called and the value of i gets intialised to 5.

We can use the MinValue and MaxValue properties to get the minimum as well as maximum
range of each data type. This is shown in following example.

Module Ranges
Sub Main( )
Console.WriteLine("Byte Range: {0} to {1}", Byte.MinValue, Byte.MaxValue)
Console.WriteLine("Short Range: {0} to {1}", Short.MinValue, Short.MaxValue)
Console.WriteLine("Integer Range: {0} to {1}", Integer.MinValue, Integer.MaxValue)
Console.WriteLine("Long Range: {0} to {1}", Long.MinValue, Long.MaxValue)
End Sub
End Module

Namespaces...

Much of interesting functionality available in VB .NET is provided by the .NET Framework Class
Library. Namespaces are used to hold collection of related classes. Console I/O is provided by
the .NET System.Console class. The WriteLine( ) method is used to display a line of text.

System.Console.WriteLine ( "Hello World" )

Reference to System.Console.WriteLine may be shortened to Console.WriteLine if you import


the System namespace.

Import System
...
Console.WriteLine ( "Hello World" )

The Import statement tells compiler to look in the System namespace before generating an error
whenever an unknown class or function is referenced.

Value Types Vs Reference Types

In VB.NET variables are either value types or of reference types. The difference between
the value type and reference type is that the data of value type gets stored on the stack
and that of the reference type gets stored on the heap. The variables of the value types
directly contain the data, whereas, reference types contain references (or addresses) of the
data. Examples of value types are the primitive data types integer, floating points,
structures whereas examples of reference types are arrays and classes

Arrays...

We can declare an array as shown below:

Dim arr( ) As Integer


arr = New Integer ( 5 ) { }

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

Here, the first statement creates only a reference to one dimensional array. By default arr holds
nothing. The second statement allocates memory for 5 integers. The space for arr is allocated on
the stack. Space of array elements gets allocated on heap. The elements of arr would be 0 as by
default array elements are initialised to zero. One more way of declaring an array is given below:

Dim arr( ) As Integer = { 1, 2 , 3 ,4 }

Here again arr is created on the stack and the actual array elements are created on the heap.
These array elements are initialised with values 1, 2, 3, 4 respectively. Note that when we
initialize an array at the same place where we are declaring it then there is no need of New
statement.

In .NET arrays are implemented as objects. An array gets automatically derived from
System.Array class. This is because when we create an array a class gets created from the
System.Array class. This class internally maintains an array. An object of this class is also
created to which the array reference points. Hence using the reference we can call methods and
access properties of the System.Array class. In VB.NET the lower bound of an array is always
zero. Thus with the statement Dim arr(3) As Integer an array of 4 elements get created.

VB.NET provides the flexibility to use Value types as Reference types, as and when required.
Whenever a value type is converted into a reference type it is known as Boxing. On the other
hand when a reference type is converted into value type it is known as Unboxing. Both the
WriteLine( ) and the ReadLine( ) methods use this concept of Boxing and Unboxing
respectively.

For example, consider following statement:

WriteLine ( Dim s As string, ParamArray arr( ) As Object )

Here, all the objects except the first are collected in the ParamArray of type Object. Hence there
is no restriction on the number of parameters being printed in the list. In the WriteLine( ) method
if we pass an integer variable, the compiler implicitly converts an integer variable ( value type )
into an object ( reference type ) using boxing and collects it as the first element of the
ParamArray of objects.

Readline( ) method is an example of Unboxing. ReadLine( ) always returns a string which is a


reference type. This reference type is explicitly converted into the value type that we want. For
example, using CInt we can convert a string into an Integer, which is a value type.

Dim I As Integer
I = CInt ( Console.ReadLine( ) )

How do I create a structure?

Ans: The following code snippet shows how we can create a structure in VB.NET.

Structure a
Dim i As Integer
Dim s As String
Sub New ( ii as Integer, ss as String )
i = ii
s = ss
End Sub
End Structure

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

Note that we cannot explicitly mention a zero-argument constructor within a structure. A zero-
argument constructor is always provided by the compiler. However writing a multiple argument
constructor within a structure is allowed.

Whenever we wish to group a few dissimilar data types, we must use structures because being a
value type it gets allocated on the stack. Memory allocation on stack is always faster than on
heap. However, if the structure is big then whenever we pass the structure variable as a
parameter or assign it to another structure variable, the full contents of the structure variable gets
copied. As against this for a class only the reference gets copied. It is more efficient to copy a 4
byte reference than copying the entire structure.

Why memory allocation for value types is faster than for reference types?

Ans: Memory allocation for value types is always faster than for reference types. This is because
reference types are always accessed via references. Hence anytime our code refers to any
member of an object on the heap, code must be generated and executed to dereference the
reference in order to manipulate the object. This affects both size and speed. However in case of
value types the variable itself represents an object. Hence there is no question of dereferencing in
order to manipulate the object. This improves performance.

What are Primitive data types?

Ans: Data types that are directly supported by the compiler are called Primitive data types.
Integers, Single, Double and Char types are all examples of primitive data types. Primitive data
types map directly to the types that exist in the base class library. For example an Integer in
VB.NET maps directly to System.Int32 type.

How do I declare variables as read only in VB.NET?

Ans: VB.NET provides a keyword ReadOnly which is used for variables which are to be
initialized at the time of building the objects. The following code shows how to declare variables
as ReadOnly.

Module module1
Class hotel
Public ReadOnly name As String
Sub New ( ByVal n As String )
name = n
End Sub
End Class

Sub main( )
Dim h As New hotel ( "Tuli" )
End Sub
End Module

We cannot assign any value to a ReadOnly Variable. Hence the statement h.name = "CP" would
give us an error. i.e h.name cannot be written on the left side of the assignment operator.

Properties In VB.NET...

Properties of a class are actually methods that work like data members .The properties are used
to store and retrieve the values to and from the data members of the class. The following code
shows how to declare a property called Length within a class called sample.

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

Module Module1
Class sample
Dim len As Integer
Property Length( ) As Integer
Get
Return len
End Get
Set ( ByVal Value As Integer )
len = Value
End Set
End Property
End Class
Sub Main( )
Dim s As New sample( )
s.Length = 10
Dim l As Integer = s.Length
Console.WriteLine( l )
End Sub
End Module

To store and retrieve the len data member of the class sample the Length property is used. A
property has two special methods known as a Get accessor and a Set accessor. The Get
accessor never accepts any value and the Set accessor never returns any value. The value
collected by the Set accessor is stored in an implicit parameter called Value.
The statement m.Length = 10 would invoke the Set accessor and the statement len = m.Length
would invoke the Get accessor.

Interfaces in VB.NET...

Interfaces are similar to abstract classes. The following statements show how we can declare an
interface called mouse.

Interface mouse
Sub lbuttondown ( x As Integer, y As Integer )
Sub rbuttondown ( x As Integer, y As Integer )
End Interface

Any class can implement the above interface and can provide separate implementation of the
functions defined in the interface. Note that an interface contains only declarations of functions
and does not contain any definitions. Following code snippet shows how a class can implement
the above interface.

Class Mouse1 : Implements mouse


Sub lbuttondown ( x As Integer, y As Integer ) Implements mouse.lbuttondown
Console.WriteLine ( "Left Button : { 0 }, { 1 }", x, y )
End Sub
Sub rbuttondown ( x As Integer, y As Integer ) Implements mouse.rbuttondown
Console.WriteLine ( "Right Button : { 0 }, { 1 }", x, y )
End Sub
End Class

Virtual Functions in VB.NET…

In VB .NET the keyword Overridable is used to indicate that a function is virtual. The

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

Overridable keyword in VB.NET is similar to the keyword virtual in C++. Following code snippet
shows how we can design a base class that has a virtual function.

Class shape
Overridable Sub draw( )
Console.WriteLine( " Shape" )
End Sub
End Class

Any class that inherits the shape class can override the draw( ) method. For this it is necessary
that draw( ) method should be preceded with the keyword Overrides in a derived class. This is
shown in following code snippet.

Class line : Inherits shape


Overrides Sub draw( )
Console.WriteLine ( "Line" )
End Sub
End Class

Conversion Functions In VB.NET...

VB.NET provides many conversion functions. Some of these functions are CInt, CBool, CStr,
CLng, CDec, CSng, CShort.

CInt function converts any numeric expression to an Integer value as shown below:

Dim i As Integer
i = CInt ( 10.5 )

CBool function convert expressions to Boolean values.

Dim check As Boolean


Dim a, b As Integer
a = 15
b = 15
check = CBool (a = b ) // 'True is assigned in check

CStr function converts a numeric value to String.

Dim i As Double = 42.34


Dim s As String
s = CStr ( i )

These functions are inline functions. Hence execution is faster because there is no call to a
procedure to perform the conversion.

Error Handling In VB.NET...

The errors that occur at the time of execution of a program are known as exceptions. VB.NET
provides a Try-Catch mechanism to handle exceptions. The Try block contains code expected to
raise an exception. This code in the Try block executes until a statement, which raises an
exception, is encountered. When an exception is encountered, the Catch block handles the
exception by executing the code written in it. In the following program an

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

IndexOutOfRangeException is raised. The CLR creates an object of the


IndexOutOfRangeException class and passes it to Catch block that accepts a reference to the
IndexOutOfRangeException.

Module Module1
Sub Main( )
Dim index As Integer = 6
Dim val As Integer = 30
Dim a ( 5 ) As Integer
Try
a ( index) = val
Catch e As IndexOutOfRangeException
Console.WriteLine ( " Index out of bounds" )
End Try
Console.WriteLine( " Remaining program" )
End Sub
End Module

The output of the above program would be:

Index out of bounds

How do I write code to navigate to previous and/or next record?

Ans: Add code to the handlers that move record pointer to previous and next record
respectively, as shown below:

Private Sub Previous_Click ( ByVal sender As System.Object, ByVal e As


System.EventArgs ) Handles Previous.Click

Dim str As String


'dr is a private variable of type DataRowCollection added to Form class
str = dr ( count ).Item ( 0 )

'to move to previous record decrement count by 1

count -= 1 ' where count is a variable of type Integer


If count < 0 Then

count = 0
MsgBox ( "Reached First Record" )

End If

End Sub

Private Sub Next_Click ( ByVal sender As System.Object, ByVal e As System.EventArgs


) Handles Next.Click

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

'to move to next record increment count by 1


count += 1

Dim str As String


str = dr ( count ).Item ( 0 ) ' where dr is a variable of type DataRowCollection

If Count >= dr.Count - 1 Then

count = dr.Count - 2
MsgBox ( "Reached Last Record" )

End If

End Sub

Virtual Functions in VB.NET…

In VB .NET the keyword Overridable is used to indicate that a function is virtual. The
Overridable keyword in VB.NET is similar to the keyword virtual in C++. Following code snippet
shows how we can design a base class that has a virtual function.

Class shape
Overridable Sub draw( )
Console.WriteLine( " Shape" )
End Sub
End Class

Any class that inherits the shape class can override the draw( ) method. For this it is necessary
that draw( ) method should be preceded with the keyword Overrides in a derived class. This is
shown in following code snippet.

Class line : Inherits shape


Overrides Sub draw( )
Console.WriteLine ( "Line" )
End Sub
End Class

How do I write pure virtual functions in VB.NET?

Ans: In VB.NET the pure virtual functions are written by writing the keyword MustOverride
against the name of the method. The keyword MustOverride specifies that the method written in
the base class must be overridden in the derived class. Like pure virtual functions a
MustOverride method cannot have a body. Consider the following example:

MustInherit Class shape


MustOverride Sub draw( )
End Class
Class circle : Inherits shape
Overrides Sub draw( )
Console.WriteLine ( "Circle" )
End Sub

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

End Class

Here, since the method draw( ) is declared as MustInherit in the base class shape, any class
that inherits the class shape must override the draw( ) method. Hence the class circle which
inherits shape class provides its own implementation of the draw( ) method.

How do I write code that would throw exceptions explicitly in VB.NET?

Ans: In VB.NET the Throw statement is used to throw an exception explicitly.

Class sample
Sub fun ( i As Integer )
If i > 10 Then
Throw New Exception ( "Value out of range" )
Else
Console.WriteLine ( i )
End If
End Sub
End Class
Module Module1
Sub Main( )
Dim m As New sample( )
Try
m.fun ( 20 )
Catch e As Exception
Console.WriteLine ( e.Message( ) )
End Try
Console.WriteLine ( "Remaining Program" )
End Sub
End Module

Here, the parameter passed to the method fun( ) is greater than 20 hence an exception would be
raised. The Catch block catches the exception and displays the message "Value out of Range".

How do I write code to display two strings on two lines using Writeline( )?

Ans: VB.NET provides a keyword NewLine which helps to achieve this purpose. In order to use
this keyword we must import the namespace Microsoft.VisualBasic.ControlChars. Following
statement shows how to use this keyword.

Console.WriteLine ( "hi" & NewLine & "hello" )

How do I change the size of an array in VB.NET?

Ans: VB.NET provides a keyword called Redim which enables us to change the size of an array
that has been already declared. The following code snippet shows how to change the size of an
array called arr from 6 elements to 11 elements.

Dim arr ( 5 ), i As Integer


For i = 0 To UBound ( arr )
arr ( i ) = i
Next
ReDim arr ( 10 ) 'The size of arr now becomes 11 ( as array always starts from 0th index)
For i = 0 To UBound ( arr )

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

arr ( i ) = i * 10
Next

Suppose we want to preserve the existing contents of an array then we have to use the keyword
preserve along with Redim as shown below:

Redim preserve arr ( 10 )

How do I write a class that cannot be inherited?

Ans: VB.NET provides a keyword called NotInheritable which ensures that a class cannot be
derived further. This is shown in following code snippet.

NotInheritable Class shape


Sub draw( )
Console.WriteLine ( "Shape" )
End Sub
End Class

Since the class shape is preceded with the keyword NotInheritable, any attempt to derive a
class from the class shape leads to an error.

How do I create a form of elliptical shape?

Ans: To create a form of elliptical shape, write following code in the constructor of the Form1
class.

Public Sub New( )


MyBase.New( )
Dim gp As New GraphicsPath( )
gp.AddEllipse ( 20, 20, 140, 40 )
Region = New Region ( gp )
End Sub

Here, first we have instantiated an object of the GraphicsPath class. This GraphicsPath class
has various methods which can be used to create various user defined shapes. Using the
AddEllipse( ) method of this class we have first created an elliptical shape.

We have then instantiated a new Region object and to its constructor we have passed this
graphics path. Next to the Region property of the Form1 class we have assigned this newly
created region. Due to this only that portion of the form would be visible which lies within this
region. Note that for this it is necessary to import System.Drawing.Drawing2D namespace.

How do I write code to create a mirror image?

Ans: To create a mirror image write following code in Form1_Paint Event handler.

Sub Form1_Paint ( s As Object, e As PaintEventArgs ) Handles MyBase.Paint


Dim g As Graphics = e.Graphics
Dim myimg As Image = Image.FromFile ( "C:\fcode.jpg" )
Dim mymat As Matrix = New Matrix( )
mymat.Scale ( -1, 1 )
mymat.Translate ( -350, 0 )

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

g.Transform = mymat
g.DrawImage ( myimg, 50, 50 )
g.ResetTransform( )
End Sub

Here first we have used the shared method FromFile( ) of the Image class. This would return a
reference to image which we have collected in the variable myimg. In order to create a mirror
image we have to make use of transformations. To create a transformation matrix we have first
created an object of the Matrix class. We have first scaled the matrix by passing a -1 as the first
parameter to the Scale( ) method. Due to this all the x coordinates would be multiplied by -1. After
multiplying this matrix with the coordinates of the image the resultant image would be the mirror
image of the original. When we scale the coordinates of an image by multiplying them with -1 the
resulting coordinates become negative. Hence they would not be visible as top left corner of the
form is 0, 0. To bring the image back in the form we have to translate it by some x and y values.
For this we multiply the co-ordinates by a negative number to make the resultant coordinates
positive. Next we have assigned this resultant transformation matrix to the Transform property of
the Graphics object. There onwards everything that gets drawn would be multiplied with the
transformation matrix. Finally for drawing the image we have used the DrawImage( ) method.

What are Delegates and how do I declare a Delegate?

Ans: The word delegate means a representation of a function. A delegate is implemented as an


object that stores address of a method in it. The class of this object is called a delegate class and
is derived from System.MultiCastDelegate class. The following statement shows how to declare
a delegate class.

delegate Sub del ( string )

When the compiler encounters this statement it creates a class named del and derives it from the
System.MulticastDelegate class. Later when an object of the delegate class del is created, it
can hold address of a method whose return type is void and receives a string. To store address
of a method say fun( ) inside a delegate object we need to first create a delegate object. This is
done as shown below:

Dim d As New del ( AddressOf fun )

Here d is a reference to an object of del. The address of the fun( ) method is passed to the
constructor of the delegate class which is created by the compiler. The constructor stores this
address in the delegate object. To call the wrapped method we can now write the following
statement:

d ( "Hi" )

Here d delegates (represents) fun( ) in true sense.

In VB..NET an Enum cannot have a circular definition. For example we cannot declare an Enum
as shown below:

Enum emp As Integer


skilled = highlyskilled
semiskilled
highlyskilled
unskilled

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

End Enum

Here the value of skilled depends on its own value and hence is an error. We can however
declare the Enum as shown below:

Enum emp As Integer


skilled
semiskilled
highlyskilled = skilled
unskilled
End Enum

Now if we print the members of the Enum in the order in which they are defined then we will get
output as 0, 1, 0 and 1. The member skilled gets initialized to 0, the semiskilled to 1 ( 0 +1),
highlyskilled to 0 again and unskilled to 1 ( 0 + 1).

How do I draw an icon on the form?

Ans: To draw an icon on the form we need to create an object of the Icon class by supplying the
file name of the '.ico' file and then calling the DrawIcon( ) method of the Graphics class.
Suppose that the reference of the graphics object is in g, then we can write the following:

Dim i As Icon New ( "C:\myicon.ico" )


g.DrawIcon ( i, 10, 20 )

where 10, 20 denote the top left coordinates from where the icon would be drawn.

What is MergeOrder? When is it used?

Ans: MergeOrder is a property of the MenuItem class. This property gets or sets a value
indicating the relative position of the menu item when it is merged with another. For example,
suppose we create an MDI application. Now we add a MainMenu control containing some
MenuItems to both the parent and the child window. If the child window has a set of menu items
that we want to display in the parent window's main menu, we can create a MainMenu as part of
both the forms and set some values to the MergeOrder property of the MenuItems of both the
forms. So now when the child window is activated, its MainMenu is merged with the MainMenu
of the parent window. While merging, the order of the menu items is according to the
MergeOrder property.

How do ASP.NET pages support Cookieless Sessions?

Ans: By default, ASP.NET pages, like ASP, use cookies to correlate the session state with every
user. Hence if the browser does not support cookies, then there arises a problem. ASP.NET
however supports cookieless session state. Cookieless sessions are enabled by adding
cookieless = “true’ to the sessionState element in the web.config file.

In this case ASP.NET correlates users and the session states by passing the session id in the
URL. The value seen in parenthesis in the browser’s address bar is the session ID. Before
returning the page to the client, ASP.NET inserts the session ID into the URL. When the page
posts back to the server, ASP.NET strips the session ID from the URL and uses it to associate the
request with the session.

What is a Mobile Web Forms page?

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

Ans: Mobile web forms page is a specialized Microsoft ASP.NET Web Forms page. As with any
other Web Forms page, a mobile Web Forms page is a text file with an '.aspx' file extension. This
page contains a set of mobile Web Form controls— ASP.NET server controls that can adaptively
render WML script.

We can program mobile pages and controls by using device-independent properties, methods,
and events. When supported device requests a mobile Web Forms page, the page and controls
automatically produce a rendering suitable for the device. Ordinary ASP.NET Web Forms pages
can contain only one form per page. However, because mobile devices typically have smaller
screens, a mobile Web Forms page allows several forms to be defined.

When a client accesses a page for the first time, the first form is shown by default. You can
programmatically navigate to other forms. To be able to develop mobile applications and use
Mobile SDK we need to download the MobileIT.exe and install the msi from
msdn.microsoft.com

How do I write code to show a bitmap in a picture box and save the picture along with
changes if some drawing is done on it?

Ans: Follow the steps as listed below:


1. On the form place a picture box named pb and a botton named save.

2. Add following variables in the form class.

Dim sourcefile As String


Dim i As Image
Dim st, en As Point
Dim p As Pen
Dim newbitmap As Bitmap

3. Add following code in the constructor to show bitmap in the picture box.

Public Sub New( )


MyBase.New( )
'This call is required by the Windows Form Designer.
InitializeComponent( )
'Add any initialization after the InitializeComponent( ) call
sourcefile = "C:\MyPicture.bmp"
Try
i = Image.FromFile ( sourcefile )
pb.Image = i
newbitmap = New Bitmap ( i )
Catch ex As Exception
MessageBox.Show ( ex.Message )
End Try
End Sub

4. Create bitmap in memory using the Bitmap class. Then whatever drawing needs to be done in
the MouseMove handler will be done on this bitmap by creating Graphics Context of the bitmap
which in our case is gi. We will create Graphics context of Picture Box say g for example.Then
write following code in the MouseMove handler.

Private Sub pb_MouseMove ( ByVal sender As Object, ByVal e As


System.Windows.Forms.MouseEventArgs )

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

Handles pb.MouseMove
p = New Pen ( Color.Red )
Dim gi As Graphics = Graphics.FromImage ( newbitmap )
Dim g As Graphics
g = pb.CreateGraphics

If ( e.Button = MouseButtons.Left ) Then


en = New Point ( e.X, e.Y )
g.DrawLine ( p, st, en )
gi.DrawLine ( p, st, en )
gi.Dispose( )
st = en
End If
End Sub

5. On clicking save button this image should get saved into another file say ‘C:\MyPicture1.bmp’.
To do so we just have to call the Save function of the Bitmap class. Add following code to this
function.

Private Sub save_Click ( ByVal sender As System.Object,


ByVal e As System.EventArgs)
Handles save.Click
Try
Dim newfile As String = "C:\MyPicture1.bmp"
newbitmap.Save ( newfile )
newbitmap.Dispose( )
Catch ex As Exception
MessageBox.Show ( ex.Message )
End Try
End Sub

How do I write code to show check boxes within a listview control and on checking a
particular check box the associated text should get written in the text box.? Every time
checking the check box the text should get appended in the text box. And on unchecking a
particular check box appropriate text should get erased from the text box

Ans: Create an application and place a listview control named list and a text box named
message on the form. Set the CheckBoxes property of list view to true. Add the check boxes
through the Items (Collection) property of the list view control. Set the Text property of each
item.

Now we want that when the check box in the list is checked the corresponding text should get
displayed in the text box and when unchecked the text should get erased from the text box. For
this add the ItemCheck handler in the form class and write following code in it.

Private Sub list_ItemCheck ( ByVal sender As Object, ByVal e As


System.Windows.Forms.ItemCheckEventArgs
) Handles list.ItemCheck
Dim icoll As ListViewItemCollection = list.Items
Dim litem As ListViewItem = icoll.Item(e.Index)
Dim i As Integer
If e.NewValue = CheckState.Checked Then
message.Text = message.Text & litem.Text
message.Text = message.Text & " "
ElseIf e.NewValue = CheckState.Unchecked Then

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

Dim l As Integer = litem.Text.Length


i = message.Text.IndexOf(litem.Text)
message.Text = message.Text.Remove(i, l + 1)
End If
End Sub

How do I show a large size bitmap into a small size picture box by using the
transformation techniques?

Ans: Create a windows application. Place a picture box named pb and a button named Show on
the form. On
clicking the button the file should get displayed in the picture box. Add code shown below to the
button handler.

Private Sub Show_Click ( ByVal sender As System.Object, ByVal e As System.EventArgs )


Handles Button1.Click
Dim i As Image
i = Image.FromFile("C:\picutre.bmp")

Dim w As Integer = i.Width ' image width


Dim h As Integer = i.Height ' image height

Dim pw As Integer = pb.Width ' picture box width


Dim ph As Integer = pb.Height ' picture box height

Dim perw As Single = pw * 100 / w


Dim perh As Single = ph * 100 / h

Dim mat As New Matrix()


mat.Scale(perw / 100, perh / 100)

Dim pbg As Graphics = pb.CreateGraphics

pbg.Transform = mat
pbg.DrawImage(i, 0, 0)
End Sub

To send mail via outlook express in VB.NET

Create a Windows application and place a button SendMail named sendmail on the form and a
text box named emailaddr on it. After writing the email address in the text box when the
SendMail Button is clicked OutLook Express Dialog Box should get popped up having the email
address which is written in the text box.

For this write the following code in the sendmail button handler

Private Sub sendmail_Click(ByVal sender As System.Object, ByVal e As System.EventArgs)


Handles mailsend.Click
If emailaddr.Text = "" then
MessageBox.Show("Enter The Email Address")
Return
End If

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

System.Diagnostics.Process.Start("mailto:" & emailaddr)

End Sub

How do I make use of LinkLabel control in a program?

Ans: Follow the steps listed below:

1. Create a Windows Application.


2. Place on it a LinkLabel control named as link.
3. Set the Text property of link as "http://www.funducode.com/".

On clicking link an appropriate web page should get opened. To make it work add the LinkClicked
event handler and write code to it as given below:

Private Sub link_LinkClicked ( ByVal sender As Object,


ByVal e As System.Windows.Forms.LinkLabelLinkClickedEventArgs ) Handles
link.LinkClicked
System.Diagnostics.Process.Start(link.Text )
End Sub

How do I write code that sends an e-mail?

Ans: Create a Windows Application. Place four Text Boxes labeled as emailaddr, fromaddr,
emailmessage and emailsubject used for—entering the destination email address, sending
email address, writing message and writing subject respectively. Also add a button SendMail
named sendmail on the form. On entering the email address in the text box and on writing the
message in the emailmessage text box when the SendMail button is clicked the mail should be
sent to the proper address. To do so we will use SMTPMail class, and to use it we need to add a
reference in our solution. Click on 'View' menu and select 'Solution Explorer'. Right-click on
'references', select 'Add Reference' option. Then select 'System.Web.dll'. Click select and then
press OK. As a result, System.Web reference will get added in our solution.

Now, we will have to import the namespace System.Web.Mail. For that write the following import
statement in the Form1.vb at the top.

Imports System.Web.Mail

Then, write following code in the Click event handler of the SendMail button.

Private Sub sendmail_Click ( ByVal sender As System.Object, ByVal e As System.EventArgs )


Handles sendmail.Click
If emailaddr.Text = "" Then
MessageBox.Show ( "Please enter email address" )
Return
End If

Dim myMail As New MailMessage( )


myMail.From = fromaddr.Text
myMail.To = emailaddr.Text
myMail.Subject = emailsubject .Text
myMail.BodyFormat = MailFormat.Text

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

myMail.Body = message.Text
SmtpMail.Send ( myMail )
End Sub

How do I write code that pops up a context sensitive menu on right clicking onto a combo
box?

Ans: Follow the steps given below.

1. Create a Windows Application and place a combo box named cb on the form. Add a context
menu on the form named
combomenu and add an item cadd in the menu.

2. Set the text property of the menu item cadd as "ADD".

3. Set the ContextMenu property of the combo box as combomenu.

4. Add the Click event handler for the cadd menu item and enter code given below in it.

Private Sub cadd_Click ( ByVal sender As System.Object, ByVal e As System.EventArgs )


Handles cadd.Click
If cb.FindStringExact(cb.Text) = -1 Then
cb.Items.Add(cb.Text)
End If
End Sub

Here, we have not only added a context sensitive menu but also given a provision that on
clicking the menu item 'ADD", the text typed in the combo box should get added in the dropdown
list. If the text is already present in the dropdown list it would not get added to the list.

How do I write code that uses ListView control to display list of records?

Ans: Create a Windows application and place three text boxes named empname, age, sal for
writing name, age and salary of an employee. Place a button called 'Add' and a list view control
on the form. On clicking 'Add' button information in all edit boxes should get added in the list view
under appropriate column. Set the View property of list as Details. Click on the Columns
property in the Property Window for list, add three columns to list in ColumnHeader Collection
Editor and set their Text Properties as 'Name', 'Age', 'Salary' respectively. Then add following
code in the Click Event handler of the 'Add' button.

Private Sub adddata_Click ( ByVal sender As System.Object, ByVal e As System.EventArgs )


Handles adddata.Click

Dim litem As New ListViewItem( )


litem.Text = empname.Text
litem.SubItems.Add ( age.Text )
litem.SubItems.Add ( sal.Text )
list.Items.Add ( litem )

End Sub

How do I write code that sends a mail via outlook express?

Ans: Create a Windows application and place a button named sendmail and a text box named

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

emailaddr on the form. On adding the email address to the text box if sendmail button is clicked
'OutLook Express' dialog box should get popped up with an email address written in the text box.
To get so write following code in the button handler.

Private Sub sendmail_Click ( ByVal sender As System.Object, ByVal e As System.EventArgs )


Handles mailsend.Click
If emailaddr.Text = "" then
MessageBox.Show ( "Enter The Email Address" )
Return
End If
System.Diagnostics.Process.Start ( "mailto:" & emailaddr )
End Sub

How do I write code that shows check boxes in the list view and displays the text in a
message box when a check box is checked?

Ans: Create a Windows application and place a list view control named as list on the form. Set
its ShowCheckBoxes property to true and view property as List. Add items in the list by clicking
on Items property in the 'Properties'. Set the Text property of each item in the 'ListViewItem
Collection' editor. To be able to make use of ListviewCollection class write following statement
in Form1.vb at the top.

Imports System.Windows.Forms.ListView

Now, add ItemCheck event handler of list and write following code in the ItemCheck event
handler.

Private Sub list_ItemCheck ( ByVal sender As Object, ByVal e As


System.Windows.Forms.ItemCheckEventArgs )
Handles list.ItemCheck
Dim icoll As ListViewItemCollection = list.Items
Dim litem As ListViewItem = icoll.Item ( e.Index )

If e.NewValue = CheckState.Checked Then


MessageBox.Show ( litem.Text )
End If
End Sub

How do I display an icon of an application in system tray and display context menu for it?

Ans: Create a Windows application and place NotifyIcon control on the form. Name it as
trayicon. Add an icon to your application and name it as myicon. Set the Icon property of
trayicon as myicon. Place a ContextMenu control on the form and name it as trayconmenu.
Add one item to the menu having text 'Exit' and name as ex. Set the ContextMenu property of
trayicon as myconmenu.

Add handler for click event for ex menu item and write following code in it.

Private Sub ex_Click ( ByVal sender As System.Object, ByVal e As System.EventArgs ) Handles


ex.Click
Application.Exit( )
End Sub

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

How do I write code to display contents of a file in a multi-line text box?

Ans: Create a Windows application. Place two text boxes named filepath and filetext, and two
buttons named browse and open on the form. Set the two properties Mutiline and ScrollBars of
filetext to True and Both respectively. Then drag OpenFileDialog control on the form. Name it
as opendlg and set its Filter property to 'Text files (*.txt)|*.txt'. Add click event handlers for both
the buttons browse and open. Write following code in button handler for browse:

Private Sub browse_Click ( ByVal sender As System.Object, ByVal e As System.EventArgs )


Handles browse.Click
opendlg.ShowDialog( )
If opendlg.FileName <> "" Then
filepath.Text = opendlg.FileName
End If
End Sub

Here, we have used StreamReader class hence write following line at the top in Form1.Vb file

Imports System.IO

Now, add following code in the click event handler of open button.

Private Sub open_Click ( ByVal sender As System.Object, ByVal e As System.EventArgs )


Handles open.Click
Dim reader As StreamReader = New StreamReader ( filepath.Text )
filetext.Text = reader.ReadToEnd( )
reader.Close( )
End Sub

How do I write code to display a Splash Screen for an application?

Ans: Create a Windows application. Add another form named SplashForm to the application by
selection Project | Add | Windows Form menu item. Insert a picture box on the SplashForm.
Copy a '.bmp' say 'Splash.bmp' to the project. Set the Image property of the picture box to the file
name 'Splash.bmp'. Change the BackColor and BorderStyle property of SplashForm to White
and none respectively. Set the TransparencyKey of SplashForm as White. Then write following
code in the constructor of Form1.

Public Sub New( )


MyBase.New()
'This call is required by the Windows Form Designer.
InitializeComponent( )
'Add any initialization after the InitializeComponent() call
Dim f As New SplashForm( )
End Sub

Write following code in constructor of SplashForm.

Public Sub New( )


MyBase.New( )
'This call is required by the Windows Form Designer.
InitializeComponent( )

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

'Add any initialization after the InitializeComponent( ) call


Show( )
Application.DoEvents( )
Thread.Sleep ( 1000 )
Dispose( )
End Sub

Accessing Database Using OLEDB.NET...

Create a database called bank and add a table called account with three fields accno, name
and balance. Create a console application. In this application we will connect to the database
and display the contents of the table account on the console output. To be able to use class
OLEDBDataReader write following line at the top in 'Module1.Vb'.

Imports System.Data.OleDb

Create the connection string and the command strings. Then create OleDbConnection object
and OleDbCommand object. Using the command object execute the query. Write code in Sub
Main( ) as shown below:

Sub Main( )
Dim connectionstr As String = "Provider = Microsoft.Jet.OLEDB.4.0 ;Data Source =
c:\bank.mdb"
Dim commandstr As String = "SELECT accno, name, balance from account"

Dim connection As New OleDbConnection ( connectionstr )


Dim command As New OleDbCommand ( commandstr, connection )
connection.Open( )
Dim r As OleDbDataReader = command.ExecuteReader( )

While r.Read( )
Console.WriteLine ( r(0) & r(1) & r(2) )
End While
connection.Close( )
End Sub

How do I declare variables as read only in VB.NET?

Ans: VB.NET provides a keyword ReadOnly which is used for variables which are to be
initialized at the time of building the objects. The following code shows how to declare variables
as ReadOnly.

Module module1
Class hotel
Public ReadOnly name As String
Sub New ( ByVal n As String )
name = n
End Sub
End Class

Sub main( )
Dim h As New hotel ( "Tuli" )
End Sub

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

End Module

We cannot assign any value to a ReadOnly Variable. Hence the statement h.name = "CP" would
give us an error. i.e h.name cannot be written on the left side of the assignment operator.

Properties In VB.NET...

Properties of a class are actually methods that work like data members .The properties are used
to store and retrieve the values to and from the data members of the class. The following code
shows how to declare a property called Length within a class called sample.

Module Module1
Class sample
Dim len As Integer
Property Length( ) As Integer
Get
Return len
End Get
Set ( ByVal Value As Integer )
len = Value
End Set
End Property
End Class
Sub Main( )
Dim s As New sample( )
s.Length = 10
Dim l As Integer = s.Length
Console.WriteLine( l )
End Sub
End Module

To store and retrieve the len data member of the class sample the Length property is used. A
property has two special methods known as a Get accessor and a Set accessor. The Get
accessor never accepts any value and the Set accessor never returns any value. The value
collected by the Set accessor is stored in an implicit parameter called Value.
The statement m.Length = 10 would invoke the Set accessor and the statement len = m.Length
would invoke the Get accessor.

What does .Net framework consist of?

Ans: The .Net framework consist of the following:


• Class Library which contains Language Independent classes
• Virtual Machine which is known as Common Language Runtime used to run native code
• Development Environment comes in the form of Visual Studio.Net which supports VB, VC++
& C# to create Portable Executable files and components

What is Microsoft Intermediate Language (MSIL)?

Ans: MSIL is a CPU-independent set of instructions. It is like bytecode in Java. MSIL code under
.Net is stored in EXEs or DLLs. EXEs are known as (portable executable) file.

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

Once our source code is written, we compile it, and the language compiler translates it to MSIL
code. Before the MSIL code can be executed it is converted to native code by Just In Time (JIT)
Compilers.
C# data types can be divided in two categories: value types and reference types.
Value types are allocated on the stack. When we assign one instance of a value type to another
instance of the value type, we get two separate copies of the same value in memory. int, byte,
short, double, etc. are the examples of value type.
Reference types are allocated on the heap. Assigning one instance of a reference type to another
instance of the reference type results in two references pointing to the single object. All the user
defined classes as well as string and object classes are of reference types. The object type is the
ultimate base type of all types

In C++ primitive data types were simple variables not objects. C++ did not provide any way to
convert the variables into objects. Java made an attempt has been made to represent everything as
an object. However, problem arises when primitive data types appear in the scene. Java separated
the primitive data types from objects. Java treats primitive data types as variables but also provides
wrapper classes to convert the primitive data types into objects. C# uses the third way. In C#, the
basic types are actually value types but can also be used as objects. For using the value type
variable as an object we do not require to use wrapper classes. Following code snippets show how
an int variable can be used as an object.

int n = 10 ;
string s = n.ToString( ) ;

string s = 10.ToString( ) ;

Here, ToString( ) function of object class gets called.

Why in C#, uninitialised variables do not contain garbage value?

In C or C++ initial value of variable is garbage value. This is not so in C#. The reason is that all
value types implicitly declare a public zero argument constructor called the default constructor.
The default constructor initialises the instance with the value according to the value type. For
example, an int is initialized with 0, bool with false, char with '\0', etc.
Like any other constructor, the default constructor of a value type is invoked using the new
operator. Because every value type implicitly has a public parameterless constructor, it is not
possible for a struct type to contain an explicit declaration of a parameterless constructor.
However, a struct type is permitted to declare parameterized constructors.
checked and unchecked operators :
Sometimes while performing mathematical calculations we may add two integers which results
into a long. This results into an unpredictable result. C# provides two operators checked and
unchecked which can be used to avoid such results. These operators control overflow checking
for arithmetic operations and conversions of integral type. If an operation is checked and if
overflow occurs an exception is thrown. If the operation is unchecked, the overflowing bits (higher
bits) are discarded and the number corresponding to the remaining bits is stored. Consider the
following code:
public static void Main ( string args[ ] )
{
int a = 60000, b = 50000, c = 0, d = 0 ;
try
{

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

d = checked ( a * b ) ;
}
catch ( System.OverflowException e )
{
Console.WriteLine ( e ) ;
}
c=(a*b);
Console.WriteLine ( "the result is {0} {1}",c , d ) ;
}
In the first case when ( a * b ) is checked an exception gets thrown as the result goes out of
scope of an int variable. In the second case the result is -1294967296 0. checked and
unchecked operators work for int, uint, long and ulong data types.
Switch-case statements do not fall through in C#...

Unlike C and C++, execution of a switch in C# is not permitted to 'fall through' to the next section.
This is because writing break in a case section is necessary. Thus, the following code would get
executed in C and would print all the statements but in C# it would flash an error.

switch ( grade )
{
case 'A' :
Console.WriteLine ( "This is A" ) ;
case 'B' :
Console.WriteLine ( "This is B " )
case 'C' :
Console.WriteLine ( "This is C" ) ;
case 'F' :
Console.WriteLine ( "This is F" ) ;
}

When execution of a case section is to be followed by another case section, we must use explicit
goto statement at the end of the section.
For example, goto case 'B' ;
This will transfer the control to case 'B' section. We can specify an integer, character and string
types in switch statement.
Strings - quoted and @-quoted

CSharp supports two types of string literals, quoted and @-quoted. Quoted strings are normal
strings that support escape sequences. If we want the compiler not to process the escape
sequences we can use @-quoted strings i.e we can preface the string with an @ symbol. The
main advantage of @-quoted string is that it simplifies the expression of path names. For
example,

string s1 = @"C:\Articles\text.txt" ; // here the escape sequences are not expanded


string s2 = "C:\\Articles\\text.txt" ; // here escape sequences are processed to get a literal
backslash

string s3 = "hi \t there" ; // output: hi there


string s4 = @"hi \t there" ; // output: hi \t there
How to create user-defined exceptions?

We can create our own exceptions by creating a class and deriving it from System.Exception
class. Creating our own exception class enables users of our class to take different actions based
on that exception. For example, if we want that value of a variable, say x, should not exceed 10
then we can design our class like this.

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

public class myexception : Exception


{
public string i ;
public myexception ( string x ) : base ( x )
{
}
}

Calling the base class constructor is mandatory here. We can throw this exception anywhere in
the program in the following manner:

if ( x > 10 )
throw new myexception ( "Value out of Range" ) ;
The new modifier

Suppose a base class has a virtual function and the virtual function is overridden in the derived
class. If we store a reference of derived class in an object of base class and try invoking the
function, the function from the derived class is called. If we don't override the virtual function, the
function from the base class is called. But along with this, a warning is flashed.
To remove this warning and call the function of the base class we have to add the a modifier
called new to it. The new modifier is used to explicitly hide a member inherited from a base class.

C# destructors and Finalize( ) method

In C++ whenever an object gets destroyed the destructor of that class gets called. In C# the
destructor does not work in this manner. A C# destructor is nothing but a Finalize( ) method in
disguise. The Garbage Collector calls the Object.Finalize( ) method immediately before the
object is collected (destroyed).

We can not tell when the garbage collector gets called and when the object gets destroyed
because C# runtime schedules garbage collections when it feels they’re necessary. It is quite
possible that the destructor we wrote never gets called. If we write the destructor and the
Finalize( ) method in the same class the compiler flashes error

String Comparison

In C# we can use == operator to compare two strings, but the comparison done will be case
sensitive. Method Compare( ) can be used for both, case sensitive as well as case-insensitive
string comparison. If we pass true as the last parameter to the Compare( ) method the
comparison becomes case insensitive. Following code snippet illustrates this:

string str1 = "hello" ;


string str2 = "HELLO" ;
bool chk1 = ( str1 == str2 ) ; // output is false
int chk2 = ( String.Compare ( str1, str2, true ) ) ; // output is 0, meaning strings are equal
Function Overloading

Value, Reference, Output and Parameter Array can be used to overload a function. Consider the
following program.

public class Class1


{
public static int Main ( string[] args )

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

{
int x = 10, y = 20, z = 30 ;
Func ( x , y ) ; Console.WriteLine ( x + " " + y ) ;
Func ( ref x, ref y ) ; Console.WriteLine ( x + " " + y ) ;
int p, q ;
Func ( out p, out q ) ; Console.WriteLine ( p + " " + q ) ;
Func ( x, y, z ) ; Console.WriteLine ( x + " " + y + " " + z ) ;
return 0 ;
}

public static void Func ( int a, int b )


{
a++ ; b++ ;
}

public static void Func ( ref int a, ref int b )


{
a++ ; b++ ;
}

public static void Func ( out int a, out int b )


{
a = 88 ; b = 77 ;
}

public static void Func ( params int[] args )


{
foreach ( int i in args )
i++ ;
}
}

The output is as follows:


10 20
11 21
88 77
11 21 30

Here, we have overloaded the function Func( ). The first call to Func( ) calls the first function
defined. Here the parameters are value parameters and after execution we see that the change is
not reflected in Main( ).
On the second call, the second function is invoked where parameters are reference parameters.
Whatever changes are made in the function are reflected in Main( ).
On the third call, the unassigned variables p and q (output parameters) get assigned and the
values are reflected in Main.
In the last function, we have used a parameter array, so the variables x, y and z are passed in the
array. The changes are not reflected in Main( ).
The WinCV Tool

The WinCV Tool is a class viewer tool. It displays all methods, properties, events and fields of the
specified class in C# syntax. In the left hand side pane we get the class name and the
namespace in which the class is contained. We get the definition of the selected class in the right
hand side pane. This side also gives us which assembly the class is defined in.

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

We must type in our string in the 'Searching For' box. As we type, the WinCV tool displays all the
classes that contain the search string.
We can start the WinCV Tool by typing in wincv at the command prompt or clicking on the file in
Windows Explorer. 'WinCV.exe' is present in 'C:\Program Files\Microsoft.Net\FrameworkSDK\Bin'.
How do I create a transparent brush?

Ans: We can create a transparent brush by changing the alpha component in the FromARGB( )
method of the Color class. To create the transparent brush we must set the alpha element to a
value less than 255. The alpha value ranges from 0 (fully transparent) to 255 (fully opaque). The
default value of alpha is 255 i.e. opaque. The first parameter passed to FromARGB( ) method is
the alpha value.

protected void Form1_Paint ( object sender, System.WinForms.PaintEventArgs e )


{
Graphics d = e.Graphics ;
SolidBrush s = new SolidBrush ( Color.FromARGB ( 255, 0, 0 ) ) ;
Font f1 = new Font ( "Times New Roman", 20 ) ;
d.DrawString ( "Hello", f1, s, 100, 100 ) ;

Font f = new Font ( "Times New Roman", 200 ) ;


SolidBrush s1 = new SolidBrush ( Color.FromARGB ( 150, 255, 255, 0 ) ) ;
d.DrawString ( "Hello", f, s1, 50, 50 ) ;
}

Thus, the second string drawn is transparent and the first string becomes visible in background,
which otherwise would have been overwritten
Threading in C#

In C# to start a new thread we create a new object of the class Thread. To the constructor of this
class, an object of the class ThreadStart is passed. The ThreadStart class is a delegate that
points to the method that should be executed first when a thread is started. When the Start( )
method is called, the new thread will begin executing at the ThreadStart delegate passed in the
constructor.

public static void NewThread1 ( )


{
for ( int i = 0 ; i <= 500 ; i++ )
Console.WriteLine ( "Second thread " + i ) ;
}

public static int Main ( string [ ] args )


{
Thread t1 = new Thread ( new ThreadStart ( NewThread1 ) ) ;
t1.Start( ) ;
for ( int i = 0 ; i <= 500 ; i ++ )
Console.WriteLine( "First thread " + i ) ;
}

Here since we have used threading both the loops will run simultaneously.
How does the Garbage Collector work?

Ans: The Garbage Collector takes information from the CLR (Common Language Runtime)
about the running application. It obtains a list of objects that are directly referenced by the
application. Then it finds out all indirect references through the direct references. After it finds out
information about these objects, it cleans up the rest of them, and compacts the remaining heap.

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

The Garbage Collector calls the Object.Finalize( ) method immediately before the object is
collected. Programmers can use the Finalize( ) method to do any necessary cleanup when
dealing with reference types.
The using statement...

Obtaining resources, executing them and disposing them off is done by the using statement. A
resource is a class or structure that implements System.IDisposable.interface. The using
statement is translated into 3 parts: acquisition, usage, and disposal. Consider the following
program
using System;
namespace resourse1
{
class Class1
{
static void Main ( string[ ] args )
{
using ( myclass m = new myclass( ) )
{
m.myfunc( ) ;
}
}
}
}
class myclass : IDisposable
{
public myclass( ) { Console.WriteLine ( "In Constructor" ) ; }
public void myfunc( ) { Console.WriteLine ( "In myfunc" ) ; }
public void Dispose( ) { Console.WriteLine ( "In Dispose" ) ; }
}
First the constructor gets called, then the myfunc( ) method and lastly the Dispose( ) method
gets called.

User Defined Conversions


We can overload explicit and implicit conversions. We can define operators for a class to convert
objects to and from other types. They are very similar to C++ type conversion operators.

public class class1


{
static void Main ( string[ ] args )
{
mystr s = ( mystr ) "Hello" ; //Explicit conversion requires explicit casting
s.show ( ) ;
string s1 = s ; //Implicit conversion does not require explicit casting
Console.WriteLine ( s1 ) ;
}
}

public class mystr


{
string str ;
mystr ( string st )
{
str = st ;
}

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

public static explicit operator mystr ( string s )


{
return new mystr ( s ) ;
}
public static implicit operator string ( mystr s )
{
return s.str ;
}
public void show ( )
{
Console.WriteLine ( str ) ;
}
}

The implicit and explicit modifiers determine the context a conversion will be done.
The Conditional Attribute...

Attributes are items of declarative information in our code. We have used the Conditional attribute
here. This attribute marks a method as conditional. This means the function executes only if the
preprocessing identifier is defined.
#define x
using System ;
using System.Diagnostics ;
class Class1
{
static void Main ( string[ ] args )
{
hello( ) ;
}
[ Conditional ( "x" ) ] public static void hello( )
{
Console.WriteLine ( "hello world " ) ;
}
}
If we comment out the #define directive, the function hello( ) would not get executed.
File and FileInfo

.Net offers two classes for file operations - the File class and the FileInfo class. The File class is
derived from the Object class. It contains static methods and never gets instantiated. The
FileInfo class is derived from FileSystemInfo class and has instance methods. This class can be
instantiated.
When we have to use a single file and perform many operations on it, we should use the FileInfo
class. But if we want to perform a single operation on a file we must use the File class. This way
we avoid the overhead of instantiating an object for just a single operation. But then when we
have to marshal files we have to use the FileInfo class, because this class inherits from the
MarshalByRefObject class used for marshalling data.
A constructor initializer of the form base( ) causes a constructor from the direct base class to be
invoked. A constructor initializer of the form this( ) causes a constructor from the class itself to be
invoked. Consider the following program
public class Class1
{
static void Main ( string [ ] args )
{
second s = new second ( ) ;

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

second s1 = new second ( 10 ) ;


}
}
public class first
{
public first ( )
{
Console.WriteLine ( "constructor of the base class" ) ;
}
public first ( int i )
{
Console.WriteLine ( "one arg constructor of the base class" ) ;
}
}
public class second: first
{
public second ( ) : this ( 10 )
{
Console.WriteLine ( "constructor of the derived class" ) ;
}
public second ( int i ) : base ( 10 )
{
Console.WriteLine ( "one arg of constructor of the derived class" ) ;
}
}
The output would be :
one arg constructor of the base class
one arg constructor of the derived class
constructor of derived class
one arg constructor of the base class
one arg constructor of the derived class
When we call the zero argument constructor of class second, it first calls its own one argument
constructor, this in turn first calls the zero argument constructor of class first. When we call the
one argument constructor of class second, it first calls the one argument constructor of class
first
Application Domain...

Application Domain means a security boundary between any two applications. This is used for
isolation of applications. Before .Net every process had its own private virtual memory avoiding it
to meddle with other processes memory. Now in .Net we have application domains. With
managed IL code the runtime can assure that access to the memory of another application inside
a single process can't happen. Multiple applications can run in a single process within multiple
application domains. To execute an exe file in our program we have to write the following:
AppDomain first = AppDomain.CreateDomain ( "test1.exe" , null , null ) ;
first.ExecuteAssembly ( " test1.exe " ) ;
Before running this second application we must make sure that we copy the .exe of the first
application (test1.exe) in the 'bin / debug' folder of this application, so that the assembly is found.
We cannot add a reference to it because references to only DLLs can be added and ours is an
exe.
The CreateDomain( ) methods creates a new application domain and the ExecuteAssembly( )
method executes the assembly given its file name.
Shared and Private Assemblies...

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

There are two types of assemblies available: private assemblies and shared assemblies. A
private assembly is used by only one application while a shared assembly is shared among
different applications.
By default when we compile a C# program, the assembly produced will be a private assembly. A
private assembly is found either in the same directory as the application or within its
subdirectories. With a private assembly it's not necessary to think about naming conflicts with
other classes or versioning problems because each application has its own copy of the assembly.
In shared assemblies we must be careful that the assembly must be unique, and therefore, have
a unique name (called a strong name). Most of the shared assemblies are stored in a Global
Assembly Cache.

Delegates

We normally pass data of any kind to a function. A situation may arise where we may want to
pass a function to a function. This would seem a bit strange but this does happen. A method may
need another method to do something. In such situation we may not even know which method to
pass We may need to pass it at run time. But simply passing a function name to other function
does not solve the problem because this approach causes problems with type safety. We cannot
just pass methods directly because we need objects to access them.

To tackle such situations Delegates have come into picture. Delegates are special types of
objects used to wrap up details of methods we need to pass. Delegates are very similar to
function pointers in C++. Delegate type is a class type derived from System.Delegate. Delegate
types are implicitly sealed i.e. it is not permissible to derive from a delegate type. There are three
steps in defining and using delegates: declaration, instantiation, and invocation.

Consider the following example:


public class Class1
{
static void Main ( string [ ] args )
{
myclass m = new myclass ( ) ;
m.call ( ) ;
}
}
class myclass
{
public delegate void myfunc ( ) ;
void func1( )
{
Console.WriteLine ( " In func1 " ) ;
}
void func2( )
{
Console.WriteLine ( " In func2 " ) ;
}
public void call( )
{
myfunc f = new myfunc ( func1 ) ;
f();
f = new myfunc ( func2 ) ;
f();
}
}

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

In this program we have created a class called myclass. In Main( ) we created an object of this
class through which we have called the call( ) function. In this call( ) function, we have created a
delegate object called f and passed the name of the method to be used in it. So as the name
suggests the delegate object is delegating the actual process of the method we call. Hence on
writing f( ), func1( ) gets called. Next time we passed the name of the second function, func2( ).
This time func2( ) is executed when we write f( )

Event

An event is a member that enables the object to provide notifications. When such notifications
are sent we need something to be done. This something is always done inside a method. Such
methods that are called when an event is raised are known as event handlers. For example when
a mouse is clicked the event sent is MouseClick and the event handler is OnCLick( ).

The event model uses delegates to bind events to the methods used to handle them. The
delegate allows other classes to register for event notification by specifying a handler method.
When the event occurs, the delegate calls the bound method. Delegates can be bound to a single
method or to multiple methods, referred to as multicasting. When creating a delegate for an
event, we typically create a multicast event. A multicast delegate maintains an invocation list of
the methods it is bound to.

When an event is recorded by the application, the control raises the event by invoking the
delegate for that event. The delegate in turn calls the bound method. In the most common case
the delegate calls each bound method in the invocation list in turn, which provides a one-to-many
notification. This strategy means that the control does not need to maintain a list of target objects
for event notification - the delegate handles all registration and notification.

Consider the following program:

namespace handle
{
using System ;
class Class1
{
static void Main ( string[] args )
{
keyboard k = new keyboard ( ) ;
k.OnHit += new hit ( k.hit1 ) ;
k.OnHit += new hit ( k.hit2 ) ;
k.keyhit( ) ;
k.OnHit -= new hit ( k.hit1 ) ;
k.keyhit( ) ;
}
}
public delegate void hit( ) ;
public class keyboard
{
public event hit OnHit ;
public void keyhit( )
{
if ( OnHit != null )
{
OnHit( ) ;
}

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

}
public void hit1( )
{
Console.WriteLine ( "Key Hit1" ) ;
}
public void hit2( )
{
Console.WriteLine ( "Key Hit2" ) ;
}
}
}

The output here is:

Key Hit1
Key Hit2
Key Hit2

We have declared a class called keyboard. In this class we added an event called OnHit. Two
simple functions hit1( ) and hit2( ) are also added. The keyhit( ) method raises the OnHit event.
The notion of raising an event is precisely equivalent to invoking the delegate represented by the
event. Outside the class, the OnHit member can only be used on the left hand side of the += and
-= operators, as in k.OnHit += new hit ( k.hit1 ) which actually appends a delegate to the
invocation list of the OnHit event and -= removes a delegate from the list. Hence as soon as we
call k.keyhit( ) it raises the event and all functions are executed.

Pointers (unsafe code)

Pointers can be used in C# just as in C++ but only in blocks of code that we have specifically
marked for pointer use. The keyword to do so is unsafe. 'unsafe' because there are potential risks
associated with pointers such as memory leaks, overwriting of important information, stack
overflow etc. Code using pointers is difficult to debug and will fail the memory type safety checks
imposed by the Common Language Runtime (CLR). We can mark individual methods, classes,
structs, blocks of code or even local variables as unsafe. For example we could write:

unsafe float myfunction( )


{
// can use pointers
}
unsafe class myclass
{
unsafe int *x ;
}
unsafe
{
// unsafe block
}

Declaring a pointer is different in C# than in C++, for example if we want to declare two integer
pointers, we will write:

int *x, y ;

in C# as against

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

int *x, *y ;

in C++.

Once we've declared the pointers, we can use them as normal pointer variables using the
'address of' (&) and the 'value at' (*) operators. For the most part, C# relies on references for
instances of classes, and the language has been designed in such a way that pointers are not
required nearly as often as they are in C++.

The .NET Data Providers

There are two .NET data providers available, the SQL Server .NET Data Provider and the
OLEDB .NET Data Provider. Depending on the design and data source for our application we
can use any one of these two. The SQL Server .NET Data Provider uses its own protocol to
communicate with the SQL Server. The OLEDB .NET Data Provider uses native OLEDB through
COM interoperability to enable data access. To use the SQL Server .NET Data Provider, you
must have access to Microsoft SQL Server 7.0 or later. SQL Server .NET Data Provider classes
are located in the System.Data.SqlClient namespace. To use the OLEDB .NET Data Provider,
you must use an OLE DB provider (we have used Microsoft Access). OLEDB .NET Data
Provider classes are located in the System.Data.OleDb namespace. To use the OLEDB .NET
Data Provider, you will have to include the System.Data.OleDb namespace in your applications.
These .NET providers include the Connection object, the Command Object, the DataReader
and the DataAdapter in their corresponding namespaces. For e.g. the Connection class in the
SQL Server .NET Data Provider is written as SqlConnection and its equivalent in the OLEDB
Service Provider is written as OleDbConnection. In the same way for all the four classes the
corresponding names are prefaced with Sql or OleDb accordingly.

Default Parameters In C#...

Methods in C# cannot have default parameters. We cannot overload methods with default
parameters. No such syntax exists in C#.

myfunction ( int x = 0, int y = 10 )


{
}

If we want a function to initialize default values to the variables like default parameter mechanism,
we'll have to simulate it. There is not specific syntax. We have to do it manually and initialize the
variables in the beginning of the function definition as shown below.

myfunction ( int x, int y )


{
x=0;
y = 10;
}

Using OLE DB .NET Data Provider in ADO.NET...

using System;
using System.Data;
using System.Data.OleDb;
class myclass
{

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

static void Main ( string[ ] args )


{
string str = "Provider = Microsoft.Jet.OLEDB.4.0 ; Data
Source = c:\\bank.mdb" ;
string cmd = "SELECT accno, name, balance from account" ;
OleDbConnection con = new OleDbConnection ( str ) ;
OleDbCommand com = new OleDbCommand ( cmd, con ) ;
con.Open( );

OleDbDataReader r = com.ExecuteReader ( ) ;
while ( r.Read ( ) )
Console.WriteLine ( r[0] + " " + r[1] + " " + r[2] ) ;
con.Close ( ) ;
}
}

To make a connection, we pass the connection string to the OleDbConnection constructor. To


the OleDbCommand constructor we pass the connection as well as the command string. The
Open( ) method opens a database connection with the property settings specified by the
connection string. The OleDbDataReader class reads a stream of rows from database. To create
an OleDbDataReader class we have to call the ExecuteReader( ) method belonging to the
OleDbCommand class. This method will execute the command and return an
OleDbDataReader object. The Read( ) method iterates through the records advancing the
OleDbDataReader by one record every time. we have used the ordinal indexer to access
individual values of a row referenced by the OleDbDataReader.

Using SQL Server .NET Data Provider...

using System;
using System.Data;
using System.Data.SqlClient;
class myclass
{
static void Main ( string[ ] args )
{
string str = "server = kicit ; uid = icit ; pwd = ypk ; Database = bank" ;
string cmd = "SELECT accno, name, balance from account" ;
SqlConnection con = new SqlConnection ( str ) ;
SqlCommand com = new SqlCommand ( cmd, con ) ;
con.Open( ) ;

SqlDataReader r = com.ExecuteReader ( ) ;
while ( r.Read ( ) )
Console.WriteLine ( r[0] + " " + r[1] + " " + r[2] ) ;
con.Close ( ) ;
}
}

First we need to get connected to the database. To do so, we have to write a connection string.
The connection string includes database name, server, database provider, user name, password.
This connection string is stored in str. The command string is stored in cmd. cmd contains the
query to be executed. To make a connection, we pass the connection string to the
SqlConnection constructor. To the SqlCommand constructor we pass the connection as well as
the command string. The Open( ) method opens a database connection with the property settings

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

specified by the connection string. The SqlDataReader class reads a stream of rows from an
SQL Server database. To create an SqlDataReader class we have to call the ExecuteReader( )
method belonging to the SqlCommand class. This method will execute the command and return
an SqlDataReader object. The Read( ) method iterates through the records advancing the
SqlDataReader by one record every time. Here we have used the ordinal indexer to access
individual values of a row referenced by the SqlDataReader.

The ILDASM Tool...

The ILDASM or the MSIL disassembler tool is used to view assemblies. We can run this tool by
starting ildasm from the command line, with the assembly as argument or by selecting the 'File |
Open' menu. The following figure shows an ildasm window with assemblies opened in it.

The tool shows the Manifest, Namespace, Class and Method in the assembly. It can also show
Interfaces, Value types, Static methods, Fields, Static Fields, Events and Properties.

Structure of an Assembly

An assembly is made up of metadata , IL (Intermediate Language) code and resources. The


Metadata consists of type metadata and an assembly metadata. Assembly Metadata which is
referred to as the Manifest describes assembly. It contains following information.

a. An identity, name, version and culture of an assembly. An assembly has a four part
version number e.g. 1.0.1.1. which stands for

<Major> . <Minor> . <Build> . <Revision>

The use of these numbers is dependent on the configuration of our application. A good policy is to
change the major or minor numbers if the version is incompatible with the previous versions. The
build number is the number of days since Jan-1, 2000, and revision is the number of seconds
since midnight local time.

b. Names of all files in an assembly.


c. Details of all types defined in an assembly.

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

d. Whether the types defined in an assembly are visible to other assemblies or not.
e. A hash of all files in an assembly.
f. Names and hashes of other assemblies that an assembly may need as reference while
execution
g. Details of any security permissions that clients need to have in order to be able to run the
assembly

The type metadata consists of metadata that describes the exported types and methods.

How do I change the underlying data type for an enum?

Ans: The following program demonstrates how we can change the underlying data type (which is
int by default) for an enum. We have provided an initial value to one of the members of the
enum.

using System ;
namespace sample
{
enum color : byte
{
red, blue = 8, green
}
class Class1
{
static void Main ( string[ ] args )
{
Console.WriteLine ( color.green ) ;
}
}
}

The output of the program would be green. But here we have to be careful that we should not
use a value, which is out of range. For example assigning a value like 500 to red in this program
will result in error since we have declared that the enum is of type byte. Using,
Console.WriteLine ( ( byte ) color.green ) instead of Console.WriteLine ( color.green ) in
Main( ) would give the output as 9. This is because, all members towards the right of blue will be
initialized to a value equivalent to blue's value plus the number of places it is far from blue. The
value green is one place right from blue, its value will be 8 + 1 i.e. 9. This is not true for members
on the left hand side. So in this case red will be initialized to 0 by the compiler. However we can
initialize all the members with different values.

How do I change the underlying data type for an enum?

Ans: The following program demonstrates how we can change the underlying data type (which is
int by default) for an enum. We have provided an initial value to one of the members of the
enum.

using System ;
namespace sample
{
enum color : byte
{
red, blue = 8, green

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

}
class Class1
{
static void Main ( string[ ] args )
{
Console.WriteLine ( color.green ) ;
}
}
}

The output of the program would be green. But here we have to be careful that we should not
use a value, which is out of range. For example assigning a value like 500 to red in this program
will result in error since we have declared that the enum is of type byte. Using,
Console.WriteLine ( ( byte ) color.green ) instead of Console.WriteLine ( color.green ) in
Main( ) would give the output as 9. This is because, all members towards the right of blue will be
initialized to a value equivalent to blue's value plus the number of places it is far from blue. The
value green is one place right from blue, its value will be 8 + 1 i.e. 9. This is not true for members
on the left hand side. So in this case red will be initialized to 0 by the compiler. However we can
initialize all the members with different values.

An enum cannot have a circular definition. For example,

enum color
{
red = yellow, blue, green, yellow, brown
}

The compiler will first try to give red yellow's value. But yellow's value depends on red's value.
Hence yellow has no value yet and will be assigned a value later. This is circular dependency
and is not allowed in enumerations.

When we perform an assignment operation on two reference variables, the reference to the first
object gets copied into the other reference variable. But this is not the case with strings. In spite
of being a reference type an assignment operation on two string variables results in creation of a
new object. The value of the right-hand side string object gets copied into the new object and the
reference to this new object gets assigned to the reference variable on the left-hand side of the
assignment operator. This is shown in the following code snippet.

string s1 = "Good Morning" ;


string s2 ;
s2 = s1 ;
s1 = "Wake Up" ;
Console.WriteLine ( s1 ) ;
Console.WriteLine ( s2 ) ;

The output of the program would be,

Wake up
Good Morning

Here we have created two string references — s1 and s2. We have initialized s1 with a reference
to an object containing “Good Morning” and kept s2 uninitialized. Then we have assigned s1 to
s2. Normally both being references only the reference of s2 should have been assigned to s1.

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

But this does not happen. Instead a new object gets created that holds the same value contained
in the object referred by s1.

Properties...

In C#, we can manipulate data stored in a data member using a feature called Properties. The
methods that we write as properties are known as accessors. There can be two accessors, a get
accessor and a set accessor. The get accessor is invoked when we want to retrieve the value of
the property, whereas the set accessor is invoked when we assign a value to the property If only
get accessor is present the property is called a read-only property. If only set accessor is present
then the property is called a write-only property. If both accessors are present, the property is said
to be a read-write property. The following program demonstrates how we can create and access
properties.

using System ;
namespace properties
{
public class sample
{
int width ;
public int Width
{
get
{
return width ;
}
set
{
width = value ;
}
}
}
class Class1
{
static void Main ( string[ ] args )
{
sample m = new sample( ) ;
m.Width = 10 ;
int w = m.Width ;
Console.WriteLine ( "Width: " + w ) ;
}
}
}

Here, the class sample, contains both the get and set properties for the data member width. In
Main( ), the statement m.Width = 10 ; would invoke the set property whereas the statement int
w = m.Width ; would invoke the get property.

Properties Vs Data members...

The advantage of using properties as against public data member is that, if we want we can
perform some functionality in the accessor body. For example if we wish to initialize a lenght
property, we can first check range for the length variable in the set accessor as shown in the
following code snippet.

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

set
{
if ( value > 10 )
length = value ;
}

As against this if length was just a data member, it would not have been possible for us to check
range or perform any such functionality on it.

Static Properties...

The static modifier can be used to create properties that belong to a class and not to an
individual object. We can write static properties for static data members only. To access these
properties we have to use the class name instead of an object. For example,

using System ;
namespace sample
{
public class window
{
static int height ;
public static int Height
{
get
{
return height ;
}
set
{
height = value ;
}
}
}
class Class1
{
static void Main ( string[ ] args )
{
window.Height = 10 ;
Console.WriteLine ( "Window height: " + window.Height ) ;
}
}
}
Properties And Inheritance

If we derive a class from a base class, which has a public property declared in it, the object of
the derived class can also access the property of the base class. If the property of the base class
is declared as virtual the derived class can override the base class property with its own version
of the property.
Abstract Properties...

Properties in C# can also be declared as abstract. If we declare the property as abstract it is


necessary to declare the class containing the property, as abstract. Since we cannot create the
objects of the abstract class it becomes necessary to derive a class from it and implement the
property.

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

Indexers...

An Indexer is a special type of property. If a class contains an array as a data member, then, an
indexer lets us access the array within the class, using an object, as though the object itself were
an array. This is done using the [ ] operator. For example, consider a class myclass which has an
int array as a data member and we create an object a of that class. Here we can access the
elements of the array by using the expressions a[0], a[1], a[2] and so on. The following code
snippet shows how to declare an indexer:

public int this [ int index ]


{
get
{
// code
}
set
{
// code
}
}
Exception Handling In C#...

C# uses a more systematic approach to tackle exceptions. The .NET CLR checks for the runtime
errors and raises exceptions to inform the program that an error has occurred. It also handles
these exceptions if the program has not handled it. In C# the exceptions are in the form of objects
of exception classes. All exception classes are derived from the System.Exception class. An
exception object cannot be "thrown" or "caught" unless their classes are inherited from the
System.Exception class. When we say an exception is thrown, it means that the CLR creates an
object of the class on heap and passes its reference to the program. There are several standard
exceptions provided by the .NET framework. We can also create user-defined exceptions. The
exception thrown by the code written in one .NET compliant language can be caught in another
.NET compliant language
LinearGradientBrush...

The LinearGradientBrush is used for gradient filling. To the constructor of a


LinearGradientBrush we pass two Point objects and two Color objects. Point is a structure
representing x and y coordinates. The two Point objects specify the starting and ending point of
the gradient fill, while the Color objects represent the starting and ending colors of the gradient
fill. An important point to note is that the y coordinates of both the points must be same for the
gradient fill to be filled horizontally. If the y coordinate of the second point passed to the
constructor of the LinearGradientBrush class does not match with the y coordinate of the first
point, the gradient fill does not remain horizontal.
Line Caps

Line caps specify shape of the end points of the lines. We can set the line caps using the
SetLineCap( ) method. This method accepts 3 parameters. The first two parameters specify
LineCap enumeration representing the cap style at the beginning and end of a line. The last
parameter specifies the DashCap enumeration that is used to specify the beginning and end of a
dash line.

Multiple Methods In A Delegate...

A delegate can wrap even more than one method. For this, it maintains a linked list. The delegate
then points to the head of such a linked list. This means that when such a delegate is invoked, it

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

calls all the methods that form the linked list. All delegate classes are derived from
System.MulticastDelegate class. Hence, instead of the statements

c1 = new click ( MyForm1_click ) ;


mouseclick( ) ;
c1 = new click ( button_click ) ;
mouseclick( ) ;

we can simply write

c1 += new click ( MyForm1_click ) ;


c1 += new click ( button_click ) ;
mouseclick( ) ;

The delegate c1 inside the mouseclick( ) method would now call both the methods. Here we are
simply adding both the methods in a list and hence both would be called. Rest of the program
remains same.

Capacity...

By default, the capacity of the ArrayList is to hold 16 elements. If the number of elements
exceeds 16 then the capacity of the array list automatically gets doubled by allocating new area
of memory. If we want, we can increase or decrease the capacity of the array list using the
Capacity property of ArrayList class. The Capacity property indicates the number of elements
the ArrayList object is capable of holding. If we increase the capacity by saying arr.Capacity =
32 the array list arr would automatically get reallocated.

The BitArray Class...

The BitArray class represents an array of bool values. Each element of the BitArray contains
either true or false. The BitArray class contains several overloaded constructors, except the
zero-argument constructor. Following statements show how an object of the BitArray can be
instantiated.

int[ ] a = { 1, 2, 3 } ;
BitArray b1 = new BitArray ( a ) ;
BitArray b2 = new BitArray ( 5 ) ;
BitArray b3 = new BitArray ( 5, true ) ;

If we pass reference to another array as an argument to the BitArray constructor, the bit values
of every element of that array get copied as the elements of the BitArray. For example, the bit
values (1 or 0) of the element 1 would become first 32 elements (1 being a 32-bit number) in the
array b1. Either true or false would get stored in b1 depending upon whether the bit is 1 or 0. The
array b2 would get created with 5 elements and by default all the elements would be set to false.
The array b3 would contain 5 elements where all the elements would be set to the bool value
true.

The lock keyword...

C# provides us with a lock keyword to lock the shared object or resource. Whatever is written
inside the parenthesis following the lock keyword gets locked for the current thread and no other
thread is permitted to access that resource or object. This marks all the statements that follow the

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

lock keyword enclosed in a pair of braces as critical section. For example, if we wish to lock an
array arr we would write,

lock ( arr )
{
//code
}

HTML controls...

HTML controls are created from classes present in System.Web.UI.HtmlControls namespace.


All HTML control classes derive, either directly or indirectly, from
System.Web.UI.HtmlControls.HtmlControl. HTML control classes are instantiated by adding
runat = "server" to ordinary HTML tags. For example, the following statement declares a
standard HTML text input field.

<input type="text">

But the following statement declares an instance of HtmlInputText.

<input type="text" runat="server"/>


Web Controls...

Web Controls are server controls. By server controls we mean those controls, which execute on
the server and not on the client. In ASP, controls were mere HTML tags. Whenever the browser
used to find these HTML tags, the controls used to get displayed. However, in ASP.NET the
controls do not get added as HTML tags. Instead, they are objects within the page. Hence we can
change properties and add events for these controls just like we would do for controls used in
WinForms. This is quite a big advantage over ASP. All the Web Controls are derived from the
WebControl class present in the System.Web.UI.Control namespace. The code that gets added
for Web Controls in the '.aspx' file is based on XML.
Validation controls...

Whenever we enter something on a Web Form form and submit it to the server it is called a
postback. Validation controls provide a method of validating user input without writing any code.
Whenever postback is initiated each control checks the control it is validating and changes its
IsValid property accordingly. If the property is set to false it means that the user input is wrong. In
such a case an error message is flashed. If the property is set to true the postback occurs.

#warning And #error Directives...

Instead of the compiler, if we want to flash a warning or raise an error at compile time we can use
the #warning and #error directives. For example, if we write

#warning Following code may give unpredictable results.

a warning is flashed when the complier encounters a statement like this. It displays whatever text
appears after the #warning directive. In this case it will be "Following code may give
unpredictable result." On encountering a #warning the compilation does not stop. The #error
directive is used to raise an error.

#error x is not accessible.

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

When the compiler encounters such a statement, it raises an error. The error raised in this case
will be 'x is not accessible'. On encountering #error the compilation process will be stopped.
These directives are used by programmers to remind themselves of tasks they might forget to do.
For example, they can arrange to get reminded by giving warnings such as "This function is
incomplete, you intended to write more code to make it fool proof". Programmers can frame some
rules for themselves and raise warning, errors accordingly.

The #region And #endregion Directives...

The #region and #endregion directives are used to mark blocks of code. For example,

#region
// code
#endregion

These directives don't affect the compilation process. They are used for ease of maintaining the
code in the editor. The editor in which we type our code is provided with a feature where on the
left hand side of the window we see minus or plus signs. These signs denote the marking of
blocks of code. We can click on the plus signs to expand the code and on the minus signs to
collapse it back, just as we would close a node in a tree control. The #region and #endregion
directives allow us to mark blocks of code in the same way and the block can be expanded and
collapsed. These directives can also work across functions

The #line directive...

The #line directive can be used to alter the file name and line number information which is output
by the compiler in warnings and error messages. Consider the following program:

1. #define x
2. using System ;
3. namespace sample
4. {
5. class Class1
6. {
7. static void Main ( string[ ] args )
8. {
9. #line 100 "xyz.sc"
10. #if x
11. #warning false warning
12. #endif
13. }
14. }
15. }

The line after the #line directive gets the specified line number. Hence in this program the line
number of the #if directive would change to 100 from line number 10. The program flashes a
warning "false warning" at line 101 instead of at line number 11 and the file name is changed to
'xyz.sc'. Complex programs having bulky code are written by many programmers and not just
one. This directive is used by them to have their own line numbers, which helps them to identify
errors or warnings in their code and in their files.

Value Parameter

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

A parameter declared with no modifier (such as ref, out, params) is a value parameter. For
example in the following function,

void fun ( int x )


{
}

x is a value parameter. If we make a call to the function by saying:

int i = 9 ;
fun ( i ) ;

the value of i gets copied in x. Here x is a totally different variable than i. Hence changing x
would not affect i. This is similar to a call by value in C.

enums...

There are a few important points to note regarding enums which are given below:

a. We can give same values to two enum members.


b. An enum cannot have a circular definition. For example,

enum color
{
red = yellow, blue, green, yellow, brown
}

Here, the compiler will first try to give red yellow's value. But yellow's value depends on
red's value. Hence yellow has no value yet and will be assigned a value later. This is
circular dependency and is not allowed.

c. The value of enum members cannot be changed.


d. An enum cannot have two members with the same name.
e. We cannot inherit from enums.

Jagged Array...

A jagged array is an array of 1D arrays each of different length. We cannot create the jagged
array in the same way as we create the rectangular array. The correct way to initialize the jagged
array is as follows:

int[ ] [ ] arr1 = new int [ 2 ] [ ] ;


arr1 [ 0 ] = new int [ 3 ] { 3 , 5, 7, 1 } ;
arr1 [ 1 ] = new int [ 2 ] { 11, 13 } ;

The way to create a 3D jagged array is as follows:

int[ ] [ ] [ ] arr = new int [ 2 ] [ ] [ ] ;


arr [ 0 ] = new int [ 3 ] [ ] ;
arr [ 0 ] [ 0 ] = new int [ 3 ] ;
arr [ 0 ] [ 1 ] = new int [ 4 ] ;
arr [ 0 ] [ 2 ] = new int [ 5] ;

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

Here the 3D array consists of two 2D arrays. The first 2D array would consist of three 1D arrays,
and finally all the three 1D arrays have different number of elements.

TopMost property is used if we want that a WinForm should be displayed as the top-most form in
an application. The TopMost property if set to true, displays the WinForm as the top-most form.
The following code snippet demonstrates this.

using System ;
using System.Drawing ;
using System.ComponentModel ;
using System.WinForms ;
using System.Data ;

public class Form1 : System.WinForms.Form


{
public static void Main(string[ ] args)
{
Form1 F1 = new Form1( ) ;
F1.TopMost = true ;
Application.Run ( F1 ) ;
}
}

The Keyword params...

C# provides a keyword called params, which is used when we want to write a function that
accepts variable number of arguments. For using the params keyword the argument must be
declared as a single dimensional array. Once an argument is prefixed with the params keyword
C# will accept any number of values (even none) for that argument. For example,

public class sample


{
public int add ( params int[ ] no )
{
int val = 0 ;
foreach ( int n in no )
{
val += n ;
}
return val ;
}

public static int Main ( string[ ] args )


{
sample s = new sample( ) ;

Console.WriteLine ( s.add( ) ) ;
Console.WriteLine ( s.add ( 4, 3 ) ) ;
Console.WriteLine ( s.add ( 5, 2, 3, 10 ) ) ;
return 0 ;
}
}

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

As C# does not allow global methods or variables ,some times we may end up with a class
containing only static members. When a class contains only static members there is no meaning
in creating an instance of that class. We can prevent users from creating an instance of a class
by introducing a private constructor within the class as shown below:

public class Color


{
static int x = 100 ;
static int y = 55 ;
static int z = 43 ;
private fun( )
{
}
}

What is the significance of ref keyword?

Ans: When we pass an array to a method, we pass its reference. What if we pass this reference
using the ref keyword? Consider the following program.

static void Main (string[] args)


{
int[ ] a = { 1, 2, 3, 4, 5 } ;
change ( ref a ) ;

foreach ( int i in a )
Console.WriteLine ( i ) ;
}
static void change ( ref int[ ] b )
{
int[ ] arr = { 10, 11, 12, 13, 14 } ;
b = arr ;
}

If you run the program output will be 10 11 12 13 14. Now remove the ref keyword and run the
program again. You will get the output as 1 2 3 4 5. Thus, when we pass a reference using the ref
keyword, we can modify the contents of the reference in the called method so that it would start
pointing to a new memory location.

Implementing ambiguous interface methods...

Suppose, two interfaces have declared a method having same signature. If a class implements
both the interfaces then it would create an ambiguous situation. To avoid this ambiguity, we must
use explicit implementation of method as shown below.

interface i1
{
void f2( ) ;
}
interface i2
{
void f2( ) ;

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

}
class sample : i1, i2
{
public void f2( )
{
Console.WriteLine ( "i1.f2" ) ;
}

void i2.f2( )
{
Console.WriteLine ( "i2.f2" ) ;
}
}

Here, the method f2( ) is declared in i1 as well as in i2. We must implement at least one of them
explicitly. To implement the method explicitly we have to use fully qualified name of the method.
An important thing about explicitly implemented methods is that they are accessible only through
the reference to the interface. We cannot access them using the reference to the implementing
class like normal methods.

The JIT Compiler

The JIT (Just In Time) compiler is a crucial component of .NET framework. The program created
in C# gets compiled into an IL (Intermediate Language) code. The JIT compiler converts this IL
code into machine code, which is then executed. The JIT compiler does not compile entire code
at once because it could hamper the performance of the program. It compiles the code at run-
time, at the time the code is called. The code that is compiled gets stored until the execution
comes to an end. This avoids recompilation of code. The reason why conversion from IL code to
machine code takes place at runtime is that, the JIT first gets information of the processor type
and convert the IL code so that it would run on that type of processor.

Suppose we create two strings having exactly same literal as shown below:

string s1 = “hi there!” ;


string s2 = “hi there!” ;

When the application is loaded in memory, CLR creates an empty hash table to store the strings
used in the source code. The JIT compiler searches all the strings and fills the hash table with
keys and values. In the hash table, the text is the key and reference is the value. So, when JIT
comes across the first declaration i.e string s1 = “hi there!”, the text “hi there!” gets stored as a
key and its reference as value. Later, it encounters s2 that has the same value. It does nothing
since duplicate keys cannot exist in hash table. Whenever we use s1 or s2 in program, it will
return the same reference from hash table. This mechanism avoids duplication of strings.

If we use the == operator on reference types it compares two references and not the contents.
But in case of strings, it works differently. If used on strings, == operator compares values not the
references. If we want to compare the string references, we must cast the string references to
object type. For example,

string s1 = "hi" ;
char[ ] ch = { 'h', 'i' } ;
string s2 = new string ( ch ) ;

if ( s1 == s2 )

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

Console.WriteLine ( "Equality of value" ) ;

if ( ( object ) s1 == ( object ) s2 )
Console.WriteLine ( "Equality of reference" ) ;

How can I determine the type of an object at runtime?

Ans: We can use the keyword is to know the type of an object at runtime. This is shown in
following program.

using System ;

class myApp
{
public static void Main()
{
string str = "Hello!" ;
int i = 25 ;

Console.WriteLine ( "{0} is {1} an integer ", s, ( IsInteger ( s ) ? "" : "not " ) ) ;


Console.WriteLine ( "{0} is {1} an integer", i, ( IsInteger ( i ) ? "" : "not " ) ) ;
}
static bool IsInteger ( object obj )
{
if ( obj is int || obj is long )
return true ;
else
return false ;
}
}

The output of this program would be as given below:

Hello is not an integer


25 is an integer

Abstract Classes vs. Interfaces

The main difference between an abstract class and an interface lies in their application i.e in the
way they are used.

The abstract classes always act as a base class of the related classes in the class hierarchy. For
example, consider a hierarchy—car and truck classes derived from four_wheeler class. The
classes two_wheeler and four_wheeler derived from an abstract class vehicle. So, the abstract
class vehicle is the base class in the class hierarchy. On the other hand one interface can be
implemented by dissimilar classes. For example, there is an interface that compares two objects.
This interface can be implemented by the classes like box, person and string, which are
unrelated to each other

The Anchor property

We can anchor a control to one or more edges of its container. Anchoring a control ensures that
even if size of the container changes, the anchored edges of control remain on the same position
relative to the edges of the container. We can specify which edges we want to anchor using the

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

Anchor property of the Form class. If the Anchor property of a control is set to None, then the
distance between the edges of control and that of the container change if the container is resized.
So, the control appears moving as the container is resized.

Making Type Conversion Perfect

C# is a strictly typed language. It allows widening conversion like int to float, char to int, etc. but
not the narrowing conversion. For narrowing conversion we need to typecast the values. For
example,

int i ;
float f ;
f = 5.8f ;
i = ( int ) f ;

If we run this code in C#, we get the output 5 in i. But if we write this type of code in VB.NET i
would contain 6 not 5 because in VB.NET the value gets rounded off. Thus, we get different
output of the same code which may cause bugs if our code is ported to another language. To
avoid this we must take help of the Convert class. Convert class provides methods to convert
one type into another. This conversion is neutral across the languages. It means that the
conversion result would be same irrespective of the language.

String comparison done using == is case-sensitive, How do I do a case-insensitive string


comparison?

Ans: Use the String.Compare function. Its third parameter is a boolean which specifies whether
case should be ignored or not. For example,

"kicit" == "KIcIt" // returns false


System.String.Compare( "kicit", "KIcIt", true ) // returns true

Finalization Internals

We can write the Finalize( ) method that gets called when an object is collected by Garbage
Collector. However, finalizable objects cause increase in overhead on the part of CLR and takes
longer time to clean up than non-finalizable objets. This is because of the following reason.

For every finalizable object an entry is made in a separate 'finalization queue'. The entry is a
reference referring to the object on the managed heap. When GC gets invoked, it checks whether
the unreferenced object has an entry in the finalization queue. If it has, then the reference is
removed from the finalization queue and is appended to yet another queue. When such an entry
is made in the queue a dedicated thread gets invoked. This thread removes the reference from
the queue and calls the Finalize( ) method of the object referred to by this reference. While this
process is going on the object continues to exist on the managed heap as a referenced object.
Next time when GC is invoked, it again checks whether an object has entry in the finalization
queue. This time it doesn't find the entry. So, the object gets collected. Thus for a finalizable
object GC needs to be invoked twice.

Visual Inheritance

Visual inheritance is a technique provided by Visual Studio.NET that allows us to reuse an


existing form. That is, we can inherit an existing form to create a new derived form. Visual
inheritance is useful when an extensive user interface with number of controls stands ready.
Visual inheritance avoids repetition of creating the user interface. The form that we can inherit is

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

exported from a class library (.dll). One class library can export any number of forms.
To create the base form, we must create a normal WindowsApplication and build it as a
ClassLibrary by selecting the 'Output Type' as ClassLibrary. Once the form is ready we can derive
another form in a new application by selecting the 'Add Inherited Form' option.

Why operator overloaded methods are static in C#?

Ans: C# provides overloaded operator methods as static methods. And so, the this reference is
not passed to these methods. Since this reference is not available we have to pass two
parameters to the overloaded binary operator methods. C++ programmers may find the syntax of
overloaded operator methods a bit confusing. But this syntax ensures that we are never required
to write friend functions. We were required to use a friend function in C++ to overload the binary
operator when two operands were of different types. For example, If we want to write the
following statement in C++,

c2 = 10 + c1 ;

we would have to define the + operator function as a friend function. Because this statement
would get expanded as 10.operator+ (c1). But if we write the same statement in C#, it would get
expanded as operator+ ( 10, c1 ). We can easily define an overloaded method that takes an int
and an object. We don't need to define a friend function for this.

Why in C#, uninitialised variables do not contain garbage value?

Ans: In C or C++ initial value of variable is garbage value. This is not so in C#. The reason is that
all value types implicitly declare a public zero-argument constructor called the default
constructor. The default constructor initialises the instance with the value according to the value
type. For example, an int is initialized with 0, bool with false, char with '\0', etc. Like any other
constructor, the default constructor of a value type is invoked using the new operator. Because
every value type implicitly has a public parameter less constructor, it is not possible for a struct
type to contain an explicit declaration of a parameter less constructor. However, a struct type is
permitted to declare parameterized constructors.

There is a provision made by the .NET Framework that relieves the programmer from managing
threads. This provision is called Thread Pooling. The concept behind thread pooling is that a
thread manager manages a pool of threads called worker threads. The idea is that we just need
to pass requests to launch threads to the thread pool manager instead of launching the threads
ourselves. Many applications use multiple threads, but often those threads spend a great deal of
time in the sleeping state waiting for an event to occur. When a wait operation completes, a
worker thread from the thread pool executes the corresponding callback function.

Why value types are sealed?

Ans: The value types are implicitly made sealed to avoid complexities related to object slicing.
This comes about because value types are stored inline when they are members of other types,
and are also stored inline in arrays. Therefore, if we were to store a derived value type in a
location where the base value type was expected, any extra fields included in the derived type
would need to be sliced off. This can cause hard-to-diagnose bugs when the derived value type is
retrieved.

What is the C# equivalent of QueryInterface?

Ans: Use keyword as as shown in following example.

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

using System ;
interface IPerson
{
string GetName( ) ;
}

interface IPerson2 : IPerson


{
int GetAge( ) ;
}

class CPerson : IPerson


{
public CPerson ( string name )
{
m_name = name ;
}

// IPerson
public string GetName( )
{
return m_name ;
}

private string m_name ;


}

class CPerson2 : IPerson2


{
public CPerson2 ( string name, int age )
{
m_name = name ;
m_age = age ;
}

// IPerson2
public string GetName( ) { return m_name ; }
public int GetAge( ) { return m_age ; }
private string m_name ; private int m_age ;
}

public class CApp


{
public static void Main( )
{
CPerson rahul = new CPerson ( "Rahul" ) ;
CPerson2 vidya = new CPerson2 ( "Vidya", 24 ) ;

DisplayAge ( rahul ) ;
DisplayAge ( vidya ) ;
}

static void DisplayAge( IPerson person )


{
IPerson2 person2 = person as IPerson2 ; // QueryInterface lives on !!!
if ( person2 != null )

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

Console.WriteLine ( "{0} is {1} years old.", person2.GetName( ), person2.GetAge( ) ) ;


else
Console.WriteLine ( "Sorry, don't know {0}'s age.", person.GetName( ) ) ;
}
}

On execution of this program it produces following output:

Sorry, don't know Rahul's age.


Vidya is 24 years old.

How do I create non-rectangular form?

Ans: If you see WindowsXP media player you would appreciate its Graphical User Interface. It
displays the main window and controls in non-rectangular shapes carrying attractive bitmaps on
them. Creating such GUI with previous versions of Windows was complicated. .NET has made it
very easy. Here are the steps to create non-rectangular form.

1. Create a bitmap in 'Paint' application and paint its background with blue color (you can select
any color). Save the file.
2. Create a Windows Application.
3. In 'Design' view open the 'Properties' window. Select the '.bmp' file we just created for
BackgroundImage property of the form.
4. Set the FormBorderStyle property to None. This would hide the title bar of the form.
5. Set the TransparencyKey property to the background color of the '.bmp' file. In this case we
would set it to blue.

Run the application. Our form would get displayed in the shape and design as created in the
'.bmp' file

How do I shift the origin to the center of the client area and draw a line of 1 inch?

Ans: Here is the code:

private void Form1_Paint ( object sender, PaintEventArgs e )


{
Graphics g = e.Graphics ;
g.PageUnit = GraphicsUnit.Inch ;
g.TranslateTransform ( ( ClientRectangle.Width / g.DpiX ) / 2,
( ClientRectangle.Height / g.DpiY ) / 2 ) ;
Pen p = new Pen ( Color.Green, 1 / g.DpiX ) ;
g.DrawLine ( p, 0, 0, 1, 0 ) ;
}

The PageUnit property sets the unit to an inch. We have called the TranslateTransform( )
method to shift the origin to the center of the client area. This method maps the world coordinates
to page coordinates. Finally, we have created a pen having proper width and drawn the line.
Since we have set the page unit to an inch, we must specify coordinates of line in inches.

How do I invoke a method using reflection?

Ans: The following example loads a user-created assembly, obtains a class type, creates its
instance and invokes a method defined in the assembly.

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

Assembly a = Assembly.LoadFrom ( "c:\\mymath.dll" ) ;


Type t = a.GetType ( "mymath" ) ;
MethodInfo m = t.GetMethod ( "add" ) ;
Object obj = Activator.CreateInstance ( t ) ;
Object[ ] arg = new Object [ 2 ] ;
arg [ 0 ] = 10 ;
arg [ 1 ] = 20 ;
m.Invoke ( obj, arg ) ;

This code snippet would invoke the add( ) method written in mymath class. The mymath class is
in the 'mymath.dll' assembly.

How do I read non-public members from metadata?

Ans: We use reflection technology to read metadata. We have various methods at hand like
GetMethods( ), GetConstructors( ), GetFields( ), GetProperties( ), etc. that can be used to
read the respective members from metadata. If we call these methods without passing any
parameters, they return only public members, not the non-public members. To read the non-
public members we must pass certain flags to them. The following statement shows how to pass
the flags to read all the methods.

mytype.GetMethods ( BindingFlags.Instance | BindingFlags.DeclaredOnly | BindingFlags.Public |


BindingFlags.NonPublic ) ;

These flags indicate that we intend to read the instance methods, methods that are not inherited
from base type and methods that are public as well as non-public.

The main design goal of C# was simplicity rather than pure power. We do give up a little
processing power, but you get cool stuff like type safety and automatic garbage collection in
return. C# can make our code stable and productive overall. C# offers several key benefits for
programmers:

• Simplicity
• Consistency
• Modernity
• Object-orientation
• Type-safety
• Scalability
• Version support
• Compatibility
• Flexibility

Let's see what version support does C# provides:


In C++, if a derived class contains a non-virtual function with a name abc( ) and the new version
of a base class is shipped with a virtual function having the same name abc( ). This would result
in an unpredictable result since the derived class version of abc( ) would get called now, which
was not expected.

Previously, there was nothing a programming language can do to retain the binary compatibility of
new version of base class with existing derived class. This is not the case in C#. In C#, a function
in derived class doesn't automatically become virtual if there is a virtual function with the same

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

name in the base class. To make the derived class function fall in the virtual chain we need to
mark it with the override keyword.

We can create two types of user-defined controls - Custom Controls and User or Composite
Controls. Custom controls display user interface by making calls to a Graphics object. Custom
controls are typically derived from the Control class. The Control class implements the very
basic functionality required by classes that display information to the user. It handles user inputs
through the keyboard. It handles message routing and security. There is limited design-time
support for creating custom controls.

User or Composite controls are composed of other existing controls and hence we need not
specify the user interface for User controls. User controls are derived from the UserControl
class. The UserControl class is also derived from the Control class There is full design-time
support for creating user controls with the Visual Studio .NET Windows Forms Designer.

The PrintDocument component...

.NET supports printing through methods and properties of the PrintDocument component. The
PrintDocument component is available in the toolbox and when added to a form, it appears in
the component tray at the bottom of the Windows' Forms Designer. This is because the
PrintDocument component is not visible at runtime. The PrintDocument class represents the
PrintDocument component and falls under the System.Drawing.Printing namespace.

Typically in a printing application we call the Print( ) method of the PrintDocument class. It also
contains properties such as DefaultPageSettings, which gets or sets page settings that are used
as defaults for all pages to be printed, PrinterSettings, which gets or sets the printer that prints
the document. The class contains events like BeginPrint, EndPrint and PageEvent. BeginPrint
is raised when the Print( ) method is called and before the first page of the document is printed.
Here we can do any initializations if needed. EndPrint event is raised when the last page of the
document has been printed. We can do cleaning up jobs here. The PrintPage event is raised
when it's time to print the current page. We can write code in the handler of this event to do the
desired printing. Hence the order of events raised when Print( ) method is called is BeginPrint,
PrintPage and then EndPrint.

The main design goal of C# was simplicity rather than pure power. We do give up a little
processing power, but you get cool stuff like type safety and automatic garbage collection in
return. C# can make our code stable and productive overall. C# offers several key benefits for
programmers:

• Simplicity
• Consistency
• Modernity
• Object-orientation
• Type-safety
• Scalability
• Version support
• Compatibility
• Flexibility

Let's see what version support does C# provides:


In C++, if a derived class contains a non-virtual function with a name abc( ) and the new version
of a base class is shipped with a virtual function having the same name abc( ). This would result
in an unpredictable result since the derived class version of abc( ) would get called now, which

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

was not expected.

Previously, there was nothing a programming language can do to retain the binary compatibility of
new version of base class with existing derived class. This is not the case in C#. In C#, a function
in derived class doesn't automatically become virtual if there is a virtual function with the same
name in the base class. To make the derived class function fall in the virtual chain we need to
mark it with the override keyword.

Thread States...

Ans: At times we may want to prevent our thread from getting CPU cycles till:

1. Passage of some time.


2. Some other thread completes some operation.
3. Some other thread terminates.

We can achieve the above three scenarios by respectively calling the methods
Thread.Sleep( ), Monitor.Wait( ) and
Thread.Join( ) methods on our thread. Upon calling one of these three methods, our
thread enters the WaitSleepJoin state. Once in this state we can transition out of it in the
following three ways:

1. The sleeping time specified by the Sleep( ) method expires.


2. Another thread calls the Thread.Interrupt( ) method before the sleeping time expires.
3. Another thread calls the Monitor.Pulse( ) method or Monitor.PulseAll( ) method.
Monitor.Pulse( ) moves the waiting thread
into the Running state. Monitor.PulseAll( ) method moves the thread along with all
the other waiting threads into the Running
state.

All the above three ways move the thread from the WaitSleepJoin state to the Running
state. When a thread completes its execution, it goes into the Stopped state. The
StopRequested state is reached when a thread is being requested to stop. There is no
method available that we can invoke to manually force our thread in this state. Whenever
an exception is thrown and the thread stops executing abruptly it goes into the Aborted
state.

Printing With Different Units...

In the Graphics methods we specify coordinates in two-dimensional coordinate system. The


system has origin at left-top corner and x and y axes point to right and down respectively. All the
methods take coordinates in pixels. The coordinates passed to Graphics methods are world
coordinates. When we pass world coordinates to a method, they firstly get translated into page
coordinates (logical coordinates) and then into device coordinates (physical coordinates).
Ultimately, the shape gets drawn in device coordinates. In both the page and device coordinate
system the measure of unit is same i.e. pixels. We can customize the coordinate system by
setting a different measure of unit.

Suppose we wish to print a line having one-inch length, for this we need to use the PageUnit

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

property of the Graphics object. The PageUnit property represents an object of the
GraphicsUnit enumeration. This enumeration specifies the unit of measure for the given data.
For example, the Inch member specifies that unit of measure is an inch, the Pixel member
specifies that the unit of measure is the device pixel etc.

.NET Remoting-Difference Between Server-activated Singleton And SingleCall Activation


Modes...

Whenever we register a server-activated object, we specify a mode. The two supported activation
modes used for server-activated objects are WellKnownObjectMode.SingleCall and
WellKnownObjectMode.Singleton. WellKnownObjectMode is an enumeration and SingleCall
and Singleton are the members of this enumeration.

The difference between the two activation modes is that if we specify SingleCall to be the
activation mode, a new instance of remotable object would get created for each and every
method call placed by any client. As against this, if we specify Singleton as the activation mode
only one instance of remotable object would be created and it would process all method calls
from all clients.

What are Channels?

Ans: A channel serves as a conduit for communication between the client and the remotable
object. The channel listens for incoming messages and sends outgoing messages. It takes a
stream of bytes, creates a package according to a particular protocol, and routes it to the final
destination.

The .NET Framework comes with two predefined channel classes, TcpChannel and
HttpChannel. The TcpChannel uses a binary formatter to serialize data to binary stream and
transport it using the TCP protocol. HttpChannel uses a SOAP formatter to serialize data and
transport the messages to and from remote objects using the SOAP protocol. We can also use
binary formatters with HttpChannel. Both these classes work as senders as well as receivers.
The way data gets serialized before sending, it gets deserialized after it is received.

The TcpChannel class serves as a combined channel, which combines the TcpServerChannel
and TcpClientChannel for convenience. The TcpServerChannel listens and the
TcpClientChannel transmits messages using the TCP protocol. These classes fall under the
System.Runtime.Remoting.Channels.Tcp namespace. Similarly, the HttpChannel class also
servers a combined channel, which combines the HttpServerChannel (listener) and
HttpClientChannel (sender).

.NET Remoting-Is there any other method to activate remote objects?

Ans: Generally when we think of activating remote objects we create an object of the remotable
class (which actually creates a proxy on the client and object on the server). The .NET
Framework offers an alternative way to activate remote objects instead of calling new( ). To
activate server-activated objects we may use the GetObject( ) method while we may use
CreateInstance( ) for client-activated objects. Both these methods belong to the
System.Activator class. If we use these methods, we need not use
RegisterActivatedClientType( ) or RegisterWellKnownClientType( ) methods to register the
remotable class on the server.

.NET Remoting- Which is better, Programmatic or Declarative Configuration?

Ans: If we perform the registrations programmatically, and later if we wish to change the

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

registration data (for example, the machine or port) we need to make changes in the source code
and re-compile the applications. As against this, if registrations are declarative all we need to do
is simply make changes in the '.config' file through 'Notepad' or any other text editor and run the
applications without recompilation.

On the negative side the security factor is very low in declarative registration. Anybody can modify
(or even delete!) the '.config' file that you create thus, leading to a trouble. On the other hand
nobody can tamper with your registration data if its done programmatically. You would have to
weigh out the convenience and security considerations as per the needs of your application.

.NET Remoting-Lifetime Of A Remotable Object...

For SingleCall server-activated objects, the duration of lifetime of an object is exactly one
method. After this the object gets collected by the garbage collector.

For Singleton server-activated objects and client-activated objects, a Lease Manager controls
the lifetime. Each instance of such objects is leased to the client for a given amount of fixed time.
The lease starts when the object is created. By default, each Singleton server-activated or client-
activated object is given a 5 minute lease. When the time expires the object is garbage collected.
During the lifetime of the object any client can increase or decrease the lifetime value of the
object by default for 2 minutes.

Another way that .NET Remoting uses to control the object's lifetime is using sponsorship. Both
server and client can act as sponsors for a particular instance of the remotable class. When the
lease of an object finishes, before destroying the object the sponsors get a chance to renew the
lease.

What are HTML controls and Web controls and how do they differ?

Ans: ASP.NET supports two distinctly different types of server controls: HTML controls and Web
controls.

HTML controls are instances of classes defined in the System.Web.UI.HtmlControls


namespace. When you add runat="server" to a conventional HTML tag (as in <input type = "text"
runat="server">), the .NET Framework responds by instantiating an HTML control.

Web controls come from classes defined in System.Web.UI.WebControls. They're declared


explicitly by prefixing class names with asp: and including runat="server" attribute (for example
<asp:TextBox runat="server">).

HTML controls exist primarily to ease the chore of migrating existing HTML forms to ASP.NET.
Web controls are richer and more diverse in scope that HTML controls.

Serializing Objects Using XML...

XML and .NET together have provided a powerful feature of serializing objects in an XML
document. In this process the public fields and properties of the class get stored in the form of
elements and attributes. We can use the classes available in the System.Xml.Serialization
namespace for serializing and de-serializing the objects.

What do you mean by the LineJoin property?

Ans: The LineJoin property of the Pen class gets or sets the join style for the ends of two
consecutive lines drawn with this Pen object. For example, while drawing the rectangle if we
specify the LineJoin property to be,

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

p.LineJoin = Drawing.Drawing2D.LineJoin.Round ;

then the corners of the rectangle would become round.

How to add Tooltips for various controls on a form?

Ans: Suppose we have a Winform application with various controls and we wish to add different
tooltips for each control. In such a case we need to drag the 'ToolTip' control on the form. As soon
as we do this, the 'Properties' window for every control starts showing a 'ToolTip' on controlname
property. Using this property we can set tooltips for the controls we want.
For example, if we add a 'ToolTip' control named mytooltip on the form. The form has a button
named mybutton. Now suppose we set the property to-"This is mybutton"-for a button called
mybutton, then when we execute the program and moves the mouse on the button, a tooltip gets
displayed. What actually happens behind the scene is that the wizard adds the following code to
the form class:

this.mytooltip.SetToolTip ( this.mybutton, "This is mybutton") ;

What is Global.asax?

Ans: Global.asax is an ASP.NET application file consisting of a class called Global. This class is
derived from the HttpApplication class and contains code for responding to application-level
events raised by ASP.NET. Following are some methods defined in the class:

• Application_Start( ):- Called when the site receives its very first request
• Session_Start( ):- Called when the session is first created
• Application_End( ) And Session_End( ): Called respectively when the application and
session terminate
• Application_Error( ):- Called when an error occurs in the application

How do I write code if I want that the following statement should join the two corners of
the form irrespective of its size?

g.DrawLine ( 0, 0, 100, 100 ) ;

Ans: Use the Graphics.ScaleTransform( ) method as shown below:

void Form1_Paint ( object sender, PaintEventArgs e )


{
Graphics g = e.Graphics ;
g.ScaleTransform ( ClientSize.Width / 100.0f, ClientSize.Height / 100.0f ) ;
Pen p = new Pen ( Color.Green, 1 / ( ClientSize.Width / 100.0f ) ) ;
g.DrawLine ( p, 0, 0, 100, 100 ) ;
}

Difference Between Custom Control And User-Defined Control..

A custom control is the one which is created by extending an existing control like Label, Textbox,
Buttons, etc. For example, we can derive a class from the TextBox class so that the user can
enter only digits in it.

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

A user-defined control is a set of one or more existing controls (WinForm or WebForm controls).
The best example of user-defined control is a media player that is a combination of several
buttons, slider control and other UI elements. A user-defined control is derived from the Forms
UserControl class.

If we want to create a control from scratch, we can do so by deriving a class from the Control
class.

Asynchronous Delegate Invocation

Delegates normally work synchronously. That is, they invoke the method passed to them and
return only when the method returns. We can also use delegates to make an asynchronous call
to the method passed to it. It means that, the delegate would initiate the method and return
immediately. To invoke a delegate asynchronously, call the BeginInvoke( ) method, which will
queue the method to be run on a thread from a system thread pool.

The BeginInvoke( ) method accepts a reference to the method that should get called when the
method called by BeginInvoke( ) ends.

What is thread pooling?

Ans: While programming Windows versions prior to Windows 2000, developers often started a
thread to perform a particular task and when the task was complete the thread would die. The
starting and closing the thread was costly in performance point of view. So, Microsoft introduced a
concept called thread pool in Windows 2000. And now in .NET, thread pool has been
implemented in CLR itself. And so, all the managed applications can use thread pool. Now if a
managed application starts a thread, it has to ask for a thread in the thread pool. The thread pool
initiates the thread just like any other normal thread. But when the task is complete, thread won’t
get destroyed. It would go to the thread pool in suspended state. If application makes a request
for thread, again this thread would wake up and perform the task. This saves lot of overhead. The
thread pool takes the responsibility of creating and killing threads, calling a method
asynchronously or after a time interval, etc.

As we know the code that accesses a common resource when enclosed within Monitor.Enter( )
and Monitor.Exit( ) helps in synchronizing concurrently running threads. What if one thread calls
Monitor.Enter( ) twice. Will it go into the wait state since lock has already been acquired? The
answer is no. This is because Enter( ) always checks which thread has acquired the resource
before making the thread wait. Initially when resource is not acquired, count in the syncblock is
set to zeros. When Enter( ) is called for the first time count becomes 1. If Enter( ) is called again
and it finds that the same thread has acquired the resource it just increments the count without
making the thread wait. This behavior seems logical otherwise the thread would have gone into
indefinite wait state expecting from itself to release the resource. The Exit( ) method then
decrements the count. When the Exit( ) method finds that the count has reached zero, it releases
the lock and makes the waiting thread as the ready thread.

What is Stack Walk?

Ans: .NET security models walk the stack to check whether a program accessing a code has
permission to do so. Stack walks are an essential part of the security system. A stack walk
operates in the following manner.

Every time a method is called a new activation record will be put on the stack. This record
contains the parameters passed to the method, if any, the address to return to when this function
completes and any local variables. At certain stages during execution, the thread might need to

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

access a system resource, such as the file system. Before allowing this access the protected
resource may demand a stack walk to verify that all functions in the call chain have permission to
access the system resource. At this stage a stack walk will occur and each activation record is
checked to see that callers do indeed have the required permission.

Suppose we create two strings having exactly same literal only one object containing the string
gets created and both the references refer to the same object. Let us understand how this works
out. Suppose we create two strings as shown below.

string s1 = "hi there! " ;


string s2 = "hi there! " ;

When the application gets loaded in memory, CLR creates an empty hashtable to store the string
constants used in the source code. The JIT compiler searches all the strings and fills the
hashtable with keys and values. In the hashtable, the text is the key and reference is the value.
So, when JIT comes across the first declaration i.e string s1 = "hi there!", the text "hi there!"
gets stored as a key and its reference as value. Later, it encounters s2 that has the same value. It
does not create another entry with this value since duplicate keys cannot exist in hashtable.
Whenever we use s1 or s2, it returns the same reference from hashtable. This mechanism avoids
duplication of strings. As soon as we assign a different string constant to any of the references it
starts referring to different object.

A Few Points About virtual Keyword…

(a) virtual or abstract method cannot be private. This is necessary because, the class designer
creates virtual or
abstract methods when he wants that user should override them in derived classes. If we
make them private, they
would fail to serve the purpose.

(b) C++ supports a concept of virtual base classes. In C++, a class can inherit the same class
twice. This happens
because of multiple inheritance. For example, a class der3 is derived from classes der1 and
der2 both of which
are derived from class base1. This results in der3 having two copies of base1’s data. Now, if
der3 refers to the
data in base1, which of the two copies will it access? To avoid this ambiguous situation,
base classes are
declared as virtual.

Such a situation would never occur in C#, as in C#, a class has exactly one base class.
Hence, C# does not have
virtual base classes

As we know the code that accesses a common resource when enclosed within Monitor.Enter( )
and Monitor.Exit( ) helps in synchronizing concurrently running threads. What if one thread calls
Monitor.Enter( ) twice. Will it go into the wait state since lock has already been acquired? The
answer is no. This is because Enter( ) always checks which thread has acquired the resource
before making the thread wait. Initially when resource is not acquired, count in the syncblock is
set to zeros. When Enter( ) is called for the first time count becomes 1. If Enter( ) is called again
and it finds that the same thread has acquired the resource it just increments the count without
making the thread wait. This behavior seems logical otherwise the thread would have gone into
indefinite wait state expecting from itself to release the resource. The Exit( ) method then

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

decrements the count. When the Exit( ) method finds that the count has reached zero, it releases
the lock and makes the waiting thread as the ready thread

What are parameterized commands?

Ans: Often we require to execute the same command on a database repeatedly, in which only
the values used in command are different. In such cases we can use parameterized commands.
Parameterized commands are also useful in the commands where input values come from user
input. They are also useful when values for only some of the fields in a row are to be stored. For
example, suppose our database table consists of fields f1, f2, f3 . . . and so on, till f7. Suppose we
have specified default values for f2, f3, f4 and f6 and we wish that f1, f5 and f7 be filled with
values a, b and c respectively. Then the parameterized command will be

"Insert into table1 { f1, f5, f7 } values ( @a, @b, @c )"

The parameter is added to the command by using Parameters collection of the command object
as shown below:

com.Parameters.Add ( "@a", 10 ) ;
com.Parameters.Add ( "@b", 230.0 ) ;
com.Parameters.Add ( "@c", 170 ) ;

where com is a reference to SqlCommand object.

How do I write code to display tool tip for controls?

Ans: We can display a tool tip for any control placed on a form. For this, we have to add a
ToolTip control to the form. As soon as we add the ToolTip control a property named 'Tooltip on
tip' gets added to the 'Properties' window of all the controls placed on the form. The string entered
against this property gets displayed as the tool tip when mouse is moved over the control. How
come only one ToolTip control manages to display tips for all the controls for which 'Tooltip on tip'
property is set? When we set the 'Tooltip on tip' property of a control, a call to the
ToolTip.SetToolTip( ) method gets added in the InitializeComponent( ) method as shown
below:

tip.SetToolTip ( button, "This is a Button" ) ;

The reference to the control (in this case, button) is passed to the SetToolTip( ) method along
with the tool tip text. The SetToolTip( ) method associates the text with the specified control.

How do I write code to invoke a method dynamically?

Ans: One of the uses of Reflections is that we can invoke a method dynamically. Following code
snippet invokes a method fun( ) of sample class stored in 'emitassembly.dll'.

Assembly a = Assembly.LoadFrom ( "emitassembly.dll" ) ;


Type t = a.GetType ( "sample" ) ;
Object o = Activator.CreateInstance ( t ) ;
t.InvokeMember ( "fun", BindingFlags.InvokeMethod, null, o, null ) ;

CreateInstance( ) creates an instance of the specified type and InvokeMember( ) method


invokes the method specified as the first parameter.

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

What are Thread States?

Ans: From the time a thread is started until it gets terminated a thread undergoes many
transitions and is said to be in at least one of the several ‘thread states’. The methods that control
the transitions from one state to another belong to either the Thread or the Monitor class. Both
these classes belong to the System.Threading namespace.

At any given time a thread can be in one or more of the states such as—Unstarted, Running,
WaitSleepJoin, Suspended, SuspendRequested, Aborted, AbortRequested, Stopped and
StopRequested. All these states are members of the ThreadState enumeration declared in
System.Threading namespace.

Using checked And unchecked Operators…

Every primitive data type has a fixed size and can store only that much value which can be
accommodated in its size. For example a variable of an int type cannot contain a value larger
than 2147483647. In an integer arithmetic operation a value greater than 2147483647 causes
overflow. This may cause an incorrect output. .NET provides two keywords checked and
unchecked to check whether integer arithmetic operations occur in a checked context or
unchecked context. In a checked context CLR throws an OverflowException if the overflow
occurs.

In the following code snippet, addition of i and j would result in a value greater than 2147483647.
Because we have added i and j in the checked context, it would throw the OverflowException.

int i = Int32.MaxValue ;
int j = Int32.MaxValue ;
int s = 0 ;
try
{
s = checked ( i + j ) ;
}
catch ( OverflowException o )
{
Console.WriteLine ( "Overflow occurred" ) ;
}
s = unchecked ( i + j ) ;
Console.WriteLine ( s ) ;

By default, arithmetic operations are done in an unchecked context. The addition performed in an
unchecked context would result in an incorrect output being stored in s

Nondeterministic Behavior Of Destructors...

In C++, we can define a destructor in a class to perform the clean up jobs. .NET framework also
allows to define destructors. But destructors in .NET are different than those in C++. In C++, the
destructor gets called when the object is destroyed. In .NET also destructor is called when the
object is destroyed. However, when the object would get destroyed is undeterministic. Because,
the object is destroyed only when the Garbage Collector is invoked. So, when the destructor of
the object would get called is also Nondeterministic.

Calling Web Serivce Asynchronously...

WebServices support asynchronous communication. In the asynchronous communication, the

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

client continues processing other tasks as it waits for a response from server. The client responds
to the result of the service request when it becomes available. Following code shows how to call
a WebService called temperature.

temperature t = new temperature ;


AsyncCallback cb = new AsyncCallback ( callbackfunc ) ;
t.BeginWebMethodName ( 20.5f, cb, t ) ;

The value 20.5f is the parameter passed to the web method. The callback function callbackfunc(
) is defined as shown below:

public void callbackfunc ( IAsyncResult ar )


{
temperature t = ( temperature ) ar.AsyncState ;
t.EndWebMethodName ( ar ) ;
}

How do I shift the origin to the center of the client area and draw a line of 1 inch?

Ans: Here is the code:

private void Form1_Paint ( object sender, PaintEventArgs e )


{
Graphics g = e.Graphics ;
g.PageUnit = GraphicsUnit.Inch ;
g.TranslateTransform ( ( ClientRectangle.Width / g.DpiX ) / 2,
( ClientRectangle.Height / g.DpiY ) / 2 ) ;
Pen p = new Pen ( Color.Green, 1 / g.DpiX ) ;
g.DrawLine ( p, 0, 0, 1, 0 ) ;
}

The PageUnit property sets the unit to an inch. We have called the TranslateTransform( )
method to shift the origin to the center of the client area. This method maps the world coordinates
to page coordinates. Finally, we have created a pen having proper width and drawn the line.
Since we have set the page unit to an inch, we must specify coordinates of line in inches.

How do I invoke a method using reflection?

Ans: The following example loads a user-created assembly, obtains a class type, creates its
instance and invokes a method defined in the assembly.

Assembly a = Assembly.LoadFrom ( "c:\\mymath.dll" ) ;


Type t = a.GetType ( "mymath" ) ;
MethodInfo m = t.GetMethod ( "add" ) ;
Object obj = Activator.CreateInstance ( t ) ;
Object[ ] arg = new Object [ 2 ] ;
arg [ 0 ] = 10 ;
arg [ 1 ] = 20 ;
m.Invoke ( obj, arg ) ;

This code snippet would invoke the add( ) method written in mymath class. The mymath class is
in the 'mymath.dll' assembly.

Compiled by rmshankar@yahoo.com
Documents downloaded from www.funducode.com

Compiled by rmshankar@yahoo.com

Potrebbero piacerti anche