beginning csne t .net

Upload: sureshreddy10

Post on 03-Apr-2018

218 views

Category:

Documents


0 download

TRANSCRIPT

  • 7/28/2019 Beginning Csne t .net

    1/123

    Chapter 1: Introduction to the .NET Framework.................................................................2Chapter 2: C# Language Fundamentals...............................................................................5Chapter 3: Object Oriented Programming in C#...............................................................13Chapter 4: Reflection.........................................................................................................32Chapter 5: Multithreading..................................................................................................38Chapter 6: Streams.............................................................................................................46

    Chapter 7: Sockets.............................................................................................................57Chapter 8: Distributed Programming with Remoting........................................................64Chapter 9: Database Programming with ADO.NET..........................................................73Chapter 10: GUI Programming with Windows Forms......................................................86Chapter 11: Web Programming with ASP.NET................................................................99Chapter 12: Interop and Enterprise Services...................................................................110

  • 7/28/2019 Beginning Csne t .net

    2/123

    Chapter 1: Introduction to the .NET Framework

    The .NET Framework provides a run-time environment called the Common LanguageRuntime, which manages the execution of code and provides services that make thedevelopment process easier. Compilers and tools expose the runtime's functionality andenable you to write code that benefits from this managed execution environment. Codethat you develop with a language compiler that targets the runtime is called managedcode; itbenefits from features such as cross-language integration, cross-languageexception handling, enhanced security, versioning and deployment support, a simplifiedmodel for component interaction, and debugging and profiling services.The runtime automatically handles object layout and manages references to objects,releasing them when they are no longer being used. Objects whose lifetimes are managed

    in this way by the runtime are called managed data. Automatic memory managementeliminates memory leaks as well as some other common programming errors.

    The Common Language Runtime makes it easy to design components and applicationswhose objects interact across languages. Objects written in different languages cancommunicate with each other, and their behaviors can be tightly integrated. For example,you can define a class, then, using a different language, derive a class from your originalclass or call a method on it. You can also pass an instance of a class to a method on aclass written in a different language. This cross-language integration is possible becauselanguage compilers and tools that target the runtime use a common type system definedby the runtime, and they follow the runtime's rules for defining new types, as well as

    creating, using, persisting, and binding to types.

    Registration information and state data are no longer stored in the registry where it can bedifficult to establish and maintain; instead, information about the types you define (andtheir dependencies) is stored with the code as metadata, making the tasks of componentreplication and removal much less complicated. The Common Language Runtime canonly execute code in assemblies. An assembly consists of code modules and resourcesthat are loaded from disk by the runtime. The assembly may be an executable (exe) or alibrary (dll).

    The benefits of the runtime are as follows:

    Performance improvements.

    The ability to easily use components developed in other languages.

    Extensible types provided by a class library.

    A broad set of language features.

    Currently Microsoft provides compilers for C# (Pronounced as C Sharp), VisualBasicand JScript in their .NET Framework SDK. These compilers generate the so called

  • 7/28/2019 Beginning Csne t .net

    3/123

    Intermediate Language(IL) code which is then assembled to a Portable Executable(PE)code. The PE code is interpreted at runtime by CLR for execution. Our first example isthe traditional Hello World program written in IL. (ilhello.il).assembly Hello{}

    .method public static void run() il managed{.entrypointldstr Hello World.NETcall void [mscorlib]System.Console::WriteLine(class System.String)ret

    }The above code declares Hello as an assembly(unit of code) and defines an il managedfunction called run. This function is marked as an entrypoint (the function which the CLRmust invoke when this code is executed). Next it stores a string on the stack and invokesWriteLine method of Console class (this method displays a line on screen). For resolving

    name collisions all classes in .NET library are packaged in namespaces. The Consoleclass for instance belongs to namespace called System (the root of all the namespaces inthe .NET base class library). The code for System.Console class is stored in mscorlib.dll.To execute this code, it must be first assembled to PE code using ilasm.exe utilityavailable with .NET Framework SDK.

    ilasm ilhello.il

    The above command will create ilhello.exe which when executed will displayHello World.NET

    on the screen. Needless to say that coding in raw IL is pretty difficult. For actualprogramming any .NET compliant high level language can be used. The listing belowshows same program coded in VisualBasic.Net(vbhello.vb).Imports SystemModule Hello

    Sub Main()Console.WriteLine(Hello World.NET)

    End SubEnd ModuleCompile vbhello.vb using command:vbc vbhello.vbThe code below is hello program in JScript (jshello.js)import System;Console.WriteLine(Hello World.NET);Compile jshello.js using commandjsc /EXE jshello.jsFinally the Hello World program in C# would be (cshello.cs)using System;class Hello{

  • 7/28/2019 Beginning Csne t .net

    4/123

    public static void Main(){Console.WriteLine(Hello World.NET);

    }}

    And it can be compiled using CSharp compiler as: csc cshello.csThe .NET framework not only allows you to write your program in any language but alsoallows you to use components coded in one language in a program written in another.Listed below is a component implemented in C#(bizcalc.cs) for calculating the price of adepreciating asset at an end of a given period:namespace BizCalc{

    public class Asset{public double OriginalCost;public float AnnualDepreciationRate;public double GetPriceAfter(int years){

    double price = OriginalCost;

    for(int n = 1; n

  • 7/28/2019 Beginning Csne t .net

    5/123

    Chapter 2: C# Language Fundamentals

    Basically a C# program consists of a class with a static member method (classfunction) called Main. When C# compiler (csc.exe) compiles a C# program it marks the

    Main method as the entrypoint in the generated IL code. This Main method may acceptan array of string as its argument (though this is optional). This array will always containthe command line arguments passed to the program by its user. The program below(hello1.cs) says hello to the first name on its command line.using System;class Hello1{

    public static void Main(string[] args){Console.WriteLine(Hello{0}, args[0]);Console.WriteLine(Goodbye.);

    }

    }After compiling hello1.cs execute it as : hello1 JohnThe screen will Display

    Hello John

    Goodbye.

    The statement Console.WriteLine(Hello {0}, args[0])prints a string on the consolewith {0} replaced by the second argument ie args[0] of WriteLine. Since args[0] is thefirst argument on the command line the output appears as Hello John. Now execute this

    program without any command line argument ie just: hello1The output would be:Exception occurred: System.IndexOutOfRangeException: An exception of type

    System.IndexOutOfRangeException was thrown.

    at Test.Main(String[] args)

    The program crashes with an exception (error). This is obvious because our programblindly references args[0] without checking for its existence. Also note the next statement(the one which displays Goodbye) does not execute at all.

    The runtime terminates an executing program as soon as an unhandled exception occurs.

    If you prefer the remaining code to execute, you must handle or catch the expectedexception. Our next program (hello2.cs) demonstrates how to.using System;class Hello2{

  • 7/28/2019 Beginning Csne t .net

    6/123

    public static void Main(string[] args){try{

    Console.WriteLine(Hello{0}, args[0]);}catch(Exception e){

    Console.WriteLine(e);

    }Console.WriteLine(Goodbye.);}

    }Compile and execute hello2.cs. If you execute hello2 without a command line argument,you will see the exception message as before but now the code will continue to executeand Goodbye message will be displayed. If any exception occurs in any statementenclosed within a try block the control moves into the catch block, the code in there isexecuted and the code below is resumed normally.

    The program(hello3.cs) below displays hello to the first argument on the command line,if the argument is missing it prompts the user for a name and then displays hello to theentered name.using System;class Hello3{

    public static void Main(string[] args){if(args.Length > 0){

    Console.WriteLine(Hello{0}, args[0]);}else{

    Console.Write(Enter your name: );string name = Console.ReadLine();Console.WriteLine(Hello{0}, name);

    }Console.WriteLine(Goodbye.);

    }}The Length property of an array returns the number of elements in the array. We checkthe Length of the args array and make our decision using the if-else construct. NoteConsole.ReadLine() used to input a line of text at runtime.The program below (hello4.cs) uses a forloop and displays hello to each name on thecommand line.using System;class Hello4{

    public static void Main(string[] args){

  • 7/28/2019 Beginning Csne t .net

    7/123

    for(int n = 0; n < args.Length ; n++){Console.WriteLine(Hello{0}, args[n]);

    }Console.WriteLine(Goodbye.);

    }

    }The for statement consists of three statements int n = 0; initializes an integer variable nused for iteration. n < args.Length ; is a boolean expression representing the condition forthe loop to continue. Finally ; n++ increments the value of n after every iteration.The above behaviour can also be obtained in a more readable fashion by using foreachstatement as shown in program (hello5.cs) below:using System;

    class Hello5{public static void Main(string[] args){foreach(string name in args){

    Console.WriteLine(Hello{0}, name);}Console.WriteLine(Goodbye.);

    }}Lastly hello6.cs uses whileloop to say hello to each name on command line but does it inreverse order.using System;class Hello6{

    public static void Main(string[] args){int n = args.Length 1;while(n >= 0){

    Console.WriteLine(Hello{0}, args[n--]); //decrement after use}Console.WriteLine(Goodbye.);

    }}C# is astrongly typed language thus C# variables must be declared with an available typeand must be initialized with a value (or reference) of same type. The table below lists allthe built-in types available in C#

    C# Type .NET Type Description

    bool System.Boolean true / false

  • 7/28/2019 Beginning Csne t .net

    8/123

    byte System.Byte unsigned byte value

    sbyte System.SByte signed byte value

    char System.Char a single character

    short System.Int16 16 bit signed integer

    ushort System.UInt16 16 bit unsigned integer

    int System.Int32 32 bit signed integer

    uint System.UInt32 32 bit unsigned integer

    long System.Int64 64 bit signed integer

    ulong System.UInt64 64 bit unsigned integer

    float System.Single 32 bit floating-point

    double System.Double 64 bit floating-point

    decimal System.Decimal a high precision double

    string System.String string of characters

    object System.Object a generic type

    At compile-time the C# compiler converts the C# types into their corresponding .NETtypes mentioned in the above table. Apart from above basic types user may define hisown types using enum,structand class. The program below (club1.cs) shows how and tocreate user-defined type

    using System;enum MemberType {Lions, Pythons, Jackals, Eagles};struct ClubMember{

    public string Name;public int Age;

    public MemberType Group;}class Test{

    public static void Main(){ClubMember a = new ClubMember();a.Name = "John";a.Age = 13;a.Group = MemberType.Eagles;ClubMember b = a; // new copy of a is assigned to bb.Age = 17; // a.Age remains 13Console.WriteLine("Member {0} is {1} years old and belongs to

    the group of {2}", a.Name, a.Age, a.Group); // above line}

    }The enum keyword is used to declare an enumeration, a distinct type consisting of a setof named constants called the enumerator list. Every enumeration type has an underlyingtype, which can be any integral type except char. The default type of the enumeration

  • 7/28/2019 Beginning Csne t .net

    9/123

    elements is int. By default, the first enumerator has the value 0, and the value of eachsuccessive enumerator is increased by one. For example: enum MemberType {Lions,Pythons, Jackals, Eagles};In this enumeration, Lions is 0, Pythons is 1, Jackals is 2 and Eagles is 3. Enumerators

    can have initializers to override the default values. For example: enum MemberType

    {Lions = 1, Pythons, Jackals, Eagles};Now Lions is 1, Pythons is 2, Jackals is 3 and Eagles is 4.

    The struct keyword is used to create a composite type called structure . In above exampleClubMember is a structure with three fields Name, Age and Group. Note the Group fieldis of type MemberType and as such it can take only one of the four values defined inMemberType enum. The fields are declared public so that they are accessible outside thescope of struct block. To use a structure you must first instantiate it i.e allocate necessarymemory for its fields. This is done by using new keyword as done in the Main method ofclass Test: ClubMember a = new ClubMember(); In this statement a variable a isdeclared to be of type ClubMember and a newly created instance is assigned to it. Next

    the public fields of ClubMember is set for this instance. Note how Group field of a is set:a.Group = MemberType.Eagles;A struct is a value type i.e when a variable holding an instance of a struct is assigned

    to another variable of same type, a new copy of the instance is created and assigned.

    Consider statementClubMember b = a;Here b contains a copy of a. Thus change in

    one of the fields of b does not affect fields of a. Thus output of program prints age of

    John as 13. In contrast the class is a reference type. club2.cs is similar to club1.cs

    except now ClubMember is a class instead of struct.

    using System;

    enum MemberType {Lions, Pythons, Jackals, Eagles};class ClubMember{public string Name;public int Age;public MemberType Group;

    }class Test{

    public static void Main(){ClubMember a = new ClubMember();a.Name = "John";a.Age = 13;a.Group = MemberType.Eagles;ClubMember b = a; // b and a refer to same instanceb.Age = 17; // a.Age also becomes 17Console.WriteLine("Member {0} is {1} years old and belongs to

    the group of {2}", a.Name, a.Age, a.Group);//above line}

    }

  • 7/28/2019 Beginning Csne t .net

    10/123

    Here since ClubMember is a class the assignment ClubMember b = a; assigns variable ba reference to instance referenced by variable a. i.e now a and b are both holding areference to same instance, any change in field of b will change the corresponding fieldof a . Hence the output of program prints age of John as 17.

    An array of values can be created in C# using one of the following syntaxes;type[] arr = {val0, val1, val2, val3, };type[] arr = new arr[size_of_array];

    For example:

    int[] k = {12, 15, 13, 19};double[] p = new double[3];p[0] = 9.3; p[1] = 12.8; p[2] = 7.7;

    In modular programming it is desirable to divide a program into multiple procedures(methods in C#). The program below (maximizer.cs) implements user-defined methods toobtain maximum of double values. These methods are then called from Main.using System;public class Maximizer{

    public static double Max(double p, double q){if(p > q) return p;return q;

    }public static double Max(double p, double q, double r){

    return Max(Max(p,q),r);}public static void Main(){

    Console.WriteLine(Maximum of 12.8 and 19.2 is {0}, Max(12.8,19.2));Console.WriteLine(Maximum of 21.7, 12.8 ,19.2 is {0} ,Max(21.7,12.8,19.2));

    }}

    Note the above programs defines to Max methods with different set of arguments. This iscalled method overloading. Both Max methods are declared public and static and as suchthese methods can be invoked from any class using fully qualified name Maximizer.Max.(A static method can be invoked on the class itself, no instance of the class is required)The invocation Maximizer.Max(13.5,21.7,12.8,19.2)will not compile since classMaximizer does not define any Max method which takes 4 double values as itsarguments. Well, we could create one more overload of Max but then what about Maxwith more than 4 doubles. C# solves this problem using params keyword. Given belowis a version of Max (you can incooperate this in maximizer.cs) which takes any numberof double values as its argument

  • 7/28/2019 Beginning Csne t .net

    11/123

    public static double Max(params double[] list){

    if(list.Length == 0) return 0;double max = list[0];foreach(double val in list){

    if(val > max) max = val;}return max;

    }When user invokes this method as Max(31.3, 9.1,13.5,21.7,12.8,19.2) the arguments arepassed to Max in an array of double (referred in Max as list)In C# the arguments are passed to a method by value i.e a copy of variable is passedinstead of the original variable. Thus when a caller of a method passes some variable tothe method as an argument and the method alters the value of this argument, the original

    value of the variable remains unchanged. In C a function may accept a pointer to avariable and the make a permanent change to its value. C# allows the use of pointer butonly in an unsafe method (the code in this method is not managed by CLR). The listingbelow (swapper1.cs) implements an unsafe method which receives pointers to variablesand swaps their values.

    using System;public class Swapper1{

    // Swap is an unsafe method which accepts pointers to two integers (int*)public static unsafe void Swap(int* p, int* q){

    int t = *p; // store the value referenced by p in t*p = *q;*q = t;

    }

    public static unsafe void Main(){int m = 109, n = 73;Console.WriteLine(m = {0} and n = {1},m,n);Console.WriteLine(Invoking Swap);// address-of operator (&) can only be used in an unsafe methodSwap(&m, &n);Console.WriteLine(m = {0} and n = {1},m,n);

    }}Compile the above source as: csc /unsafe swapper1.cs

    If you execute the program you will notice the variables are swapped successfully. It isnot necessary to rely on unsafe code just for sake of passing a variable to a method by

  • 7/28/2019 Beginning Csne t .net

    12/123

    reference. C# provides refkeyword for passing and receiving arguments by reference.swapper2.cs uses this approach to swap values of variables.using System;public class Swapper2{

    // Swap receives two integers by reference (ref int)public static void Swap(refint p, refint q){int t = p;p = q;q = t;

    }public static void Main(){

    int m = 109, n = 73;Console.WriteLine(m = {0} and n = {1},m,n);Console.WriteLine(Invoking Swap);Swap(refm, refn); // passing m and n by reference to Swap

    Console.WriteLine(m = {0} and n = {1},m,n);}}A method can return only one value, what if more than one value ie expected from amethod. For this purpose C# uses out keyword. An uninitialized out argument can bepassed to a method and that method can set the value of this argument. The programbelow(divider.cs) defines a method called Divide which returns quotient and remainder indivision of one integer by another. The quotient is returned in a normal way (usingreturn keyword) and remainder is returned through an out argument.using System;class Divider{

    public static int Divide(int dividend, int divisor, out int remainder){int quotient = dividend/divisor;remainder = dividend - quotient * divisorreturn quotient;

    }public static void Main(string[] args){

    int r;int q = Divide(157, 23, out r);Console.WriteLine("Quotient = {0} and Remainder = {1}, q,r);

    }}

    Qualifier read write

    yes no

    ref yes yes

    out no yes

  • 7/28/2019 Beginning Csne t .net

    13/123

    Chapter 3: Object Oriented Programming in C#

    Object Oriented Programming (OOP) is essentially programming in terms ofsmaller units called objects. An object oriented program is composed of one or more

    objects. Each objectholds some data (fields or attributes) as defined by its class. Theclass also defines a set of functions (methods or operations) which can be invoked on itsobjects. Generally the data is hidden within the object and can be accessed only throughfunctions defined by its class (encapsulation). One or more objects (instances) can becreated from a class by a process called instantiation. The process of deciding whichattributes and operations will be supported by an object (i.e defining the class) is calledabstraction. We say the stateof the object is defined by the attributes it supports and itsbehaviouris defined by the operations it implements. The termpassing a messageto anobject means invoking its operation. Sometimes the set of operations supported by anobject is also referred to as the interfaceexposed by this object.

    Given below is a simple class (item.cs) which defines an Item. Each item supports twoattributes, its cost and the percent profit charged on it and provides some operations.public class Item{

    private double _cost;private float _profit;private static int _count;public Item(){

    _count++;}public Item(double cost, float profit){

    if(cost > 0) _cost = cost;_profit = profit;_count++;

    }public double Cost{

    get {return _cost;

    }set{

    if(value > 0) _cost = value;}

    }public float Profit{

    get {return _profit;

    }set{

    _profit = value;}

  • 7/28/2019 Beginning Csne t .net

    14/123

    }public static int Count{

    get{return _count;

    }

    }// use of virtual modifier will be explained laterpublic virtual double SellingPrice(){

    return _cost * (1 + _profit / 100);}public double EMI(){

    double amount = 1.12 * SellingPrice(); // 12% interestreturn amount / 12;

    }}

    Class Item defines two private member variables, _cost and _profit. These variables arevisible only inside the body of class Item. An outsider can only access these variablesthrough special property methods(Cost and Profit). For example a user may create aninstance of the class as follows.

    Item p = new Item();p._cost = 1200; // compile-time error, _cost is not accessiblep.Cost = 1200; //works, invokes set method of Cost with value = 1200

    A property implemented in a class is automatically translated by the C# compiler to a pairof methods. For example the Cost property in Item class is translated by the compiler to:

    public double get_Cost (){return cost;

    }public void set_Cost (double value){

    if (value > 0) cost = value;}

    Which also explains the use of undeclared variable value in the set part of a property.A non-static (instance) variable is stored within object of the class, thus each object hasits own copy of a non-static variable. A static (class) variables on the other hand is storedwithin the class and is shared by all of its objects. In Item class _count is a static variableused for determining number of times the class has been instantiated. The value of thisvariable can be obtained using the Count property of the class. Note the Count property ismarked static which means a user may access it as Item.Count. As non-static membervariables are not stored in a class, a static method cannot directly reference a non-staticmember of the class.

  • 7/28/2019 Beginning Csne t .net

    15/123

    A user instantiates a class by applying the new operator to the class constructor(amethod whose name matches with the class name and does not define any return type). Aclass may define multiple constructors. If no constructor is defined by the class a default(no argument) constructor is automatically made available to the class. Item class definestwo constructors. A user may instantiate and initialize Item as follows:

    Item p = new Item(); // using default constructorp.Cost = 1200;p.Profit = 9;Item q = new Item(1500,8); // using second constructor

    Item class also provides two utility methods for calculating selling price and the equalmonthly installment (1 year scheme) for the item.The program below(itemtest1.cs) uses Item class

    using System;class ItemTest1{

    public static void Main(){Item pc = new Item(32000, 12);Item ac = new Item(25000, 10);Console.WriteLine(Selling price of PC is {0} and its EMI is {1},

    pc.SellingPrice(), pc.EMI());Console.WriteLine(Selling price of AC is {0} and its EMI is {1},

    ac.SellingPrice(), ac.EMI());Console.WriteLine(Number of Items created: {0}, Item.Count);

    }}To compile itemtest1.cs either first compile item.cs to create a dll and then compileitemtest1.cs referencing item.dll (Note: only public classes from one assembly can beaccessed from other assembly, hence class Item is declared public in item.cs)

    csc /t:library item.cs creates item.dllcsc /r:item.dll itemtest1.cs creates itemtest1.exe

    You can also compile itemtest.cs by using command

    csc itemtest1.cs item.cs creates only itemtest1.exeOne of the most important feature of OOP issubclassing. It involves creation of a new(sub or derived) class based on an existing(super or base) class. The members of the baseclass are automatically made available to the derived class (inheritance). Subclassingenforces an is-a relationship between two classes i.e an instance of the base class can bereplaced by an instance of the derived class in other words an instance of the derivedclass is also an instance of the base class. For example let DClass be a subclass ofBClass (In C#, DClass : BClass), the above rule makes it possible to write: BClass obj =

  • 7/28/2019 Beginning Csne t .net

    16/123

    new DClass(); Thus for compiler obj is an object of BClass however at runtime obj isassigned to an instance of DClass. The opposite will obviously not compile.

    Though the derived class inherits all the operations supported by the base class but forsome reason the derived class may want to change the behaviour (implementation) of an

    operation it inherits. The derived class may do so either by overridingor by hidingtheoperation of the base class. The difference in the two approach can be described asfollows. Let DClass be a subclass of BClass and let both of these classes have their ownimplementations for a method called SomeOperation(). Now consider statements:

    BClass obj = new DClass();obj.SomeOperation();

    If DClass overrides SomeOperation() of BClass, obj.SomeOperation() will be invokedfrom DClass despite of the fact that obj is declared to be an object of BClass. Thisbehaviour is calledpolymorphism(capability of an operation to exhibit multiple

    behaviours) orlate-binding(determining address of operation to be invoked at run-timeand not at compile-time).However if DClass hides SomeOperation() of BClass thenobj.SomeOperation() will be invoked from BClass despite of the fact that obj is assignedto an instance of DClass.

    To override a method of base class the derived class must use override modifier whileredeclaring this method and this is only allowed for those methods which have beendeclared with virtual modifier in the base class. To hide a method of base class thederived class must use new modifier while redeclaring this method, the same method inbase class may or may not be declared virtual.Given below is an implementation of a subclass of Item called SpecialItem(specialitem.cs). This class adds a Discount property to Item and overrides itsSellingPrice (virtual) method .using System;public class SpecialItem : Item{

    private float _discount;public SpecialItem(double c, float p, float d) : base(c,p){

    if(d > 0) _discount = d;}public float Discount{

    get {return _discount;

    }set{

    if(value > 0) _discount = value;}

    }

  • 7/28/2019 Beginning Csne t .net

    17/123

    public override double SellingPrice(){double price = base.SellingPrice();return price * (1 - _discount/100);

    }}

    Note a subclass constructor must first invoke the base class constructor, this is doneby attaching :base() to the constructor of the subclass. If no such arrangement ismade by the subclasser then the default (no argument) constructor of base class will

    be called (absence of which will result in a compile time error). Also note howSellingPrice method of SpecialItem invokes the same method from its base class usingbase keyword. SpecialItem class does not reimplement the EMI method, when EMImethod is invoked on an instance of SpecialItem the implementation from Item will beinvoked however EMI method will properly invoke the SellingPrice method ofSpecialItem. If instead of overriding SellingPrice method, SpecialItem would havehidden it (replacing override modifier by new modifier) then EMI method would call the

    SellingPrice of Item which would not take in account the Discount.The program below (itemtest2.cs) uses both Item and SpecialItem classes:using System;class ItemTest2{

    public static void Main(){Item pc = new Item(25000, 12);SpecialItem ac = new SpecialItem(25000, 12, 7);Console.WriteLine(Selling price of PC is {0} and its EMI is {1},

    pc.SellingPrice(), pc.EMI());Console.WriteLine(Selling price of AC is {0} and its EMI is {1},

    ac.SellingPrice(), ac.EMI());Console.WriteLine(Number of Items created: {0}, Item.Count);

    }}Compile this program as: csc itemtest2.cs item.cs specialitem.csThe output of the program will show that both Selling price and EMI of AC are lesserthan the Selling price and EMI of PC even though the cost and profit of both the items aresame.The rule of inheritance (an instance of base class can be replaced by that of derived class)allows us to place objects of SpecialItem in an array of Item objects. For example thecode below is legal:

    Item[] store = {new Item(1500, 7), new SpecialItem(22000, 10, 5),new SpecialItem(3500,12,7), new Item(15000,0), new Item(750, 5)};

  • 7/28/2019 Beginning Csne t .net

    18/123

    Now consider a routine to calculate total SellingPrice of all the items in the store.

    double total = 0;foreach(Item itm in store){

    total += itm.SellingPrice();

    }Since SellingPrice() is virtual in Item and has been overriden in SpecialItem, for store[1]and store[2] the SellingPrice() method is invoked from SpecialItem (for compiler itm isan object of Item). What if we have to calculate average discount on all the items in thestore. In code similar to above itm. Discount will not compile since compiler will look forDiscount property in Item class (itm is declared to be Item in foreach). Also statementforeach(SpecialItem itm in store) will not compile because store is declared to be an arrayof Item. The code below identifies which of the items in store are of type SpecialItemthen converts these items to objects of SpecialItem and sums their discount:

    double total = 0;foreach(Item itm in store){if(itm is SpecialItem){

    SpecialItem sitm = itm as SpecialItem;total += sitm.SellingPrice();

    }}

    The is operator is used to check whether a given object is an instance of a given class andthe as operator is used to narrow object of base class to an object of its derived class. Theconversion SpecialItem sitm = itm as SpecialItem; can also be achieved by means ofcasting SpecialItem sitm = (SpecialItem) itm; the difference between these two methodsof conversion is that the first approach (using as operator) will return null if theconversion fails while the second approach (using the cast operator) will throwSystem.InvalidCastException if the conversion fails.Next consider a similar situation. A bank currently supports two types of accounts,SavingsAccount and CurrentAccount (more types are expected in future). Both of theseaccount types support a Withdraw operation with obviously different behaviours. Youdont want one of these account type to be a subclass of other since the statementSavingsAccount is a CurrentAccount or vice versa does not hold good and yet youwant to place the instances of these account type in a single array. A simple solutionwould be to inherit both of these account types from a common base class say Accountand then create an array of Account.

    Account[] bank = {new SavingsAccount(), new CurrentAccount(), };Both SavingsAccount and CurrentAccount are derived from Account and supportWithdraw(double amount) operation. Now lets write a routine which withdraws 500 fromall the accounts in bank array.

    foreach(Account acc in bank){

  • 7/28/2019 Beginning Csne t .net

    19/123

    acc.Withdraw(500);}

    Naturally the compiler looks for Withdraw method in Account class and runtime invokesthe overriden method from the appropriate subclass. This clearly means Account class

    must provide a virtual Withdraw method. But it cannot provide implementation for thismethod because the implementation depends on the actual type of account. Such anoperation (method) without behaviour (implementation) is called an abstract method.Account class will declare Withdraw to be an abstract method and the implementation tothis method will be provided by SavingsAccount and CurrentAccount by overriding it.On any grounds user must not be allowed to instantiate the Account class otherwise hemight invoke the codeless Withdraw method directly from the Account. Such a classwhich cannot be instantiated is called an abstract class. Only abstract classes can haveabstract methods. Howeverits possible to create an abstract class without any abstractmethod.A subclass of an abstract class must provide implementation for all the abstractmethod it inherits from its superclass or the subclass must itself be declared abstract. C#

    uses abstract keyword to declare abstract methods and abstract classes. Note an abstractmethod is automatically virtual and must be defined in the derived class with overridemodifier (new modifer will cause a compile time error since inherited abstract methodscannot be hidden)Code below(bank.cs) contains an abstract Account class and its subclasses among otherclasses (explanation follows the code)namespace Project.Bank{

    public class InsufficientFundsException : System.Exception{}

    public class IllegalTransferException : System.Exception{}

    public abstract class Account{

    public abstract void Deposit(double amount);public abstract void Withdraw(double amount);public abstract double Balance{

    get;}public void Transfer(double amount, Account other){

    if(other == this) throw new IllegalTransferException();this.Withdraw(amount); // same as Withdraw(amount);other.Deposit(amount);

    }}

    public abstract class BankAccount : Account{

    protected double _balance; // also accessible to any subclass

  • 7/28/2019 Beginning Csne t .net

    20/123

    internal string _id; // also accessible to any other class in this dll

    public string ID{get{

    return _id;

    }}public override double Balance{

    get{return _balance;

    }}public override void Deposit(double amount){

    _balance += amount;}

    }

    public sealed class SavingsAccount : BankAccount{public const double MIN_BALANCE = 500.0;public SavingsAccount(){

    _balance =MIN_BALANCE;_id = S/A;

    }public override void Withdraw(double amount){

    if(_balance amount < MIN_BALANCE){throw new InsufficientFundsException();

    }_balance -= amount;

    }}

    public sealed class CurrentAccount : BankAccount{

    public const double MAX_CREDIT = 50000.0;public CurrentAccount(){

    _id = C/A;}public override void Withdraw(double amount){

    if(_balance amount < - MAX_CREDIT){throw new InsufficientFundsException();

    }_balance -= amount;

    }}public sealed class Banker{

    private static Banker self;private int nextid;

  • 7/28/2019 Beginning Csne t .net

    21/123

    private Banker(){nextid = 1001;

    }public static Banker GetBanker(){

    if(self == null) self = new Banker();

    return self;}public BankAccount OpenAccount(string type){

    BankAccount acc;if(type == SavingsAccount) acc = new SavingsAccount();else if(type == CurrentAccount) acc = new CurrentAccount();else return null;acc._id += nextid++;return acc;

    }}

    }Here are important points to note about bank.cs1. All the classes are placed in a namespace Project.Bank. Namespaces are used to

    organize related classes into a group and also to protect classes from name conflicts.A user may refer to Account class in namespace Project.Bank by its fully qualifiedname, i.eProject.Bank.Accountor he might first mention using Project.Bankandthen refer to Account class asAccount. A user can also alias the namespace as

    using pb = Project.Bankand then refer to Account class aspb.Account.2. Classes InsufficientFundsException and IllegalTransferException represent

    exceptions since they are derived from System.Exception. Instances of subclassesof System.Exception can be used along with throw keyword within a methodbody to trigger an error situation. Throwing of an exception immediately abortsthe method and the control moves into the callers catch block for that exception.

    3. The Account class is an abstract class. It defines two abstract methods and anabstract get property for Balance. It also provides the Transfer method fortransferring an amount from an Account on which Transfer was invoked (whichis referred in body of Transfer using the this keyword) to another Account passedas the other argument. If the source of transfer is exactly same object as itsdestination, the Transfer method throws IllegalTransferException.

    4. The BankAccount class is derived from Account class but does not implement itsWithdraw method and as such has been declared abstract. This class defines twomember variables _balance and _id. _balance is declared as protected this meansapart from the currrent class this member is accessible to the subclasses also. The_id is declared internal which means apart from the current class this member isaccessible to any other class in the current assembly (protectedinternal is alsoallowed and it means apart from the current class the member will be accessible onlyto the subclasses or any other class in the current assembly)

    5. SavingsAccount and CurrentAccount are two concrete implementations of Account.Both of these classes are derived from BankAccount and are declared sealed which

  • 7/28/2019 Beginning Csne t .net

    22/123

  • 7/28/2019 Beginning Csne t .net

    23/123

    class need to inherit multiple characteristics. Consider an abstract class called Profitablegiven below

    public abstract class Profitable{public abstract void AddInterest(float rate, int period);

    }A bankable entity (not necessarily an account) which provides interest must be derivedfrom above class and provide an implementation for AddInterest. What ifSavingsAccount wants to support interest? It cannot subclass both BankAccount andProfitable. To resolve this issue, C# introduces a concept ofinterface. An interface canbe regarded to be a pure abstract class as it can only contain abstract operations (abstractclasses may contain non-abstract operations also). A class may inherit from one and onlyone other class but can inherit from multiple interfaces. When a class inherits from aninterface it must provide implementations for all the methods in that interface or the

    class must be declared abstract. The above Profitable may now be defined as an interface

    (add this to bank.cs).public interface IProfitable{

    void AddInterest(float rate, int period);}

    Methods declared in an interface are public and abstract by default and when a classimplements a method which it inherits from an interface the override modifier isautomatically understood.The SavingsAccount class (update bank.cs) can inherit from both BankAccount andIProfitable as follows:

    public sealed class SavingsAccount : BankAccount, IProfitable{public const double MIN_BALANCE = 500.0;public SavingsAccount(){

    _balance =MIN_BALANCE;_id = S/A;

    }public override void Withdraw(double amount){

    if(_balance amount < MIN_BALANCE){throw new InsufficientFundsException();

    }_balance -= amount;

    }//override is understoodpublic void AddInterest(float rate, int period){

    _balance = _balance * (1 + rate * period /100);}

    }

  • 7/28/2019 Beginning Csne t .net

    24/123

    The statement IProfitable acc = new SavingsAccount(); compiles since SavingsAccountimplements IProfitable howeverIProfitable acc = new CurrentAccount(); will cause acompile-time error.

    Next consider following two interfaces

    public interface ITaxable{void Deduct();

    }

    public interface IFinable{void Deduct();

    }Now suppose we would like our CurrentAccount class to implement both of theseinterfaces. Clearly this is not possible as both of these interfaces contain members with

    same signature. This problem is solved in C# by using explicit interface memberimplementations. The code below demonstrates the technique.

    public sealed class CurrentAccount : BankAccount, ITaxable, IFinable{public const double MAX_CREDIT = 50000.0;public CurrentAccount(){

    _id = C/A;}public override void Withdraw(double amount){

    if(_balance amount < - MAX_CREDIT){throw new InsufficientFundsException();

    }_balance -= amount;

    }// implementation of Deduct() inherited from ITaxablevoid ITaxable.Deduct(){

    if(_balance > 50000) _balance *= 0.95;}// implementation of Deduct() inherited from IFinablevoid IFinable.Deduct(){

    if(_balance < -0.5*MAX_CREDIT) _balance *= 0.98;}

    }The member methods are implemented with their fully qualified names(InterfaceName.MemberName). The methods implemented in this fashion must bedeclared without any access modifier (private, protected, public) and as such are onlyaccessible through an interface instance. For example the right way to invokeITaxable.Deduct() method of CurrentAccount is

  • 7/28/2019 Beginning Csne t .net

    25/123

    ITaxable acc = new CurrentAccount(); // declare acc to be an instance of ITaxableacc.Deduct(); // this will invoke ITaxable.Deduct() implemented in CurrentAccount

    C# defines delegate keyword, which can be used to receive a reference to a method. It isvery useful in situations where a class needs to invoke a method implemented by its user

    (such methods are also called callback methods). Our next class (fixeddeposit.cs)FixedDeposit uses a delegate to invoke a method passed by its user for determining therate of interest.using System;namespace Project.Bank{

    // Scheme represents a method which takes a double and an int as its arguments and// returns a float;public delegate float Scheme(double principal, int period);

    public class FixedDeposit{

    private double deposit;private int duration;private Scheme InterestRate; // InterestRate is a method of type Scheme

    public FixedDeposit(double p, int n, Scheme s){

    deposit = p;duration = n;InterestRate = s;

    }

    public double Deposit{get{

    return deposit;}

    }

    public int Duration{get{

    return duration;}

    }

    public double Amount{get{

    float rate = InterestRate(deposit,duration); //callback users methodreturn deposit * Math.Pow(1 + rate/100, duration);

    }}

    }}

  • 7/28/2019 Beginning Csne t .net

    26/123

    The program below (fdtest.cs) makes use of above class:

    using Project.Bank;using System;class FDTest{

    public static float MyRate(double p, int n){return (n < 5) ? 9 : 11;

    }

    public float HisRate(double p, int n){return (p < 20000) ? 8 : 10;

    }

    public static void Main(){FixedDeposit myfd = new FixedDeposit(25000,7,new Scheme(MyRate));FixedDeposit hisfd = new FixedDeposit(25000,7,

    new Scheme(new FDTest().HisRate));Console.WriteLine("I get {0:#.00}",myfd.Amount); // formatted outputConsole.WriteLine("He gets {0:#.00}",hisfd.Amount);

    }}In the Main method an instance of Scheme delegate is created using method MyRate andis passed to FixedDeposit constructor which saves the reference in its InterestRatemember variable. When Amount get property of myfd is called MyRate is invoked byFixedDeposit. Note how a Scheme delegate is created using a non-static method HisRate.Delegates are mostly used to implement events. An event is a notification sent by asenderobject to a listenerobject. The listener shows an interest in receiving an event byregistering an event handler method with the sender. When event occurs the senderinvokes event handler methods of all of its registered listeners. In our bank.cs theAccount class provides a Transfer method for transferring funds from one account toanother. We would like target account to raise an event whenever a transfer is successful.Replace the Account class in bank.cs by following code:

    public delegate void TransferHandler(Account source, double amount);public abstract class Account{

    public event TransferHandler FundsTransferred;public abstract void Deposit(double amount);public abstract void Withdraw(double amount);public abstract double Balance{

    get;}

  • 7/28/2019 Beginning Csne t .net

    27/123

    private void OnFundsTransferred(Account source, double amount){if(FundsTransferred != null) FundsTransferred(source, amount);

    }public void Transfer(double amount, Account other){

    if(other == this) throw new IllegalTransferException();

    this.Withdraw(amount); // same as Withdraw(amount);other.Deposit(amount);// raise FundsTransferred event on otherother.OnFundsTransferred(this, amount);

    }}

    First a delegate called TransferHandler is declared, next in Account class we declare anevent called FundsTransferred whose handler is of type TransferHandler. In the Transfermethod the event is fired on the other account. The program below (banktest2.cs) showshow to register an event handler and handle the event.

    using Project.Bank;using System;class BankTest2{

    // The event handler methodpublic static void vend_FundsTransferred(Account source, double amount){

    Console.WriteLine(Vendor received amount {0}, amount);}public static void Main(){

    Banker banker = Banker.GetBanker();BankAccount cust = banker.OpenAccount(SavingsAccount);BankAccount vend = banker.OpenAccount(CurrentAccount);cust.Deposit(12000);//register the event handler method with vendvend.FundsTransferred += new TransferHandler(vend_FundsTransferred);

    Console.Write("Enter amount to transfer: ");double amt = Double.Parse(Console.ReadLine());try{

    cust.Transfer(amt,vend);}catch(InsufficientFundsException e){

    Console.WriteLine("Transfer Failed");}Console.WriteLine("Customer: Account ID: {0} and Balance: {1}",cust.ID,

    cust.Balance);Console.WriteLine("Vendor: Account ID: {0} and Balance: {1}",vend.ID,

    vend.Balance);}

    }

  • 7/28/2019 Beginning Csne t .net

    28/123

    The event handler is registered by adding (+=) the delegate of event handler to theFundsTransferred event of the Account. This allows registeration of multiple eventhandler methods. When event occurs all the handlers will be invoked.Operator Overloading is yet another feature introduced in C#. It allows a class to redefine

    standard operators for its instances. Not all operators can be overloaded nor newoperators can be created. The class below (money.cs) shows how to overload some of theoperators in C#using System;public class Money{

    private int dollars;private int cents;

    public Money(int d, int c){dollars = d;cents = c;

    }

    public static Money operator+(Money lhs, Money rhs){int d = lhs.dollars+rhs.dollars;int c = lhs.cents+rhs.cents;if(c > 100){

    d += 1;c -= 100;

    }return new Money(d,c);

    }

    public static explicit operator Money(double rhs){int d = (int) rhs;int c = (int)(100*rhs-100*d);return new Money(d,c);

    }

    public static implicit operator double(Money rhs){return rhs.dollars + rhs.cents/100.0;

    }

    public static bool operator(Money lhs, Money rhs){

  • 7/28/2019 Beginning Csne t .net

    29/123

    return (lhs.dollars + lhs.cents/100.0) > (rhs.dollars + rhs.cents/100.0);}

    }The above class overloads +, < and > operators. The methods used for operator

    overloading must be static and must be named as operator op (where op is the operator tobe overloaded) C# compiler will translate these method names appropriately beforecompiling (for example method name operator+ is transalated to op_Addition)Some operators must be overloaded in pairs for example if you overload operator < youmust also overload operator >. C# does not allow overloading of cast () operator butallows you to define explicit and implicit operators. If conversion is defined throughexplicit operator then an appropriate cast will be needed during conversion. In aboveclass conversion of Money instance to double is defined using explicit operator thusstatement Money m = 123.45; will cause a compile-time error. The correct approach isMoney m = (Money)123.45; On the other hand conversion of a Money instance to adouble is defined using implicit operator and this conversion will not require a cast i.e

    statement double m = new Money(123, 45); will compile. The program below(moneytest.cs) shows how to use Money class.using System;class MoneyTest{

    public static void Main(){Money k = new Money(123, 45); // instantiating with constructorMoney l = (Money) 13.75; // explicit conversionMoney m = k + l; // using + operatordouble n = m; // implicit conversion;Console.WriteLine(n); // must display 137.18

    }}

    One last important feature of C# language is the indexer. Indexer allows an instance tobehave like an array i.e it allows notation of type instance[index] to be used to accesscertain information. The class RandomList mentioned below (randomlist.cs) generates alist of first n consecative integers and provides an operation to shuffel this list. It providesan indexer for retrieving the elements of the list. It also supports features which wouldallow a user to iterate through the list using foreach statement.using System;public class RandomList{

    private int[] list;private int current;

    public RandomList(int size){

    list = new int[size];

  • 7/28/2019 Beginning Csne t .net

    30/123

    for(int i=0;i1;i--){int j = gen.Next(0,i); // random integer between 0 and iint t = list[i-1];list[i-1]=list[j];list[j] = t;

    }}

    public int Count{get{

    return list.Length;

    }}

    //support for indexerpublic int this[int index]{

    get{return list[index];

    }}

    //support forforeach statementpublic bool MoveNext(){

    return (++current < list.Length);}

    public int Current{

    get{return list[current];

    }}

    public RandomList GetEnumerator(){

    current = -1;return this;

    }

    public static void Maim(){RandomList list = new RandomList(10);// using the indexerfor(int k = 0; k < list.Count;k++){

  • 7/28/2019 Beginning Csne t .net

    31/123

    Console.WriteLine(list[k]);}list.Shuffle();// using the iteratorforeach(int k in list){

    Console.WriteLine(k);}}

    }Class RandomList accepts a size through its constructor and populates an internal arraywith consecative integers. The Shuffle method shuffles the internal array by swappingelements at random positions. Next it provides the indexer which allows reading ofelements using [] notation i.e the third element of a RandomList instance rl can beaccessed by rl[2].Any class which supports iteration through foreach statement must provide a method

    called GetEnumerator() which returns a reference to an instance of a class whichprovides a get property called Currentand a method calledMoveNext() which returns abool value. Since RandomList itself provides Current property and MoveNext() methodits GetEnumerator returns its own reference (this). The foreach statement first obtains areference from GerEnumerator() and continuously returns the value returned by theCurrent property of the reference as long as its MoveNext() method returns true. TheMain method show two different method to iterate RandomList. The first method usesindexer and second uses iterator.

  • 7/28/2019 Beginning Csne t .net

    32/123

    Chapter 4: Reflection

    Exposing and utilizing types at runtime is calledReflection. The type of an object isstored as an instance of System.Type class the reference to which can be obtained usingone of the following methods.

    1. From the declaration type: If declaration ATypevar is legal then System.Type

    representing AType can be obtained using typeofoperator as:Type t = typeof(AType);

    2. From an instance: Type of an instance obj can be obtained using GetType method

    defined in System.Object as:Type t = obj.GetType();

    3. From the type name within current/referenced assembly: System.Type offers a static

    method called GetType to obtain a Type from a fully qualified name of the type. The

    name will be searched in the current and all the referenced assemblies.Type t = Type.GetType(FullyQualifiedTypeName);

    4. From the type name within any assembly: First load the assembly and obtain a

    reference to it. This reference can be used to obtain the Type with given name:using System.Reflection;Assembly asm = Assembly.LoadFrom(AssemblyName);Type t = asm.GetType(FullyQualifiedTypeName);

    Alternatively one could also use:Type t = asm.GetType(FullyQualifiedTypeName,AssemblyName);

    The program below(showtypes.cs) displays all the Types defined in an assembly whosename is passed in first command line argument:using System;using System.Reflection;class ShowTypes{

    public static void Main(string[] args){Assembly asm = Assembly.LoadFrom(args[0]);Type[] types = asm.GetTypes();foreach(Type t in types) Console.WriteLine(t);

    }}Execute this program using command line: showmethods anyassembly.dllPass complete path to any .NET exe or dll to see the types declared in it.

  • 7/28/2019 Beginning Csne t .net

    33/123

    The second program (showmembers.cs) takes assembly name and type name as itscommand line arguments and displays all the members defined in that type of thatassembly.using System;

    using System.Reflection;class ShowMembers{

    public static void Main(string[] args){Assembly asm = Assembly.LoadFrom(args[0]);Type t = asm.GetType(args[1]);MemberInfo[] members = t.GetMembers();foreach(MemberInfo m in members) Console.WriteLine(m);

    }}

    Using reflection it is also possible to create an instance of a class and invoke its membermethods at runtime. This feature can be used to write more generic (dynamicallyextensible) programs which receive names of classes at runtime. Consider one suchprogram which is supposed to calculate the amount that a user will receive if he invests acertain amount for a certain period of time in a certain investment policy. The rate ofinterest will depend on the policy in which he invests. Our program must take the nameof the class which implements policy at runtime and perform the calculations. The codebelow(invpol.cs) provide implementations for various policies:public interface Policy{

    float Rate(double principal, int period);}public class BronzePolicy : Policy{

    public float Rate(double p, int n){return 7;

    }}public class SilverPolicy : Policy{

    public float Rate(double p, int n){return (p < 25000) ? 8 : 10;

    }}public class GoldPolicy {

    public float Rate(double p, int n){return (n < 5) ? 9 : 11;

    }}

  • 7/28/2019 Beginning Csne t .net

    34/123

    public class PlatinumPolicy : Policy{

    public float Rate(double p, int n){float r = (p < 50000) ? 10 : 12;if(n >= 3) r += 1;

    return r;}}Each policy provides a Rate method which returns the rate of interest for a givenprincipal and for a given period. All policy classes implement Policy interface exceptGoldPolicy which defines Rate without implementing policy. Compile invpol.cs to createinvpol.dll: csc /t:library invpol.csHere is our investment program (investment.cs) which accepts principal, period andpolicy name as its arguments and displays the amount the investor will receive:

    using System;using System.Reflection;class Investment{

    public static void Main(string[] args){double p = Double.Parse(args[0]); // string to doubleint n = Int32.Parse(args[1]); // string to intType t = Type.GetType(args[2]);Policy pol = (Policy)Activator.CreateInstance(t);float r = pol.Rate(p,n);double amount = p*Math.Pow(1+r/100,n);Console.WriteLine("You will get {0:#.00}",amount);

    }}After obtaining the reference to Policy Type (t) we instantiate the type dynamically usingActivator.CreateInstance(t). For this to work the Type t must not be an abstract class andmust support a public default constructor. Activator.CreateInstance method declares toreturn the generic System.Object which we cast to Policy in order to invoke the Ratemethod. This cast will work only if the type t implements Policy otherwise it will causean InvalidCastException. Compile investment.cs: csc /r:invpol.dll investment.csExecute: investment 65000 6 SilverPolicy,invpolThe amount will be displayed. If GoldPolicy is used an exception will occur sinceGoldPolicy does not implement policy. GoldPolicy does provide Rate method but toinvoke it we must cast the object returned by Activator.CreateInstance to Policy whichfails. Our next program (investmentdmi.cs) calls the Rate method using the so calledDynamic Method Invocation. As this approach calls the method by its name the casting isnot required, this version of investment program will work with all the policy classes ininvpol.dll.

  • 7/28/2019 Beginning Csne t .net

    35/123

    using System;using System.Reflection;class InvestmentDMI{

    public static void Main(string[] args){double p = Double.Parse(args[0]);int n = Int32.Parse(args[1]);Type t = Type.GetType(args[2]);object pol = Activator.CreateInstance(t); // no castingType[] ptypes = {typeof(double), typeof(int)};//look for a method called Rate (double, int)MethodInfo m = t.GetMethod("Rate",ptypes);// store the values of the argument in an array of object// which can hold values of any type (boxing)object[] pvalues = {p,n};

    // Invoke the Rate method on pol instance with arguments// stored in pvalues.//Cast the return value of type object to float (unboxing)float r = (float)m.Invoke(pol,pvalues);double amount = p*Math.Pow(1+r/100,n);Console.WriteLine("You will get {0:#.00}",amount);

    }}Compile investmentdmi.cs using command csc investmentdmi.csIt will work with all four policies in invpol.dllC# provides a mechanism for defining declarative tags, called attributes, which you canplace on certain entities in your source code to specify additional information. Theinformation that attributes contain can be retrieved at run time through reflection You canuse predefined attributes or you can define your own custom attributes. Attributes can beplaced on most any declaration (though a specific attribute might restrict the types ofdeclarations on which it is valid). Syntactically, an attribute is specified by placing thename of the attribute, enclosed in square brackets, in front of the declaration of the entity(class, member method etc) to which it applies, For example:

    [Marker(arglist)] entity declarationWhere Marker is an attribute which can be applied to the entity that follows.You can create your own custom attributes by defining an attribute class, a class thatderives directly or indirectly from System.Attribute. The Attribute class must be alwaysbe named as SomethingAttribute so that [Something()] can be used to apply thisattribute and this class must be marked with the predefined attribute AttributeUsagewhich specifies the type of the declaration to which this attribute can be applied.

  • 7/28/2019 Beginning Csne t .net

    36/123

    The listing below(execattr.cs) defines two attributes Executable and Authorize.[AttributeUsage(AttributeTargets.Class)] // applies only to a classpublic class ExecutableAttribute : Attribute{}

    [AttributeUsage(AttributeTargets.Method)] // applies to a method of a classpublic class AuthorizeAttribute : Attribute{private string _pwd;public AuthorizeAttribute(string pwd){

    _pwd = pwd;}public string Password{

    get{ return _pwd; }}

    }

    Next sample (executer.cs) is a program which takes a name of class at runtime andinvokes its Execute() method it does so only if the specified class has been marked withExecutable attribute. It also checks if the Execute method of the class has been markedwith Authorize attribute and if so it retrieves the password passed through the attributeand forces the user to authorize before invoking Execute() method of the class.class Executer{

    public static void Main(string[] args){Type t = Type.GetType(args[0]); //args[0] = ClassName,AssemblyName// check if the class supports Executable attributeif(!t.IsDefined(typeof(ExecutableAttribute))){

    Console.WriteLine("{0} is not executable", args[0]);return;

    }// lookup for a Execute method which takes no argumentsMethodInfo m = t.GetMethod("Execute");// obtain AuthorizeAttribute if supported by this methodAuthorizeAttribute auth =

    (AuthorizeAttribute)Attribute.GetCustomAttribute(m,typeof(AuthorizeAttribute));

    if(auth != null){Console.Write(Enter Password: );if(Console.ReadLine() != auth.Password ){

    Console.WriteLine("Password is incorrect");return;

    }}m.Invoke(null, null); //Execute is a static method and takes no arg

    }}

  • 7/28/2019 Beginning Csne t .net

    37/123

    Compile above program using command: csc executer.cs, execattr.csApps.cs provides few classes for testing executer program.

    using System;[Executable]public class AClock{

    public static void Execute(){Console.WriteLine("Its {0}", DateTime.Now);

    }}[Executable]public class AGame{

    [Authorize("tiger")]public static void Execute(){Random r = new Random();int p = r.Next(1,10);Console.Write("Guess a number between 1 and 10: ");int q = Int32.Parse(Console.ReadLine());if(p == q) Console.WriteLine("You won!!!");else Console.WriteLine("You lost, correct number was {0}",p);

    }}public class AMessage{

    public static void Execute(){Console.WriteLine("Hello World!");

    }}Classes AClock and AGame are both marked with Executable attribute and so executerwill execute them. Since Execute method of AGame is marked with Authorize attribute,executer will prompt the user for password if his password matches with tigerAGame.Execute will be invoked. AMessage class will not be executed as it is not markedwith the Executable attribute. Compile apps.cs to create a dll using command

    csc /t:library apps.cs execattr.cs

    (executer.exe must be referenced because apps.cs uses attributes defined in thatassembly). Test executer:

    executer AClock,apps will show the current timeexecuter AGame,apps will prompt for passwordexecuter AMessage,apps will not execute

  • 7/28/2019 Beginning Csne t .net

    38/123

    Chapter 5: Multithreading

    In this chapter we discuss concurrent programming ie executing multiple blocksof code simultaneously. Lets first see how to launch a new process from a .NETexecutable.The program below (processtest.cs) launches notepad.exe and asynchronously

    counts up from 1 to 10000 and then destroys the notepad process.using System;using System.Diagnostics; // for Process classclass ProcessTest{

    public static void Main(){Process p = Process.Start("notepad.exe");for(int i = 1;i < 10001;i++) Console.WriteLine(i);p.Kill();

    }

    }Compile: csc processtest.csWhen you execute processtest you will notice how two processes (processtest.exe andnotepad.exe) can execute concurrently.Threads are parts of same process which execute concurrently. In .NET Base ClassLibrary(BCL) the System.Threading namespace provides various classes for executingand controlling threads. The program below (threadtest1.cs) executes two loopssimultaneously using threads.

    using System;using System.Threading; // for Thread classclass ThreadTest1{

    public static void SayHello(){for(int i = 1;; i++){

    Console.WriteLine(Hello {0},i);}

    }public static void Main(){

    Thread t = new Thread(new ThreadStart(SayHello));t.Start();for(int i = 1;i < 10001; i++){

    Console.WriteLine(Bye {0},i);}t.Abort();

    }}

  • 7/28/2019 Beginning Csne t .net

    39/123

    We create a Thread instance by passing it an object of ThreadStart delegate whichcontains a reference to our SayHello method. When the thread is started (using its Startmethod) SayHello will be executed in an asynchronous manner. Compile and run theabove program, you will notice series of Hello and Bye messages appearing on the

    screen. When the program is executed the CLR launches the main thread (the one whichexecutes Main method) within the body of main we launch thread t (which executesSayHello method). While thread t goes in an infinite loop printing Hello on the consolethe main thread concurrently prints Bye on the console 10000 times, after which the mainthread kills thread t invoking its Abort() method before it itself terminates. If thread twould not be aborted in this fashion it would continue to execute even after the mainthread terminates. We could also mark thread t as Back Ground thread, in which case twould automatically abort soon after the last foreground thread (main thread in this case)would terminate. The program below (threadtest2.cs) shows how:using System;

    using System.Threading;class ThreadTest2{public static void SayHello(){

    for(int i = 1;; i++){Console.WriteLine("Hello {0}",i);

    }}public static void Main(){

    Thread t = new Thread(new ThreadStart(SayHello));t.IsBackground = true;

    t.Start();for(int i = 1;i < 10001; i++){

    Console.WriteLine("Bye {0}",i);}

    }}Just running threads simultaneously is not the whole thing, we sometimes need to controlthem. In program below (sleepingthread.cs) the main thread prints Hello 15 times whileat the same time another thread t prints Welcome 5 times followed by a Goodbye.The programs sees to it that the Goodbye message printed by thread t is always the lastmessage of the program. To achieve this control thread t puts itself to sleep for 5 secondafter printing its Welcome messages, this time is big enough for the main thread to printits Hello messages. After doing so the main threads interrupts the sleeping thread t, suchan interruption causes the Sleep method to throw ThreadInterruptedException. Thread thandles this exception and finally prints Goodbye message.using System;using System.Threading;

  • 7/28/2019 Beginning Csne t .net

    40/123

    class SleepingThread{

    public static void Run(){for(int i=1;i

  • 7/28/2019 Beginning Csne t .net

    41/123

    as both the threads are simultaneously checking whether there is enough balance in theaccount before deducting, there is quite a possiblity of over withdrawlusing System;using System.Threading;

    class Account {private double balance=5000;public void Withdraw(double amount) {

    Console.WriteLine("WITHDRAWING {0}",amount);if(amount>balance) throw new Exception("INSUFFICIENT FUNDS");Thread.Sleep(10); //do other stuffbalance-=amount;Console.WriteLine("BALANCE {0}",balance);

    }}

    class SyncThread {static Account acc = new Account();public static void Run() {

    acc.Withdraw(3000);}public static void Main() {

    new Thread(new ThreadStart(Run)).Start();acc.Withdraw(3000);

    }}We say Withdraw method is not thread safe (as it may fail to behave as required whenmultiple threads execute it simultaneously). Some time it is necessary to guarantee that acertain critical section of code is executed only by one thread at a time. C# offers lockstatement to mark a statement block as a critical section. Consider following code block(obj is some object):

    lock(obj){// critical section

    }Any thread which needs to execute the code enclosed in lock(obj){} block mustacquire the (one and only one)Monitorof obj. If one thread acquires monitor of an objectthen any other thread which attempts to do the same will be blocked until the first threadreleases it( i.e moves out of the locked block). The same effect can also be obtained usingfollowing method

    Monitor.Enter(obj);// critical sectionMonitor.Exit(obj);

    A thread safe implementation of above Account.Withdraw method (modifysyncthreads.cs) is given below

  • 7/28/2019 Beginning Csne t .net

    42/123

    public void Withdraw(double amount) {

    Console.WriteLine("WITHDRAWING {0}",amount);lock(this) {

    if(amount>balance)

    throw new Exception("INSUFFICIENT FUNDS");Thread.Sleep(10); //do other stuffbalance-=amount;

    }Console.WriteLine("BALANCE {0}",balance);

    }Now any thread interested in executing Withdraw method on an instance of Accountmust first acquire the monitor of that instance. Thus only one thread will be allowed toexecute Withdraw on a given instance of Account at a time (obviously one threadsexecution of Withdraw method on one instance will not block another threads execution

    of Withdraw method on another instance because each instance will have its ownmonitor).A thread which acquires the monitor of an object obj may release its monitor by invokingMonitor.Wait(obj), but doing so will block the thread (as it is still in the locked block)until any other thread which acquires the monitor of obj passes a notification by invokingMonitor.Pulse(obj) before releasing it. This feature of thread and monitor can be used toobtain a complete coordination between two threads. The example below(waitingthread.cs) shows how two threads can be made to coordinate using the Monitor.using System;using System.Threading;class WaitingThread {

    static object obj = new object();public static void Run() {

    for(int i = 0 ; i

  • 7/28/2019 Beginning Csne t .net

    43/123

    Normally when a caller invokes a method, the call issynchronous that is the caller has towait for the method to return before the remaing code can be executed. .NET alsosupports theAsynchronous programming model. Using this model the caller can issue arequest for invocation of a method and concurrently execute the remaing code. For every

    delegate declared in an assembly the compiler emits a class (subclass ofSystem.MulticastDelegate) with Invoke, BeginInvoke and EndInvoke methods. Forexample condider a delegate declared as:

    delegate int MyWorker(char ch, int max);The compiler will emit MyWorker class:

    class MyWorker : System.MulticastDelegate{public int Invoke(char ch, int max);public System.IAsyncResult BeginInvoke(char ch, int max,

    System.AsyncCallback cb, object asyncState);public int EndInvoke(System.IAsyncResult result);}

    The BeginInvoke and EndInvoke methods can be used for asynchronous invocation of amethod pointed by MyWorker delegate. In the example below (asynctest1.cs) DoWorkmethod (which displays character ch max number of times) is invoked asynchronouslywith character +, in the next statement this method is directly invoked with character*. You will notice both + and * are displayed (1000 times each) on the consolesimultaneously. As an asynchronous call executes within its own background thread, wehave used Console.Read() to pause the main thread.using System;delegate int MyWorker(char ch, int max);class AsyncTest1{

    static MyWorker worker;

    static int DoWork(char ch, int max){int t = Environment.TickCount; // returns number of milliseconds elapsed

    since the system startedfor(int i=1;i

  • 7/28/2019 Beginning Csne t .net

    44/123

    DoWork('*',1000); // synchronous callConsole.Read(); // pause until user enters a key

    }}

    But how do we retrieve the value returned by DoWork if it is invoked asynchronously?The return value can be obtained by invoking EndInvoke method of delegate passing itthe IAsyncResult instance which is returned by BeginInvoke method. The EndInvokemethod blocks the current thread until asynchronous call is completed. Our next example(asynctest2.cs) demonstrates this approach.using System;delegate int MyWorker(char ch, int max);class AsyncTest2{

    static MyWorker worker;static int DoWork(char ch, int max){

    int t = Environment.TickCount;for(int i=1;i

  • 7/28/2019 Beginning Csne t .net

    45/123

  • 7/28/2019 Beginning Csne t .net

    46/123

    Chapter 6: StreamsThe Stream class and its subclasses provide a generic view of data sources andrepositories, isolating the programmer from the specific details of the operating system

    and underlying devices. Streams involve these three fundamental operations:

    1. Streams can be read from. Reading is the transfer of data from a stream into a datastructure, such as an array of bytes.

    2. Streams can be written to. Writing is the transfer of data from a data structure into astream.

    3. Streams can support seeking. Seeking is the querying and modifying of the currentposition within a stream.

    All classes that represent streams inherit from the System.IO.Stream class. Anapplication can query a stream for its capabilities by using the CanRead, CanWrite, and

    CanSeekproperties. TheReadand Write methods read and write data in a variety offormats. For streams that support seeking, the SeekandPosition can be used to query andmodify the current position a stream. Some stream implementations perform localbuffering of the underlying data to improve performance. For such streams, theFlushmethod can be used to clear any internal buffers and ensure that all data has been writtento the underlying data source or repository. Calling Close on a stream flushes anybuffered data, essentially callingFlush for you. Close also releases operating systemresources such as file handles, network connections, or memory used for any internalbuffering.The System.IO.FileStream class is for reading from and writing to files. This class can

    be used to read and write bytes to a file. The System.IO.File class, used in conjunctionwithFileStream, is a utility class with static methods primarily for the creation ofFileStream objects based on file paths. The program below (readfile.cs) displays contentof a file whose name is passed through the command line.using System;using System.IO;using System.Text; // For Encoding

    class ReadFile{public static void Main(string[] args){

    Stream s = new FileStream(args[0], FileMode.Open);int size = (int) s.Length;byte[] buffer = new byte[size];s.Read(buffer,0,buffer.Length);s.Close();string text = Encoding.ASCII.GetString(buffer);Console.WriteLine(text);

    }

  • 7/28/2019 Beginning Csne t .net

    47/123

  • 7/28/2019 Beginning Csne t .net

    48/123

    string record = today+"|"+String.Join(|, args);StreamWriter sw = new StreamWriter("orders.txt",true);sw.WriteLine(record);sw.Close();

    }

    }We use the staticNow property ofSystem.DateTime structure to obtain the currrent datetime of the system. Then we convert this DateTime instance to a string containing currentdate in dd-MMM-yyyy format (Ex: 13-Jun-2001). We build a pipe delimited record byappending this date to the remaining fields in args (note the use of String.Join). Next wecreate a StreamWriter to orders.txt for appending (indicated by second boolean argumentof StreamWriter constructor) and we save the record as a line of text. We can also obtaina StreamWriter to a file using: StreamWriter sw = File.AppendText(file_name);Out next program (vieworders.cs) parses orders.txt file and displays all the orders which

    were placed before the date provided in the first command line argument.using System;using System.IO;class ViewOrders{

    public static void Main(string[] args){DateTime adate = DateTime.ParseExact(args[0],"dd-MMM-yyyy", null);StreamReader sr = new StreamReader("orders.txt");while(true){

    string record = sr.ReadLine();if(record == null) break;string[] fields = record.Split(new char[]{'|'});DateTime odate = DateTime.ParseExact(fields[0],

    "dd-MMM-yyyy",null);if(odate < adate){

    Console.WriteLine(record.Replace(|, ));}

    }sr.Close();

    }}First the string in args[0] is converted into a DateTime instance. Then we create aStreamReader to orders.txt. TheReadLine() method of StreamReader returns the nextline in the stream ornullif it encounters an end of file. We read lines from orders.txt oneat a time, split each line on | character, obtain the date from the first token and wedisplay the record with each field separated by a space ( ) only if the date in record isbefore the date provided by the user. We can also obtain a StreamReader to a file using:StreamWriter sw = File.OpenText(file_name);

  • 7/28/2019 Beginning Csne t .net

    49/123

    System.IO.BinaryWriter and System.IO.BinaryReader can be used for writing andreading primitive data types to a stream. The example below (binaryio.cs) writes somedata to a file called info.dat and then rereads it and prints it.using System;

    using System.IO;class BinaryIO{

    private static void WriteData(int i, double d, string t){Stream s = File.OpenWrite("info.dat");BinaryWriter bw = new BinaryWriter(s);bw.Write(i);bw.Write(d);// write length-prefixed stringbw.Write(t);bw.Close();

    }private static void ReadData(){

    Stream s = File.OpenRead("info.dat");BinaryReader br = new BinaryReader(s);int i = br.ReadInt32();double d = br.ReadDouble();string t = br.ReadString();br.Close();Console.WriteLine("{0}, {1}, {2}", i, d, t);

    }

    public static void Main(){WriteData(12345, 3.1415467, "Hello World");ReadData();

    }}Sometimes it is desirable to store a complete object in a stream. This is achieved by aprocess called Object Serialization. By Serialization we mean converting an object, or aconnected graph of objects (a set of objects with some set of references to each other),stored within computer memory into a linear sequence of bytes. That string of bytescontains all of the important information that was held in the objects we started with.Wecan go on to use that sequence of bytes in several ways. For example:

    Send it to another process (on the same machine) and use it to construct

    arguments to a method that is run in that other process. In this case, the sequenceof bytes is copied from one location in the machine's physical memory to another it never leaves the machine

  • 7/28/2019 Beginning Csne t .net

    50/123

    Send it to the clipboard, to be browsed or included in another application. As

    above, the sequence of bytes is transferred to another location in memory on thecurrent machine.

    Send it 'down the wire' to another machine and use it to create a clone on that

    machine of the original object graph. As above, we might then use this object

    graph as an argument to a method call. In this case, however, the sequence ofbytes is actually transferred outside of the originating machine.

    Send it to a file on-disk, so that it can be reused later.

    Class authors need to be aware of serialization. The serialization services assume that atype is NOT Serializable unless type is specifically marked as Serializable (usingSystem.IO.Serializable attribute). In the most simple case marking a class asSerializable is the all the class author will have to do. Given below (employee.cs) is theEmployee class whose instance we will serialize.using System;

    using System.Runtime.Serialization;[Serializable]public class Employee {

    public string Name;public string Job;public double Salary;

    public Employee(string name, string job, double salary){

    Name=name;

    Job=job;Salary=salary;

    }

    public Employee(){}

    // We override ToString() method of System.Object. This method is invoked// whenever an Employee object is to be converted to a string.public override string ToString(){

    return String.Format("{0} is a {1} and earns {2}",Name,Job,Salary);

    }}

    The program below (binsertest1.cs) creates an instance of Employee class and stores it infile emp.bin. It also retreives and displays the object.using System;using System.IO;

  • 7/28/2019 Beginning Csne t .net

    51/123

    using System.Runtime.Serialization.Formatters.Binary;class BinarySerializationTest1{

    static BinaryFormatter bf = new BinaryFormatter();

    private static void WriteEmployee(Employee emp){Stream s = File.OpenWrite("emp.bin");bf.Serialize(s,emp);s.Close();

    }

    private static void ReadEmployee(){Stream s = File.OpenRead("emp.bin");Employee emp = (Employee)bf.Deserialize(s);s.Close();Console.WriteLine(emp); //displays emp.ToString()

    }

    public static void Main(string[] args){Employee emp = new Employee("Jack", "Clerk", 44000);WriteEmployee(emp);ReadEmployee();

    }}Compile: csc binsertest1.cs employee.cs

    Sometimes we need to control the serialization process. For example consider a subclassof Employee class called Manager. When we store a Manager instance we dont want itsJob field to be stored (because Job of Manager is Manager). A class which needs toparticipate in its own serialization process must satisfy following two requirements.1. The class must implement System.IO.ISerializable interface and provide

    implementation for itsvoid GetObjectData(SerializationInfo info, StreamingContext context)

    method. During serialization, the Formatter will invoke this method and store onlythat information in the stream which has been added to the info argument.

    2. The class must provide a constructor which takes the same two arguments as above GetObjectData method. During deserialization the Formatter invokes this constructor

    passing it the info object containing the information from the stream.Below is the Manager class (add it to employee.cs) which exhibits custom serialization.

    [Serializable]public class Manager : Employee, ISerializable {

    public Employee Secretary;

  • 7/28/2019 Beginning Csne t .net

    52/123

    public Manager(string name, double salary, Employee secretary){Name = name;Salary = salary;Secretary = secretary;Job = "Manager";

    }public Manager(){}

    // This constructor will be called upon during deserialization// Retreive the field values from the info object passed as first argumentpublic Manager(SerializationInfo info, StreamingContext context){

    Name=info.GetString("name");Salary=info.GetDouble("salary");Secretary=(Employee)info.GetValue("secretary", typeof(Employee));

    Job = "Manager";}

    // This method will be called upon during serialization// Add the field values to be stored to the info object object

    public void GetObjectData(SerializationInfo info, StreamingContext context){info.AddValue("name",Name);info.AddValue("salary",Salary);info.AddValue("secretary",Secretary);

    }

    public override string ToString(){return base.ToString()+"\nHis secretary "+Secretary.ToString();

    }}The program below (binsertest2.cs) creates an instance of Manager class and stores it infile boss.bin. It also retreives and displays the object.using System;using System.IO;using System.Runtime.Serialization.Formatters.Binary;class BinarySerializationTest{

    static BinaryFormatter bf = new BinaryFormatter();

    private static void WriteManager(Manager mgr){Stream s = File.OpenWrite("boss.bin");bf.Serialize(s,mgr);s.Close();

  • 7/28/2019 Beginning Csne t .net

    53/123

    }

    private static void ReadManager(){Stream s = File.OpenRead("boss.bin");Manager mgr = (Manager)bf.Deserialize(s);

    s.Close();Console.WriteLine(mgr);}

    public static void Main(string[] args){Employee sec = new Employee("Jane", "Steno", 24000);Manager mgr = new Manager("John", 72000, sec);WriteManager(mgr);ReadManager();

    }}

    Above two examples useBinaryFormatterto store the image of object into the stream ina binary format. Obviously this information is not human readable. It is also possible tostore object in an xml form using System.Xml.Serialization.XmlSerializer .The nextprogram (xmlsertest.cs) stores a Manager instance in file boss.xml and then reads it backand displays it.using System;using System.IO;using System.Xml.Serialization;class XmlSerializationTest{

    static XmlSerializer xs = new XmlSerializer(typeof(Manager));

    private static void WriteManager(Manager mgr){Stream s = File.OpenWrite("boss.xml");xs.Serialize(s,mgr);s.Close();

    }

    private static void ReadManager(){Stream s = File.OpenRead("boss.xml");Manager mgr = (Manager)xs.Deserialize(s);s.Close();Console.WriteLine(mgr);

    }

    public static void Main(string[] args){Employee sec = new Employee("Jane", "Steno", 24000);Manager mgr = new Manager("John", 72000, sec);

  • 7/28/2019 Beginning Csne t .net

    54/123

    WriteManager(mgr);ReadManager();

    }}

    Compile: csc xmlsertest.cs employee.csExecution of this program will create boss.xml in the current directory with followingcontent

    JaneSteno24000

    JohnManager72000

    Note: XmlSerializer does not support custom serialization with ISerializable (The Jobfield of Manager instance is stored in boss.xml). Also for XmlSerializer to work the classwhose object is being serialized must support a public default constructor.The .NET framework provides XML parser for reading and modifying xml documents.Given below is emp.xml containing informations about employees.

    Johnmanager72000

    Janesteno23000

    Jimsalesman36000

  • 7/28/2019 Beginning Csne t .net

    55/123

    Jillclerk45000

    The program below (listemp.cs) displays id and salary of each employee in emp.xml.using System;using System.Xml;class ListEmployees{

    public static void Main(){XmlDocument doc = new XmlDocument();// load employee.xml in XmlDocument

    doc.Load("emp.xml");// obtain a list of all employee elementXmlNodeList list = doc.GetElementsByTagName("employee");foreach(XmlNode emp in list){

    // obtain value of id attribute of the employee tagstring id = emp.Attributes["id"].Value;// obtain value of salary subtag of the employee tagstring sal = emp["salary"].FirstChild.Value;Console.WriteLine("{0}\t{1}",id,sal);

    }}

    }Compile: csc listemp.cs

    The next program (addemp.cs) takes informations from command line and makes a newentry in employee.xmlusing System;using System.Xml;class AddEmployee{

    public static void Main(string[] args){XmlDocument doc = new XmlDocument();doc.Load("emp.xml");// create a new employee element and value of its id attributeXmlElement emp = doc.CreateElement("employee");emp.SetAttribute("id",args[0]);// create a name tag and set its valueXmlNode name = doc.CreateNode("element","name","");

  • 7/28/2019 Beginning Csne t .net

    56/123

    name.InnerText = args[1];// make name tag a subtag of newly created employee tagemp.AppendChild(name);XmlNode job = doc.CreateNode("element","job","");job.InnerText = args[2];

    emp.AppendChild(job);XmlNode sal = doc.CreateNode("element","salary","");sal.InnerText = args[3];emp.AppendChild(sal);// add the newly created employee tag to the root (employees) tagdoc.DocumentElement.AppendChild(emp);// save the modified documentdoc.Save("employee.xml");

    }}

    Compile: csc addemp.csExecute: addemp 105 Jeff president 105000Open employee.cs you will see the following fragment has been appended.

    Jefflpresident105000

  • 7/28/2019 Beginning Csne t .net

    57/123

    Chapter 7: Sockets

    Inter-Process Communication i.e the capability of two or more physicallyconnected machines to exchange d