C# concepts


Published on

Published in: Technology
  • Be the first to comment

  • Be the first to like this

No Downloads
Total views
On SlideShare
From Embeds
Number of Embeds
Embeds 0
No embeds

No notes for slide

C# concepts

  1. 1. In this article we will discuss key concepts of object orientation with theirpractical implementation in C#. We will discuss here basics of OOPSincluding Interfaces, Access Modifiers, inheritance, polymorphism etc. This ismy second article on csharp-corner.com.My first article was "Memory Management in .NET",you can find this article at http://www.c-sharpcorner.com/UploadFile/tkagarwal/MemoryManagementInNet11232005064832AM/MemoryManagementInNet.aspxKey Concepts of Object OrientationAbstractionEncapsulationPolymorphismInheritance.Abstraction is the ability to generalize an object as a data type that has aspecific set of characteristics and is able to perform a set of actions.Object-oriented languages provide abstraction via classes. Classes define theproperties and methods of an object type.Examples:You can create an abstraction of a dog with characteristics, such ascolor, height, and weight, and actions such as run and bite. Thecharacteristics are called properties, and the actions are calledmethods.A Recordset object is an abstract representation of a set of data.Classes are blueprints for Object.Objects are instance of classes.C# Example of Class:public class Draw{// Class code.}Object ReferencesWhen we work with an object we are using a reference to that object. On the
  2. 2. other hand, when we are working with simple data types such as Integer, weare working with the actual value rather than a reference.When we create a new object using the New keyword, we store a referenceto that object in a variable. For instance:Draw MyDraw = new Draw;This code creates a new instance of Draw. We gain access to this new objectvia the MyDraw variable. This variable holds a reference to the object.Now we have a second variable, which also has a reference to that sameobject. We can use either variable interchangeably, since they bothreference the exact same object. The thing we need to remember is that thevariable we have is not the object itself but, rather, is just a reference orpointer to the object itself.Early binding means that our code directly interacts with the object, bydirectly calling its methods. Since the compiler knows the objects data typeahead of time, it can directly compile code to invoke the methods on theobject. Early binding also allows the IDE to use IntelliSense to aid ourdevelopment efforts; it allows the compiler to ensure that we are referencingmethods that do exist and that we are providing the proper parametervalues.Late binding means that our code interacts with an object dynamically atrun-time. This provides a great deal of flexibility since our code literallydoesnt care what type of object it is interacting with as long as the objectsupports the methods we want to call. Because the type of the object isntknown by the IDE or compiler, neither IntelliSense nor compile-time syntaxchecking is possible but we get unprecedented flexibility in exchange.If we enable strict type checking by using Option Strict On at the top of ourcode modules, then the IDE and compiler will enforce early binding behavior.By default, Option Strict is turned off and so we have easy access to the useof late binding within our code.Access ModifiersAccess Modifiers are keywords used to specify the declared accessibility of amember of a type.Public is visible to everyone. A public member can be accessed using aninstance of a class, by a classs internal code, and by any descendants of a
  3. 3. class.Private is hidden and usable only by the class itself. No code using a classinstance can access a private member directly and neither can a descendantclass.Protected members are similar to private ones in that they are accessibleonly by the containing class. However, protected members also may be usedby a descendant class. So members that are likely to be needed by adescendant class should be marked protected.Internal/Friend is public to the entire application but private to anyoutside applications. Internal is useful when you want to allow a class to beused by other applications but reserve special functionality for theapplication that contains the class. Internal is used by C# and Friend by VB.NET.
  4. 4. Protected Internal may be accessed only by a descendant class thatscontained in the same application as its base class. You use protectedinternal in situations where you want to deny access to parts of a classfunctionality to any descendant classes found in other applications.Composition of an OBJECTWe use an interface to get access to an objects data and behavior. Theobjects data and behaviors are contained within the object, so a clientapplication can treat the object like a black box accessible only through itsinterface. This is a key object-oriented concept called Encapsulation. Theidea is that any programs that make use of this object wont have directaccess to the behaviors or data-but rather those programs must make use ofour objects interface.There are three main parts of Object:
  5. 5. 1. Interface2. Implementation or Behavior3. Member or Instance variablesInterfaceThe interface is defined as a set of methods (Sub and Function routines),properties (Property routines), events, and fields (variables or attributes)that are declared Public in scope.Implementation or BehaviorThe code inside of a method is called the implementation. Sometimes it isalso called behavior since it is this code that actually makes the object douseful work.Client applications can use our object even if we change the implementation-as long as we dont change the interface. As long as our method name andits parameter list and return data type remain unchanged, we can changethe implementation all we want.So Method Signature depends on:Method nameData types of parametersEither Parameter is passed ByVal or ByRef.Return type of method.It is important to keep in mind that encapsulation is a syntactic tool-it allowsour code to continue to run without change. However, it is not semantic-meaning that, just because our code continues to run, doesnt mean itcontinues to do what we actually wanted it to do.Member or Instance VariablesThe third key part of an object is its data, or state. Every instance of a classis absolutely identical in terms of its interface and its implementation-theonly thing that can vary at all is the data contained within that particularobject.Member variables are those declared so that they are available to all codewithin our class. Typically member variables are Private in scope-availableonly to the code in our class itself. They are also sometimes referred to asinstance variables or as attributes. The .NET Framework also refers to themas fields.
  6. 6. We shouldnt confuse instance variables with properties. A Property is a typeof method that is geared around retrieving and setting values, while aninstance variable is a variable within the class that may hold the valueexposed by a Property.Interface looks like a class, but has no implementation.The only thing it contains is definitions of events, indexers, methods and/orproperties. The reason interfaces only provide definitions is because they areinherited by classes and structs, which must provide an implementation foreach interface member defined. So, what are interfaces good for if theydont implement functionality? Theyre great for putting together plug-n-playlike architectures where components can be interchanged at will. Since allinterchangeable components implement the same interface, they can beused without any extra programming. The interface forces each componentto expose specific public members that will be used in a certain way.Because interfaces must be defined by inheriting classes and structs, theydefine a contract. For instance, if class foo inherits from the IDisposableinterface, it is making a statement that it guarantees it has the Dispose()method, which is the only member of the IDisposable interface. Any codethat wishes to use class foo may check to see if class foo inheritsIDisposable. When the answer is true, then the code knows that it can callfoo.Dispose().Defining an Interface: MyInterface.cinterface IMyInterface{void MethodToImplement();}Above listing shows defines an interface named IMyInterface. A commonnaming convention is to prefix all interface names with a capital "I", but thisis not mandatory. This interface has a single method namedMethodToImplement(). This could have been any type of method declarationwith different parameters and return types. Notice that this method does nothave an implementation (instructions between curly braces- {}), but insteadends with a semi-colon, ";". This is because the interface only specifies thesignature of methods that an inheriting class or struct must implement.All the methods of Interface are public by default and no access modifiers(like private, public) are allowed with any method of Interface.
  7. 7. Using an Interface: InterfaceImplementer.csclass InterfaceImplementer : IMyInterface{public void MethodToImplement(){Console.WriteLine("MethodToImplement() called.");}}The InterfaceImplementer class in above listing implements the IMyInterfaceinterface. Indicating that a class inherits an interface is the same asinheriting a class. In this case, the following syntax is used:class InterfaceImplementer : IMyInterfaceNote that this class inherits the IMyInterface interface; it must implement itsall members. While implementing interface methods all those needs to bedeclared public only. It does this by implementing the MethodToImplement()method. Notice that this method implementation has the exact samesignature, parameters and method name, as defined in the IMyInterfaceinterface. Any difference will cause a compiler error. Interfaces may alsoinherit other interfaces. Following listing shows how inherited interfaces areimplemented.Interface Inheritance: InterfaceInheritance.csusing System;interface IParentInterface{void ParentInterfaceMethod();}interface IMyInterface : IParentInterface{void MethodToImplement();}class InterfaceImplementer : IMyInterface{public void MethodToImplement(){Console.WriteLine("MethodToImplement() called.");}public void ParentInterfaceMethod(){Console.WriteLine("ParentInterfaceMethod() called.");}}The code in above listing contains two interfaces: IMyInterface and theinterface it inherits, IParentInterface. When one interface inherits another,
  8. 8. any implementing class or struct must implement every interface member inthe entire inheritance chain. Since the InterfaceImplementer class in abovelisting inherits from IMyInterface, it also inherits IParentInterface. Therefore,the InterfaceImplementer class must implement the MethodToImplement()method specified in the IMyInterface interface and theParentInterfaceMethod() method specified in the IParentInterface interface.In summary, you can implement an interface and use it in a class. Interfacesmay also be inherited by other interface. Any class or struct that inherits aninterface must also implement all members in the entire interfaceinheritance chain.Inheritance is the idea that one class, called a subclass, can be based onanother class, called a base class. Inheritance provides a mechanism forcreating hierarchies of objects.Inheritance is the ability to apply another classs interface and code to yourown class.Normal base classes may be instantiated themselves, or inherited. Derivedclasses can inherit base class members marked with protected or greateraccess. The derived class is specialized to provide more functionality, inaddition to what its base class provides. Inheriting base class members inderived class is not mandatory.Access Keywordsbase -> Access the members of the base class.this -> Refer to the current object for which a method is called.The base keyword is used to access members of the base class from within aderived class:Call a method on the base class that has been overridden by anothermethod. Specify which base-class constructor should be called when creatinginstances of the derived class. A base class access is permitted only in aconstructor, an instance method, or an instance property accessor.In following example, both the base class, Person, and the derived class,Employee, have a method named Getinfo. By using the base keyword, it ispossible to call the Getinfo method on the base class, from within thederived class.// Accessing base class membersusing System;
  9. 9. public class Person{protected string ssn = "444-55-6666";protected string name = "John L. Malgraine";public virtual void GetInfo(){Console.WriteLine("Name: {0}", name);Console.WriteLine("SSN: {0}", ssn);}}class Employee: Person{public string id = "ABC567EFG";public override void GetInfo(){// Calling the base class GetInfo method:base.GetInfo();Console.WriteLine("Employee ID: {0}", id);}}class TestClass{public static void Main(){Employee E = new Employee();E.GetInfo();}}OutputName: John L. MalgraineSSN: 444-55-6666Employee ID: ABC567EFGBase class constructors can be called from derived classes. To call a baseclass constructor, use the base() constructor reference. This is desirablewhen its necessary to initialize a base class appropriately.Heres an example that shows the derived class constructor with an addressparameter:abstract public class Contact{private string address;public Contact(string b_address){this.address = b_address;}}public class Customer : Contact
  10. 10. {public Customer(string c_address) : base(C_address){}}In this code, the Customer class does not have an address, so it passes theparameter to its base class constructor by adding a colon and the basekeyword with the parameter to its declaration. This calls the Contactconstructor with the address parameter, where the address field in Contactis initialized.One more example which shows how base-class constructor is called whencreating instances of a derived class:using System;public class MyBase{int num;public MyBase(){Console.WriteLine("In MyBase()");}public MyBase(int i){num = i;Console.WriteLine("in MyBase(int i)");}public int GetNum(){return num;}}public class MyDerived : MyBase{static int i = 32;// This constructor will call MyBase.MyBase()public MyDerived(int ii) : base(){}// This constructor will call MyBase.MyBase(int i)public MyDerived() : base(i){}public static void Main(){MyDerived md = new MyDerived(); // calls public MyDerived() : base(i) and// passes i=32 in base classMyDerived md1 = new MyDerived(1); // call public MyDerived() : base(i)}}
  11. 11. Outputin MyBase(int i)in MyBase()The following example will not compile. It illustrates the effects of notincluding a default constructor in a class definition:abstract public class Contact{private string address;public Contact(string address){this.address = address;}}public class Customer : Contact{public Customer(string address){}}In this example, the Customer constructor does not call the base classconstructor. This is obviously a bug, since the address field will never beinitialized.When a class has no explicit constructor, the system assigns a defaultconstructor. The default constructor automatically calls a default orparameterless base constructor. Heres an example of automatic defaultconstructor generation that would occur for the preceding example:public Customer() : Contact(){}When a class does not declare any constructors, the code in this example isautomatically generated. The default base class constructor is calledimplicitly when no derived class constructors are defined. Once a derivedclass constructor is defined, whether or not it has parameters, a defaultconstructor will not be automatically defined, as the preceding code showed.Calling Base Class MembersDerived classes can access the members of their base class if thosemembers have protected or greater access. Simply use the member name in
  12. 12. the appropriate context, just as if that member were a part of the derivedclass itself. Heres an example:abstract public class Contact{private string address;private string city;private string state;private string zip;public string FullAddress(){string fullAddress = address + n + city + , + state + + zip;return fullAddress;}}public class Customer : Contact{public string GenerateReport(){string fullAddress = FullAddress();// do some other stuff...return fullAddress;}}In above example, the GenerateReport() method of the Customer class callsthe FullAddress() method in its base class, Contact. All classes have fullaccess to their own members without qualification. Qualification refers tousing a class name with the dot operator to access a class member-MyObject.SomeMethod(), for instance. This shows that a derived class canaccess its base class members in the same manner as its own.More Tips regarding Inheritance:A static member cannot be marked as override, virtual, or abstract. Sofollowing is an error:public static virtual void GetSSN()You cant call static methods of base class from derived class usingbase keyword.In above example if you declare a static method as follows:public class Person{protected string ssn = "444-55-6666";protected string name = "John L. Malgraine";public static void GetInfo(){// Implementation
  13. 13. }}now you cant call this method using base.GetInfo() from derived classinstead you have to call Person.GetInfo() from derived class.Inside Static members we can access only static fields, methods etc.Following example will give error, because we cant access name in GetInfo()because name is not static.public class Person{protected string ssn = "444-55-6666";protected string name = "John L. Malgraine";public static void GetInfo(){Console.WriteLine("Name: {0}", name);Console.WriteLine("SSN: {0}", ssn);}}Virtual or abstract members cannot be private.If you are not overriding a virtual method of base class in derivedclass, you cant use base class method by using base keyword inderived class. Also when you will create an instance of derived class, itwill call derived class method and you will only be able to access baseclass method when you will create instance of base class.You cant decrease access level of a method in derived class when youare overriding a base class method in derived class, vice versa ispossible.Means you can make protected method of base class to public inderived class.The "this" keyword refers to:the current instance for which a method is called. Static memberfunctions do not have a this pointer. The this keyword can be used toaccess members from within constructors, instance methods, andinstance accessors.The following are common uses of this:To qualify members hidden by similar names, for example:public Employee(string name, string alias){this.name = name;
  14. 14. this.alias = alias;}In above example, this.name refers to private variable name in the class. Ifwe write name = name, then this will refer to argument name of theconstructor Employee and not to private variable name in the class. In thiscase private variable name will never be initialized.To pass an object as a parameter to other methods, for example:CalcTax(this);To declare indexers, for example:public int this [int param]{get{return array[param];}set{array[param] = value;}}It is an error to refer to this in a static method, static property accessor, orvariable initializer of a field declaration.In this example, this is used to qualify the Employee class members, nameand alias, which are hidden by similar names. It is also used to pass anobject to the method CalcTax, which belongs to another class.// keywords_this.cs// this exampleusing System;public class Employee{public string name;public string alias;public decimal salary = 3000.00m;// Constructor:public Employee(string name, string alias){// Use this to qualify the fields, name and alias:this.name = name;this.alias = alias;}// Printing method:public void printEmployee(){
  15. 15. Console.WriteLine("Name: {0}nAlias: {1}", name, alias);// Passing the object to the CalcTax method by using this:Console.WriteLine("Taxes: {0:C}", Tax.CalcTax(this));}}public class Tax{public static decimal CalcTax(Employee E){return (0.08m*(E.salary));}}public class MainClass{public static void Main(){// Create objects:Employee E1 = new Employee ("John M. Trainer", "jtrainer");// Display results:E1.printEmployee();}}OutputName: John M. TrainerAlias: jtrainerTaxes: $240.00Abstract ClassesAbstract classes are a special type of base classes. In addition to normalclass members, they have abstract class members. These Abstract classmembers are methods and properties that are declared without animplementation. All classes derived directly from abstract classes mustimplement all of these abstract methods and properties.Abstract classes can never be instantiated. This would be illogical, becauseof the members without implementations.So what good is a class that cantbe instantiated? Lots! Abstract classes sit toward the top of a classhierarchy. They establish structure and meaning to code. They makeframeworks easier to build. This is possible because abstract classes haveinformation and behavior common to all derived classes in a framework.Take a look at the following example:abstract public class Contact // Abstract Class Contact.{protected string name;public Contact(){
  16. 16. // statements...}public abstract void generateReport();abstract public string Name{get;set;}}Contact, is an abstract class. Contact has two abstract members, and it hasan abstract method named generateReport(). This method is declared withthe abstract modifier in front of the method declaration. It has noimplementation (no braces) and is terminated with a semicolon. The Nameproperty is also declared abstract. The accessors of properties areterminated with semicolons.public class Customer : Contact // Customer Inherits Abstract Class Contact.{string gender;decimal income;int numberOfVisits;public Customer(){// statements}public override void generateReport(){// unique report}public override string Name{get{numberOfVisits++;return name;}set{name = value;numberOfVisits = 0;}}}public class SiteOwner : Contact{int siteHits;string mySite;public SiteOwner(){// statements
  17. 17. }public override void generateReport(){// unique report}public override string Name{get{siteHits++;return name;}set{name = value;siteHits = 0;}}}The abstract base class Contact has two derived classes, Customer andSiteOwner. Both of these derived classes implement the abstract membersof the Contact class. The generateReport() method in each derived class hasan override modifier in its declaration. Likewise, the Name declarationcontains an override modifier in both Customer and SiteOwner.C# requires explicit declaration of intent when overriding methods. Thisfeature promotes safe code by avoiding the accidental overriding of baseclass methods, which is what actually does happen in other languages.Leaving out the override modifier generates an error. Similarly, adding anew modifier also generates an error. Abstract methods must be overriddenand cannot be hidden, which the new modifier or the lack of a modifierwould be trying to do.The most famous of all abstract classes is the Object class. It may bereferred to as object or Object, but its still the same class. Object is thebase class for all other classes in C#. Its also the default base class when abase class is not specified. The following class declarations produce the sameexact results:abstract public class Contact : Object{// class members}abstract public class Contact{// class members}
  18. 18. Object is implicitly included as a base class if it is not already declared.Besides providing the abstract glue to hold together the C# class framework,object includes built-in functionality, some of which is useful for derivedclasses to implement.Difference between Interface and Abstract ClassInterfaces are closely related to abstract classes that have allmembers abstract.For an abstract class, at least one method of the class must be anabstract method that means it may have concrete methods.For an interface, all the methods must be abstractClass that implements an interface much provide concreteimplementation of all the methods definition in an interface or elsemust be declare an abstract classIn C#, multiple inheritance is possible only through implementation ofmultiple interfaces. Abstract class can only be derived once.An interface defines a contract and can only contains four entities vizmethods, properties, events and indexes. An interface thus cannotcontain constants, fields, operators, constructors, destructors, staticconstructors, or types.Also an interface cannot contain static members of any kind. Themodifiers abstract, public, protected, internal, private, virtual, overrideis disallowed, as they make no sense in this context.Class members that implement the interface members must bepublicly accessible.Overriding Summery:A derived class may override a virtual method of the base class with thekeyword override. The following restrictions must be followed.Keyword override is used in the definition of child class method that isgoing to override the base classs virtual method.The return type must be the same as the virtual method have in baseclass.The name of the method should also be same.The parameter-list must also be same in order, number and type ofparameters.The accessibility of the overriding method should not be morerestricted than that of the accessibility defined with virtual method ofthe base class. This accessibility either be the same or less restricted.
  19. 19. The virtual methods can be sealed in the child or derived classes toprevent further modifications in the implementation of the virtualmethod in the derived classes, by declaring them as sealed methods.Hiding Base Class MembersSometimes derived class members have the same name as a correspondingbase class member. In this case, the derived member is said to be "hiding"the base class member.When hiding occurs, the derived member is masking the functionality of thebase class member. Users of the derived class wont be able to see thehidden member; theyll see only the derived class member. The followingcode shows how hiding a base class member works.abstract public class Contact{private string address;private string city;private string state;private string zip;public string FullAddress(){string fullAddress =address + n +city + , + state + + zip;return fullAddress;}}public class SiteOwner : Contact{public string FullAddress(){string fullAddress;// create an address...return fullAddress;}}In this example, both SiteOwner and its base class, Contact, have a methodnamed FullAddress(). The FullAddress() method in the SiteOwner class hidesthe FullAddress() method in the Contact class. This means that when aninstance of a SiteOwner class is invoked with a call to the FullAddress()method, it is the SiteOwner class FullAddress() method that is called, not theFullAddress() method of the Contact class.Although a base class member may be hidden, the derived class can stillaccess it. It does this through the base identifier. Sometimes this isdesirable. It is often useful to take advantage of the base class functionality
  20. 20. and then add to it with the derived class code. The next example shows howto refer to a base class method from the derived class.abstract public class Contact{private string address;private string city;private string state;private string zip;public string FullAddress(){string fullAddress =address + n +city + , + state + + zip;return fullAddress;}}public class SiteOwner : Contact{public string FullAddress(){string fullAddress = base.FullAddress();// do some other stuff...return fullAddress;}}In this particular example, the FullAddress() method of the Contact class iscalled from within the FullAddress() method of the SiteOwner class. This isaccomplished with a base class reference. This provides another way toreuse code and add on to it with customized behavior.VersioningVersioning, in the context of inheritance, is a C# mechanism that allowsmodification of classes (creating new versions) without accidentally changingthe meaning of the code. Hiding a base class member with the methodspreviously described generates a warning message from the compiler. This isbecause of the C# versioning policy. Its designed to eliminate a class ofproblems associated with modifications to base classes.Heres the scenario: A developer creates a class that inherits from a third-party library. For the purposes of this discussion, we assume that theContact class represents the third-party library. Heres the example:public class Contact{// does not include FullAddress() method}public class SiteOwner : Contact{
  21. 21. public string FullAddress(){string fullAddress = mySite.ToString();return fullAddress;}}In this example, the FullAddress() method does not exist in the base class.There is no problem yet. Later on, the creators of the third-party libraryupdate their code. Part of this update includes a new member in a base classwith the exact same name as the derived class:public class Contact{private string address;private string city;private string state;private string zip;public string FullAddress(){string fullAddress =address + n +city + , + state + + zip;return fullAddress;}}public class SiteOwner : Contact{public string FullAddress(){string fullAddress = mySite.ToString();return fullAddress;}}In this code, the base class method FullAddress() contains differentfunctionality than the derived class method. In other languages, thisscenario would break the code because of implicit polymorphism. However,this does not break any code in C# because when the FullAddress() methodis called on SiteOwner, it is still the SiteOwner class method that gets called.This scenario generates a warning message. One way to eliminate thewarning message is to place a new modifier in front of the derived classmethod name, as the following example shows:using System;public class WebSite{public string SiteName;public string URL;public string Description;public WebSite()
  22. 22. {}public WebSite( string strSiteName, string strURL, string strDescription ){SiteName = strSiteName;URL = strURL;Description = strDescription;}public override string ToString(){return SiteName + ", " +URL + ", " +Description;}}public class Contact{public string address;public string city;public string state;public string zip;public string FullAddress(){string fullAddress =address + n +city + , + state + + zip;return fullAddress;}}public class SiteOwner : Contact{int siteHits;string name;WebSite mySite;public SiteOwner(){mySite = new WebSite();siteHits = 0;}public SiteOwner(string aName, WebSite aSite){mySite = new WebSite(aSite.SiteName,aSite.URL,aSite.Description);Name = aName;}new public string FullAddress(){string fullAddress = mySite.ToString();return fullAddress;}public string Name{get{siteHits++;return name;}set
  23. 23. {name = value;siteHits = 0;}}}public class Test{public static void Main(){WebSite mySite = new WebSite("Le Financier","http://www.LeFinancier.com","FancyFinancial Site");SiteOwner anOwner = new SiteOwner("John Doe", mySite);string address;anOwner.address = "123 Lane Lane";anOwner.city = "Some Town";anOwner.state = "HI";anOwner.zip = "45678";address = anOwner.FullAddress(); // Different ResultsConsole.WriteLine("Address: n{0}n", address);}}Heres the output:Address:Le Financier, http://www.LeFinancier.com, Fancy Financial SiteThis has the effect of explicitly letting the compiler know the developersintent. Placing the new modifier in front of the derived class member statesthat the developers know there is a base class method with the same name,and they definitely want to hide that member. This prevents breakage ofexisting code that depends on the implementation of the derived classmember. With C#, the method in the derived class is called when an objectof the derived class type is used. Likewise, the method in the base class iscalled when an object of the Base class type is called. Another problem thispresents is that the base class may present some desirable new featuresthat wouldnt be available through the derived class.To use these new features requires one of a few different workarounds. Oneoption would be to rename the derived class member, which would allowprograms to use a base class method through a derived class member. Thedrawback to this option would be if there were other classes relying upon theimplementation of the derived class member with the same name. Thisscenario will break code and, for this reason, is considered extremely badform.Another option is to define a new method in the derived class that called thebase class method. This allows users of the derived class to have the new
  24. 24. functionality of the base class, yet retain their existing functionality with thederived class. While this would work, there are maintainability concerns forthe derived class.Sealed ClassesSealed classes are classes that cant be derived from. To prevent otherclasses from inheriting from a class, make it a sealed class. There are acouple good reasons to create sealed classes, including optimization andsecurity.Sealing a class avoids the system overhead associated with virtual methods.This allows the compiler to perform certain optimizations that are otherwiseunavailable with normal classes.Another good reason to seal a class is for security. Inheritance, by its verynature, dictates a certain amount of protected access to the internals of apotential base class. Sealing a class does away with the possibility ofcorruption by derived classes. A good example of a sealed class is the Stringclass. The following example shows how to create a sealed class:public sealed class CustomerStats{string gender;decimal income;int numberOfVisits;public CustomerStats(){}}public class CustomerInfo : CustomerStats // error{}This example generates a compiler error. Since the CustomerStats class issealed, it cant be inherited by the CustomerInfo class.The CustomerStatsclass was meant to be used as an encapsulated object in another class. Thisis shown by the declaration of a CustomerStats object in the Customer class.public class Customer{CustomerStats myStats; // okay}Polymorphism
  25. 25. Polymorphism is reflected in the ability to write one routine that can operateon objects from more than one class-treating different objects from differentclasses in exactly the same way. For instance, if both Customer and Vendorobjects have a Name property, and we can write a routine that calls theName property regardless of whether were using a Customer or Vendorobject, then we have polymorphism.A vehicle is a good example of polymorphism. A vehicle interface would onlyhave those properties and methods that all vehicles have, a few of whichmight include paint color, number of doors, accelerator, and ignition. Theseproperties and methods would apply to all types of vehicles including cars,trucks, and semi-trucks.Polymorphism will not implement code behind the vehicles properties andmethods. Instead, polymorphism is the implementation of an interface. Ifthe car, truck, and semitruck all implement the same vehicle interface, thenthe client code for all three classes can be exactly the same.C# gives us polymorphism through inheritance. C# provides a keywordvirtual that is used in the definition of a method to support polymorphism.Child class are now free to provide their own implementation of this virtualmethod, that is called overriding. The following points are importantregarding virtual keyword:-If the method is not virtual, the compiler simply uses the reference type toinvoke the appropriate method.If the method is virtual, the compiler will generate code to checkup thereference type at runtime it is actually denoting to, then the appropriatemethod is called from the class of the reference type.When a virtual method is called, runtime check (late method binding) ismade to identify the object and appropriate method is invoked, all this isdone at runtime.In case of non-virtual methods, this information is available at compile time,so no runtime check to identify the object is made, so slightly efficient in theway non-virtual methods are called. But the behavior of virtual method isuseful in many ways; the functionality they provide is fair enough to bearthis slight loss of performance.Implementing Polymorphism
  26. 26. The key factor here is the ability to dynamically invoke methods in a classbased on their type. Essentially, a program would have a group of objects,examine the type of each one, and execute the appropriate method. Heresan example:using System;public class WebSite{public string SiteName;public string URL;public string Description;public WebSite(){}public WebSite( string strSiteName, string strURL, string strDescription ){SiteName = strSiteName;URL = strURL;Description = strDescription;}public override string ToString(){return SiteName + ", " +URL + ", " +Description;}}When we inherit above class, we have two choices to invoke constructor ofthe class. So this is an example of design time polymorphism. Here at designtime we have to decide which method we need to invoke while inheriting theclass.Polymorphism is the capability of a program to carry out dynamic operationsby implementing methods of multiple derived classes through a commonbase class reference. Another definition of polymorphism is the ability totreat different objects the same way. This means that the runtime type of anobject determines its behavior rather than the compile-time type of itsreference.Resource AllocationThe Microsoft .NET common language runtime requires that all resources beallocated from the managed heap. Objects are automatically freed whenthey are no longer needed by the application.When a process is initialized, the runtime reserves a contiguous region ofaddress space that initially has no storage allocated for it. This addressspace region is the managed heap. The heap also maintains a pointer. Thispointer indicates where the next object is to be allocated within the heap.
  27. 27. Initially, the pointer is set to the base address of the reserved address spaceregion.An application creates an object using the new operator. This operator firstmakes sure that the bytes required by the new object fit in the reservedregion (committing storage if necessary). If the object fits, then pointerpoints to the object in the heap, this objects constructor is called, and thenew operator returns the address of the object.Above fig shows a managed heap consisting of three objects: A, B, and C.The next object to be allocated will be placed where NextObjPtr points(immediately after object C).When an application calls the new operator to create an object, there maynot be enough address space left in the region to allocate to the object. Theheap detects this by adding the size of the new object to NextObjPtr. IfNextObjPtr is beyond the end of the address space region, then the heap isfull and a collection must be performed.In reality, a collection occurs when generation 0 is completely full. Briefly, ageneration is a mechanism implemented by the garbage collector in order toimprove performance. The idea is that newly created objects are part of ayoung generation, and objects created early in the applications lifecycle arein an old generation. Separating objects into generations can allow thegarbage collector to collect specific generations instead of collecting allobjects in the managed heap.The Garbage Collection AlgorithmThe garbage collector checks to see if there are any objects in the heap thatare no longer being used by the application. If such objects exist, then thememory used by these objects can be reclaimed. (If no more memory isavailable for the heap, then the new operator throws anOutOfMemoryException.)Every application has a set of roots. Roots identify storage locations, whichrefer to objects on the managed heap or to objects that are set to null. Forexample, all the global and static object pointers in an application areconsidered part of the applications roots. In addition, any localvariable/parameter object pointers on a threads stack are considered part ofthe applications roots. Finally, any CPU registers containing pointers to
  28. 28. objects in the managed heap are also considered part of the applicationsroots. The list of active roots is maintained by the just-in-time (JIT) compilerand common language runtime, and is made accessible to the garbagecollectors algorithm.When the garbage collector starts running, it makes the assumption that allobjects in the heap are garbage. In other words, it assumes that none of theapplications roots refer to any objects in the heap. Now, the garbagecollector starts walking the roots and building a graph of all objectsreachable from the roots. For example, the garbage collector may locate aglobal variable that points to an object in the heap.Following fig shows a heap with several allocated objects where theapplications roots refer directly to objects A, C, D, and F. All of these objectsbecome part of the graph. When adding object D, the collector notices thatthis object refers to object H, and object H is also added to the graph. Thecollector continues to walk through all reachable objects recursively.Once this part of the graph is complete, the garbage collector checks thenext root and walks the objects again. As the garbage collector walks fromobject to object, if it attempts to add an object to the graph that itpreviously added, then the garbage collector can stop walking down thatpath. This serves two purposes. First, it helps performance significantly sinceit doesnt walk through a set of objects more than once. Second, it preventsinfinite loops should you have any circular linked lists of objects.Once all the roots have been checked, the garbage collectors graph containsthe set of all objects that are somehow reachable from the applicationsroots; any objects that are not in the graph are not accessible by theapplication, and are therefore considered garbage.The garbage collector now walks through the heap linearly, looking forcontiguous blocks of garbage objects (now considered free space). Thegarbage collector then shifts the non-garbage objects down in memory(using the standard memcpy function), removing all of the gaps in the heap.Of course, moving the objects in memory invalidates all pointers to theobjects. So the garbage collector must modify the applications roots so thatthe pointers point to the objects new locations. In addition, if any objectcontains a pointer to another object, the garbage collector is responsible forcorrecting these pointers as well.Following fig shows the managed heap after a collection.
  29. 29. After all the garbage has been identified, all the non-garbage has beencompacted, and all the non-garbage pointers have been fixed-up, theNextObjPtr is positioned just after the last non-garbage object. At this point,the new operation is tried again and the resource requested by theapplication is successfully created.GC generates a significant performance hit, and this is the major downsideof using a managed heap. However, keep in mind that GCs only occur whenthe heap is full and, until then, the managed heap is significantly faster thana C-runtime heap. The runtimes garbage collector also offers someoptimizations using Generations that greatly improve the performance ofgarbage collection.You no longer have to implement any code that manages the lifetime of anyresources that your application uses. Now it is not possible to leak resources,since any resource not accessible from your applications roots can becollected at some point. Also it is not possible to access a resource that isfreed, since the resource wont be freed if it is reachable. If its notreachable, then your application has no way to access it.Following code demonstrates how resources are allocated and managed:class Application{public static int Main(String[] args){// ArrayList object created in heap, myArray is now in rootArrayList myArray = new ArrayList();// Create 10000 objects in the heapfor (int x = 0; x < 10000; x++){myArray.Add(new Object()); // Object object created in heap}// Right now, myArray is a root (on the threads stack). So,// myArray is reachable and the 10000 objects it points to are also reachable.Console.WriteLine(myArray.Count);// After the last reference to myArray in the code, myArray is not a root.// Note that the method doesnt have to return, the JIT compiler knows// to make myArray not a root after the last reference to it in the code.// Since myArray is not a root, all 10001 objects are not reachable// and are considered garbage. However, the objects are not// collected until a GC is performed.}}If GC is so great, you might be wondering why it isnt in ANSI C++. Thereason is that a garbage collector must be able to identify an applicationsroots and must also be able to find all object pointers. The problem with
  30. 30. C++ is that it allows casting a pointer from one type to another, and theresno way to know what a pointer refers to. In the common language runtime,the managed heap always knows the actual type of an object, and themetadata information is used to determine which members of an object referto other objects.GenerationsOne feature of the garbage collector that exists purely to improveperformance is called generations. A generational garbage collector (alsoknown as an ephemeral garbage collector) makes the followingassumptions:The newer an object is, the shorter its lifetime will be.The older an object is, the longer its lifetime will be.Newer objects tend to have strong relationships to each other and arefrequently accessed around the same time.Compacting a portion of the heap is faster than compacting the wholeheap.When initialized, the managed heap contains no objects. Objects added tothe heap are said to be in generation 0, as you can see in following fig.Stated simply, objects in generation 0 are young objects that have neverbeen examined by the garbage collector.Now, if more objects are added to the heap, the heap fills and a garbagecollection must occur. When the garbage collector analyzes the heap, itbuilds the graph of garbage (shown here in Green) and non-garbage objects.Any objects that survive the collection are compacted into the left-mostportion of the heap. These objects have survived a collection, are older, andare now considered to be in generation 1.As even more objects are added to the heap, these new, young objects areplaced in generation 0. If generation 0 fills again, a GC is performed. Thistime, all objects in generation 1 that survive are compacted and consideredto be in generation 2 (see following fig). All survivors in generation 0 arenow compacted and considered to be in generation 1. Generation 0 currentlycontains no objects, but all new objects will go into generation 0.
  31. 31. Currently, generation 2 is the highest generation supported by the runtimesgarbage collector. When future collections occur, any surviving objectscurrently in generation 2 simply stay in generation 2.Generational GC Performance OptimizationsGenerational garbage collecting improves performance. When the heap fillsand a collection occurs, the garbage collector can choose to examine onlythe objects in generation 0 and ignore the objects in any greatergenerations. After all, the newer an object is, the shorter its lifetime isexpected to be. So, collecting and compacting generation 0 objects is likelyto reclaim a significant amount of space from the heap and be faster than ifthe collector had examined the objects in all generations.A generational collector can offer more optimizations by not traversing everyobject in the managed heap. If a root or object refers to an object in an oldgeneration, the garbage collector can ignore any of the older objects innerreferences, decreasing the time required to build the graph of reachableobjects. Of course, it is possible that an old object refers to a new object. Sothat these objects are examined, the collector can take advantage of thesystems write-watch support (provided by the Win32 GetWriteWatchfunction in Kernel32.dll). This support lets the collector know which oldobjects (if any) have been written to since the last collection. These specificold objects can have their references checked to see if they refer to any newobjects.If collecting generation 0 doesnt provide the necessary amount of storage,then the collector can attempt to collect the objects from generations 1 and0. If all else fails, then the collector can collect the objects from allgenerations-2, 1, and 0.One of the assumptions stated earlier was that newer objects tend to havestrong relationships to each other and are frequently accessed around thesame time. Since new objects are allocated contiguously in memory, yougain performance from locality of reference. More specifically, it is highlylikely that all the objects can reside in the CPUs cache. Your application willaccess these objects with phenomenal speed since the CPU will be able toperform most of its manipulations without having cache misses which forcesRAM access.Microsofts performance tests show that managed heap allocations are fasterthan standard allocations performed by the Win32 HeapAlloc function. These
  32. 32. tests also show that it takes less than 1 millisecond on a 200 MHz Pentiumto perform a full GC of generation 0. It is Microsofts goal to make GCs takeno more time than an ordinary page fault.Disadvantages of Win32 heap:Most heaps (like the C runtime heap) allocate objects wherever theyfind free space. Therefore, if I create several objects consecutively, itis quite possible that these objects will be separated by megabytes ofaddress space. However, in the managed heap, allocating severalobjects consecutively ensures that the objects are contiguous inmemory.When memory is allocated from a Win32 heap, the heap must beexamined to find a block of memory that can satisfy the request. Thisis not required in managed heap, since here objects are contiguous inmemory.In Win32 heap, data structures that the heap maintains must beupdated. The managed heap, on the other hand, only needs toincrement the heap pointer.FinalizationThe garbage collector offers an additional feature that you may want to takeadvantage of: finalization. Finalization allows a resource to gracefully cleanup after itself when it is being collected. By using finalization, a resourcerepresenting a file or network connection is able to clean itself up properlywhen the garbage collector decides to free the resources memory.When the garbage collector detects that an object is garbage, the garbagecollector calls the objects Finalize method (if it exists) and then the objectsmemory is reclaimed. For example, lets say you have the following type (inC#):public class BaseObj{public BaseObj(){}protected override void Finalize(){// Perform resource cleanup code here// Example: Close file/Close network connectionConsole.WriteLine("In Finalize.");}}
  33. 33. Now you can create an instance of this object by calling:BaseObj bo = new BaseObj();Some time in the future, the garbage collector will determine that this objectis garbage. When that happens, the garbage collector will see that the typehas a Finalize method and will call the method, causing "In Finalize" toappear in the console window and reclaiming the memory block used by thisobject.Many developers who are used to programming in C++ draw an immediatecorrelation between a destructor and the Finalize method. However, objectfinalization and destructors have very different semantics and it is best toforget everything you know about destructors when thinking aboutfinalization. Managed objects never have destructors.When designing a type it is best to avoid using a Finalize method. There areseveral reasons for this:Finalizable objects get promoted to older generations, which increasesmemory pressure and prevents the objects memory from beingcollected when the garbage collector determines the object is garbage.In addition, all objects referred to directly or indirectly by this objectget promoted as well.Finalizable objects take longer to allocate.Forcing the garbage collector to execute a Finalize method cansignificantly hurt performance. Remember, each object is finalized. Soif I have an array of 10,000 objects, each object must have its Finalizemethod called.Finalizable objects may refer to other (non-finalizable) objects,prolonging their lifetime unnecessarily. In fact, you might want toconsider breaking a type into two different types: a lightweight typewith a Finalize method that doesnt refer to any other objects, and aseparate type without a Finalize method that does refer to otherobjects.You have no control over when the Finalize method will execute. Theobject may hold on to resources until the next time the garbagecollector runs.When an application terminates, some objects are still reachable andwill not have their Finalize method called. This can happen if
  34. 34. background threads are using the objects or if objects are createdduring application shutdown or AppDomain unloading. In addition, bydefault, Finalize methods are not called for unreachable objects whenan application exits so that the application may terminate quickly. Ofcourse, all operating system resources will be reclaimed, but anyobjects in the managed heap are not able to clean up gracefully. Youcan change this default behavior by calling the System.GC typesRequestFinalizeOnShutdown method. However, you should use thismethod with care since calling it means that your type is controlling apolicy for the entire application.The runtime doesnt make any guarantees as to the order in whichFinalize methods are called. For example, lets say there is an objectthat contains a pointer to an inner object. The garbage collector hasdetected that both objects are garbage. Furthermore, say that theinner objects Finalize method gets called first. Now, the outer objectsFinalize method is allowed to access the inner object and call methodson it, but the inner object has been finalized and the results may beunpredictable. For this reason, it is strongly recommended that Finalizemethods not access any inner, member objects.If you determine that your type must implement a Finalize method, thenmake sure the code executes as quickly as possible. Avoid all actions thatwould block the Finalize method, including any thread synchronizationoperations. Also, if you let any exceptions escape the Finalize method, thesystem just assumes that the Finalize method returned and continues callingother objects Finalize methods.When the compiler generates code for a constructor, the compilerautomatically inserts a call to the base types constructor. Likewise, when aC++ compiler generates code for a destructor, the compiler automaticallyinserts a call to the base types destructor. Finalize methods are differentfrom destructors. The compiler has no special knowledge about a Finalizemethod, so the compiler does not automatically generate code to call a basetypes Finalize method. If you want this behavior-and frequently you do-thenyou must explicitly call the base types Finalize method from your typesFinalize method:public class BaseObj{public BaseObj(){}protected override void Finalize(){Console.WriteLine("In Finalize.");
  35. 35. base.Finalize(); // Call base types Finalize}}Note that youll usually call the base types Finalize method as the laststatement in the derived types Finalize method. This keeps the base objectalive as long as possible. Since calling a base type Finalize method iscommon, C# has a syntax that simplifies your work. In C#, the followingcode:class MyObject{MyObject(){}}causes the compiler to generate this code:class MyObject{protected override void Finalize(){base.Finalize();}}Note that this C# syntax looks identical to the C++ languages syntax fordefining a destructor. But remember, C# doesnt support destructors. Dontlet the identical syntax fool you.Finalization InternalsWhen an application creates a new object, the new operator allocates thememory from the heap. If the objects type contains a Finalize method, thena pointer to the object is placed on the finalization queue. The finalizationqueue is an internal data structure controlled by the garbage collector. Eachentry in the queue points to an object that should have its Finalize methodcalled before the objects memory can be reclaimed.Following fig shows a heap containing several objects. Some of these objectsare reachable from the applications roots, and some are not. When objectsC, E, F, I, and J were created, the system detected that these objects hadFinalize methods and pointers to these objects were added to the finalizationqueue.
  36. 36. When a GC occurs, objects B, E, G, H, I, and J are determined to begarbage. The garbage collector scans the finalization queue looking forpointers to these objects. When a pointer is found, the pointer is removedfrom the finalization queue and appended to the freachable queue(pronounced "F-reachable"). The freachable queue is another internal datastructure controlled by the garbage collector. Each pointer in the freachablequeue identifies an object that is ready to have its Finalize method called.After the collection, the managed heap looks like following fig. Here, you seethat the memory occupied by objects B, G, and H has been reclaimedbecause these objects did not have a Finalize method that needed to becalled. However, the memory occupied by objects E, I, and J could not bereclaimed because their Finalize method has not been called yet.There is a special runtime thread dedicated to calling Finalize methods.When the freachable queue is empty (which is usually the case), this threadsleeps. But when entries appear, this thread wakes, removes each entryfrom the queue, and calls each objects Finalize method. Because of this, youshould not execute any code in a Finalize method that makes anyassumption about the thread thats executing the code. For example, avoidaccessing thread local storage in the Finalize method.The interaction of the finalization queue and the freachable queue is quitefascinating. First, let me tell you how the freachable queue got its name. Thef is obvious and stands for finalization; every entry in the freachable queueshould have its Finalize method called. The "reachable" part of the namemeans that the objects are reachable. To put it another way, the freachablequeue is considered to be a root just like global and static variables areroots. Therefore, if an object is on the freachable queue, then the object isreachable and is not garbage.In short, when an object is not reachable, the garbage collector considersthe object garbage. Then, when the garbage collector moves an objectsentry from the finalization queue to the freachable queue, the object is nolonger considered garbage and its memory is not reclaimed. At this point,the garbage collector has finished identifying garbage. Some of the objectsidentified as garbage have been reclassified as not garbage. The garbagecollector compacts the reclaimable memory and the special runtime threadempties the freachable queue, executing each objects Finalize method.
  37. 37. The next time the garbage collector is invoked, it sees that the finalizedobjects are truly garbage, since the applications roots dont point to it andthe freachable queue no longer points to it. Now the memory for the objectis simply reclaimed. The important thing to understand here is that two GCsare required to reclaim memory used by objects that require finalization. Inreality, more than two collections may be necessary since the objects couldget promoted to an older generation. Above fig shows what the managedheap looks like after the second GC.Dispose MethodUse this method to close or release unmanaged resources such as files,streams, and handles held by an instance of the class that implements thisinterface. This method is, by convention, used for all tasks associated withfreeing resources held by an object, or preparing an object for reuse.When implementing this method, objects must seek to ensure that all heldresources are freed by propagating the call through the containmenthierarchy. For example, if an object A allocates an object B, and object Ballocates an object C, then As Dispose implementation must call Dispose onB, which must in turn call Dispose on C. Objects must also call the Disposemethod of their base class if the base class implements IDisposable.If an objects Dispose method is called more than once, the object mustignore all calls after the first one. The object must not throw an exception ifits Dispose method is called multiple times. Dispose can throw an exceptionif an error occurs because a resource has already been freed and Disposehad not been called previously.Because the Dispose method must be called explicitly, objects thatimplement IDisposable must also implement a finalizer to handle freeingresources when Dispose is not called. By default, the garbage collector willautomatically call an objects finalizer prior to reclaiming its memory.However, once the Dispose method has been called, it is typicallyunnecessary for the garbage collector to call the disposed objects finalizer.To prevent automatic finalization, Dispose implementations can call theGC.SuppressFinalize method.Direct Control with System.GCThe System.GC type allows your application some direct control over thegarbage collector. You can query the maximum generation supported by the
  38. 38. managed heap by reading the GC.MaxGeneration property. Currently, theGC.MaxGeneration property always returns 2.It is also possible to force the garbage collector to perform a collection bycalling one of the two methods shown here:void GC.Collect(Int32 Generation)void GC.Collect()The first method allows you to specify which generation to collect. You maypass any integer from 0 to GC.MaxGeneration, inclusive. Passing 0 causesgeneration 0 to be collected; passing 1 cause generation 1 and 0 to becollected; and passing 2 causes generation 2, 1, and 0 to be collected. Theversion of the Collect method that takes no parameters forces a fullcollection of all generations and is equivalent to calling:GC.Collect(GC.MaxGeneration);Under most circumstances, you should avoid calling any of the Collectmethods; it is best to just let the garbage collector run on its own accord.However, since your application knows more about its behavior than theruntime does, you could help matters by explicitly forcing some collections.For example, it might make sense for your application to force a fullcollection of all generations after the user saves his data file. I imagineInternet browsers performing a full collection when pages are unloaded. Youmight also want to force a collection when your application is performingother lengthy operations; this hides the fact that the collection is takingprocessing time and prevents a collection from occurring when the user isinteracting with your application.The GC type also offers a WaitForPendingFinalizers method. This methodsimply suspends the calling thread until the thread processing the freachablequeue has emptied the queue, calling each objects Finalize method. In mostapplications, it is unlikely that you will ever have to call this method.Lastly, the garbage collector offers two methods that allow you to determinewhich generation an object is currently in:Int32 GetGeneration(Object obj)Int32 GetGeneration(WeakReference wr)The first version of GetGeneration takes an object reference as a parameter,and the second version takes a WeakReference reference as a parameter. Ofcourse, the value returned will be somewhere between 0 andGC.MaxGeneration, inclusive.
  39. 39. Chapter ObjectiveOOPs overviewClasses and ObjectsConstructor and DestructorFunction OverloadingEncapsulationInheritanceInterfacePolymorphismOOPs overviewObject-oriented programming (OOP) is the core ingredient of the .NET framework. OOP is so importantthat, before embarking on the road to .NET, you must understand its basic principles and terminology towrite even a simple program. The fundamental idea behind OOP is to combine into a single unit bothdata and the methods that operate on that data; such units are called an object. All OOP languagesprovide mechanisms that help you implement the object-oriented model. They are encapsulation,inheritance, polymorphism and reusability. Lets now take a brief look at these concepts.EncapsulationEncapsulation binds together code and the data it manipulates and keeps them both safe from outsideinterference and misuse. Encapsulation is a protective container that prevents code and data from beingaccessed by other code defined outside the container.InheritanceInheritance is the process by which one object acquires the properties of another object. A type derivesfrom a base type, taking all the base type members fields and functions. Inheritance is most useful whenyou need to add functionality to an existing type. For example all .NET classes inherit from theSystem.Object class, so a class can include new functionality as well as use the existing objects classfunctions and properties as well.PolymorphismPolymorphism is a feature that allows one interface to be used for a general class of action. This conceptis often expressed as "one interface, multiple actions". The specific action is determined by the exactnature of circumstances.ReusabilityOnce a class has been written, created and debugged, it can be distributed to other programmers for usein their own program. This is called reusability, or in .NET terminology this concept is called a componentor a DLL. In OOP, however, inheritance provides an important extension to the idea of reusability. Aprogrammer can use an existing class and without modifying it, add additional features to it.Simple "Hello World" C# Program
  40. 40. This simple one-class console "Hello world" program demonstrates many fundamental conceptsthroughout this article and several future articles.C# codeusing System;namespace oops{//class definitionpublic class SimpleHelloWorld{//Entry point of the programstatic void Main(string[] args){//print Hello world"Console.WriteLine("Hello World!");}}}So SimpleHelloWorld is the name of the class that contains the Main () method. On line 1 , a usingdirective indicates to the compiler that this source file refers to classes and constructs declared within theSystem namespace. Line 6 with the public keyword indicates the program accessibility scope for otherapplications or components.At line 7 there appears an opening curly brace ("{") which indicates the beginning of theSimpleHelloWorld class body. Everything belongs to the class, like fields, properties and methods appearin the class body between the opening and closing braces. The purpose of the Main () method is toprovide an entry point for application execution.The static keyword in the Main () method states that this method would be executed without instantiatingthe class.Compiling the ProgramYou can compile a C# program into either an assembly or a module. If the program has one class thatcontains a Main () method then it can be compiled directly into an assembly. This file has an ".exe"extension. A program with no Main() method can be compiled into a module as in the following:csc /target:module "program name"
  41. 41. You can then compile this program by F9 or by simply running the C# command line compiler (csc.exe)against the source file as the following:csc oops.csClasses and ObjectsClasses are special kinds of templates from which you can create objects. Each object contains data andmethods to manipulate and access that data. The class defines the data and the functionality that eachobject of that class can contain.A class declaration consists of a class header and body. The class header includes attributes, modifiers,and the class keyword. The class body encapsulates the members of the class, that are the data membersand member functions. The syntax of a class declaration is as follows:Attributes accessibility modifiers class identifier: baselist { body }Attributes provide additional context to a class, like adjectives; for example the Serializable attribute.Accessibility is the visibility of the class. The default accessibility of a class is internal. Private is the defaultaccessibility of class members. The following table lists the accessibility keywords;Keyword Descriptionpublic Public class is visible in the current and referencing assembly.private Visible inside current class.protected Visible inside current and derived class.Internal Visible inside containing assembly.Internal protected Visible inside containing assembly and descendent of the current class.Modifiers refine the declaration of a class. The list of all modifiers defined in the table are as follows;Modifier Descriptionsealed Class cant be inherited by a derived class.static Class contains only static members.unsafe The class that has some unsafe construct likes pointers.Abstract The instance of the class is not created if the Class is abstract.The baselist is the inherited class. By default, classes inherit from the System.Object type. A class caninherit and implement multiple interfaces but doesnt support multiple inheritances.Step-by-step Tutorial for Creating a Class1. Open Visual Studio 2010 from start menu.
  42. 42. 2. Go to "File" > "New" > "Project...", select "Console Application" in the right pane and provide thename "oops" for the project.3. Then in the Solution Explorer, you will notice some files that are automatically created as:4. You can also write your own code in the default program.cs file that is created but it is a goodprogramming practice to create a new class.5. For adding a new class, right-click over the project name (oops) in the Solution Explorer, then click"Add" > "Class". Give the name to the class "customer" as in the following;
  43. 43. 6. When you open the customer.cs class. you will find some default-generated code as in thefollowing;C# codeusing System;using System.Collections.Generic;using System.Linq;using System.Text;namespace oops{class customer{}}Note: the C# console application project must require a single entry point Main () function that is alreadygenerated in the program class. For example if you add a new customer class and want to define one ormore Main () entry points here then .NET will throw an error of multiple entry points. So it is advisable todelete or exclude the program.cs file from the solution.So here in this example the customer class defines fields such as CustID, Name and Address to holdinformation about a particular customer. It might also define some functionality that acts upon the datastored in these fields.C# codeusing System;namespace oops{class customer{// Member Variablespublic int CustID;public string Name;public string Address;//constuctor for initializing fieldscustomer(){CustID=1101;Name="Tom";
  44. 44. Address="USA";}//method for displaying customer records (functionality)public void displayData(){Console.WriteLine("Customer="+CustID);Console.WriteLine("Name="+Name);Console.WriteLine("Address="+Address);}// Code for entry point}}At line 9, we are defining a constructor of the customer class for initializing the class member fields. Theconstructor is a special function that is automatically called when the customer class object is created(instantiated). And at line 11 we are printing these fields to the console by creating a user defined methoddisplayData().You can then instantiate an object of this class to represent one specific customer, set the field value forthat instance and use its functionality, as in:C# codeclass customer{// class members code//Entry pointstatic void Main(string[] args){// object instantiationcustomer obj = new customer();//Method callingobj.displayData();//fields callingConsole.WriteLine(obj.CustID);Console.WriteLine(obj.Name);Console.WriteLine(obj.Address);}
  45. 45. }Here you use the keyword new to declare the customer class instance. This keyword creates the objectand initializes it. When you create an object of the customer class, the .NET framework IDE provides aspecial feature called Intellisense that provides access to all the class member fields and functionsautomatically. This feature is invoke when the "." Operator is put right after the object, as in the following;Image 1.1 Intellisense featureNormally, as the program grows in size and the code becomes more complex, the Intellisense featureincreases the convenience for the programmer by showing all member fields, properties and functions.Multiple Class DeclarationSometimes circumstances require multiple classes to be declared in a single namespace. So in that case itis not mandatory to add a separate class to the solution, instead you can attach the new class into theexisting program.cs or another one as in the following;C# codeusing System;namespace oops{
  46. 46. class Program{public void MainFunction(){Console.WriteLine("Main class");}static void Main(string[] args){//main class instanceProgram obj = new Program();obj.MainFunction();//other class instacedemo dObj=new demo();dObj.addition();}}class demo{int x = 10;int y = 20;int z;public void addition(){z = x + y;Console.WriteLine("other class in Namespace");Console.WriteLine(z);}}}Here in this example, we are creating an extra class "demo" in the program.cs file at line 12 and finally weare instantiating the demo class with the program class inside the Main() entry in lines 6 to 11. So itdoesnt matter how many classes we are defining in a single assembly.Partial classesTypically, a class will reside entirely in a single file. However, in situations where multiple developers needaccess to the same class, then having the class in multiple files can be beneficial. The partial keywordsallow a class to span multiple source files. When compiled, the elements of the partial types are combined
  47. 47. into a single assembly.There are some rules for defining a partial class as in the following;A partial type must have the same accessibility.Each partial type is preceded with the "partial" keyword.If the partial type is sealed or abstract then the entire class will be sealed and abstract.In the following example we are adding two files, partialPart1.cs and partialPart2.cs, and declare a partialclass, partialclassDemo, in both classes.partialPart1.csusing System;namespace oops{public partial class partialclassDemo{public void method1(){Console.WriteLine("method from part1 class");}}}partialPart2.csusing System;namespace oops{public partial class partialclassDemo{public void method2(){Console.WriteLine("method from part2 class");}}}And finally we are creating an instance of the partialclassDemo in the program.cs file as the following:
  48. 48. Program.csusing System;namespace oops{class Program{static void Main(string[] args){//partial class instancepartialclassDemo obj = new partialclassDemo();obj.method1();obj.method2();}}}Static classesA static class is declared using the "static" keyword. If the class is declared as static then the compilernever creates an instance of the class. All the member fields, properties and functions must be declared asstatic and they are accessed by the class name directly not by a class instance object.C# codeusing System;namespace oops{static class staticDemo{//static fieldsstatic int x = 10, y;//static methodstatic void calcute(){y = x * x;Console.WriteLine(y);}static void Main(string[] args)
  49. 49. {//function calling directlystaticDemo.calcute();}}}Creating and accessing Class Component Library.NET provides the capability of creating libraries (components) of a base application rather than anexecutable (".exe"). Instead the library projects final build version will be ".DLL" that can bereferenced from other outside applications to expose its entire functionality.Step-by-step tutorial1. First create a class library based application as:2. Then we are implementing a math class library that is responsible of calculating square root and theaddition of two numbers as:using System;
  50. 50. namespace LibraryUtil{public class MathLib{public MathLib() { }public void calculareSum(int x, int y){int z = x + y;Console.WriteLine(z);}public void calculareSqrt(double x){double z = Math.Sqrt(x);Console.WriteLine(z);}}}3. Build this code and you will notice that a DLL file was created, not an executable, in the root directory ofthe application (path = D:tempLibraryUtilLibraryUtilbinDebug LibraryUtil.dll).4. Now create another console based application where you utilize all the class librarys functionality.5. Then you have to add the class library dll file reference to access the declared class in the library dll.(Right-click on the Reference then "Add reference" then select the path of the dll file.)6. When you add the class library reference then you will notice in the Solution Explorer that a newLibraryUtil is added as in the following;
  51. 51. 7. Now add the namespace of the class library file in the console application and create the instance ofthe class declared in the library as in the following;using System;using LibraryUtil; // add library namespacenamespace oops{public class LibraryClass{static void Main(){//library class instanceMathLib obj = new MathLib();//method populateobj.calculareSum(2, 5);obj.calculareSqrt(25);}}}8. Finally run the application.Constructor and DestructorA constructor is a specialized function that is used to initialize fields. A constructor has the same name asthe class. Instance constructors are invoked with the new operator and cant be called in the same manneras other member functions. There are some important rules pertaining to constructors as in the following;Classes with no constructor have an implicit constructor called the default constructor, that isparameterless. The default constructor assigns default values to fields.A public constructor allows an object to be created in the current assembly or referencingassembly.Only the extern modifier is permitted on the constructor.A constructor returns void but does not have an explicitly declared return type.A constructor can have zero or more parameters.Classes can have multiple constructors in the form of default, parameter or both.The following example shows one constructor for a customer class.
  52. 52. C# codeusing System;namespace oops{class customer{// Member Variablespublic string Name;//constuctor for initializing fieldspublic customer(string fname, string lname){Name= fname +" "+ lname;}//method for displaying customer recordspublic void AppendData(){Console.WriteLine(Name);}//Entry pointstatic void Main(string[] args){// object instantiationcustomer obj = new customer("Barack", "Obama");//Method callingobj.AppendData();}}}Note: The moment a new statement is executed, the default constructor is called.Static ConstructorA constructor can be static. You create a static constructor to initialize static fields. Static constructors arenot called explicitly with the new statement. They are called when the class is first referenced. There aresome limitations of the static constructor as in the following;Static constructors are parameterless.Static constructors cant be overloaded.
  53. 53. There is no accessibility specified for Static constructors.In the following example the customer class has a static constructor that initializes the static field and thisconstructor is called when the class is referenced in the Main () at line 26 as in the following:C# codeusing System;namespace oops{class customer{// Member Variablesstatic private int x;//constuctor for static initializing fieldsstatic customer(){x = 10;}//method for get static fieldstatic public void getData(){Console.WriteLine(x);}//Entry pointstatic void Main(string[] args){//static Method callingcustomer.getData();}}}DestructorsThe purpose of the destructor method is to remove unused objects and resources. Destructors are notcalled directly in the source code but during garbage collection. Garbage collection is nondeterministic. Adestructor is invoked at an undetermined moment. More precisely a programmer cant control itsexecution; rather it is called by the Finalize () method. Like a constructor, the destructor has the samename as the class except a destructor is prefixed with a tilde (~). There are some limitations of destructorsas in the following;
  54. 54. Destructors are parameterless.A Destructor cant be overloaded.Destructors are not inherited.Destructors can cause performance and efficiency implications.The following implements a destructor and dispose method. First of all we are initializing the fields viaconstructor, doing some calculations on that data and displaying it to the console. But at line 9 we areimplementing the destructor that is calling a Dispose() method to release all the resources.using System;namespace oops{class customer{// Member Variablespublic int x, y;//constuctor for initializing fieldscustomer(){Console.WriteLine("Fields inititalized");x = 10;}//method for get fieldpublic void getData(){y = x * x;Console.WriteLine(y);}//method to release resource explicitlypublic void Dispose(){Console.WriteLine("Fields cleaned");x = 0;y = 0;}//destructor~customer(){Dispose();}//Entry point
  55. 55. static void Main(string[] args){//instance createdcustomer obj = new customer();obj.getData();}}}At line 12 when the instance is created, fields are initialized but it is not necessary that at the same timethe destructor is also called. Its calling is dependent on garbage collection. If you want to see thedestructor being called into action then put a breakpoint (by F9) at line 10 and compile the application.The CLR indicates its execution at the end of the program by highlighting line 10 using the yellow color.Function OverloadingFunction overloading allows multiple implementations of the same function in a class. Overloadedmethods share the same name but have a unique signature. The number of parameters, types ofparameters or both must be different. A function cant be overloaded on the basis of a different returntype alone.using System;namespace oops{class funOverload{public string name;//overloaded functionspublic void setName(string last){name = last;}public void setName(string first, string last){name = first + "" + last;}public void setName(string first, string middle, string last){
  56. 56. name = first + "" + middle + "" + last;}//Entry pointstatic void Main(string[] args){funOverload obj = new funOverload();obj.setName("barack");obj.setName("barack "," obama ");obj.setName("barack ","hussian","obama");}}}At lines 3, 4 and 5 we are defining three methods with the same name but with different parameters. Inthe Main (), the moment you create an instance of the class and call the functions setName() via obj atlines 7, 8 and 9 then intellisense will show three signatures automatically.EncapsulationEncapsulation is the mechanism that binds together the code and the data it manipulates, and keeps bothsafe from outside interference and misuse. In OOP, code and data may be combined in such a way that aself-contained box is created. When code and data are linked together in this way, an object is createdand encapsulation exists.Within an object, code, data or both may be private or public to that object. Private code is known to andaccessible only by another part of the object, that is private code or data may not be accessible by a pieceof the program that exists outside the object. When the code and data is public, other portions of yourprogram may access it even though it is defined within an object.C# codeusing System;namespace oops{class Encapsulation{/// <summary>/// Every member Variable and Function of the class are bind/// with the Encapsulation class object only and safe with
  57. 57. /// the outside inference/// </summary>// Encapsulation Beginint x;//class constructorpublic Encapsulation(int iX){this.x = iX;}//calculating the squarepublic void MySquare(){int Calc = x * x;Console.WriteLine(Calc);}// End of Encapsulation//Entry pointstatic void Main(string[] args){//instance createdcustomer obj = new customer(20);obj. MySquare();}}}InheritanceInheritance is the process by which one object can acquire the properties of another object. Inheritance isa "is a kind of" relationship and it supports the concept of classification in which an object needs onlydefine those qualities that make it unique within the class. Inheritance involves a base class and a derivedclass. The derived class inherits from the base class and also can override inherited members as well asadd new members to extend the base class.A base type represents the generalization, whereas a derived type represents a specification of aninstance. Such as Employees that can have diverse types, such as hourly, salaried and temporary so in thatcase Employees is the general base class and hourly, salaried and temporary employee are specializedderived classes.
  58. 58. Classes can inherit from a single class and one or more interfaces. When inheriting from a class, thederived class inherits the members including the code of the base class. The important point to rememberis that Constructors and Destructors are not inherited from the base class.The syntax of inheritance is as in the following;Class derivedClass : baseClass, Iterface1, Interface2 { body }For example we are defining two classes, Father and Child. You notice at line 7, we are implementinginheritance by using a colon (:); at this moment all the properties belonging to the Father Class isaccessible to the Child class automatically.C# codeusing System;namespace oops{//Base Classpublic class Father{public void FatherMethod(){Console.WriteLine("this property belong to Father");}}//Derived classpublic class Child : Father
  59. 59. {public void ChildMethod(){Console.WriteLine("this property belong to Child");}}class Inheritance{//Entry pointstatic void Main(string[] args){Father fObj = new Father();fObj.FatherMethod();//Here Child object can access both class methodsChild cObj = new Child();cObj.FatherMethod();cObj.ChildMethod();}}}At line 11 , the Intellisense only shows the Father class functions but at line 15 to 16 the Child class objectis able to access both class methods as in the following.We can create a class in the VB.Net language or another .NET supported language and can inherit them ina C# .Net class and vice versa. But a class developed in C++ or other unmanaged environment cant beinherited in .NET.Note: Cross-language and multiple inheritance is not supported by .NET.AccessibilityAccessibility sets the visibility of the member to outside assemblies or derived types. The following tabledescribes member accessibility;Modifiers Outside Assembly Derived Classprivate No Nopublic Yes Yesprotected No Nointernal Yes ( this assembly only) Yes ( this assembly only)internal protected Yes( this assembly only) Yes
  60. 60. Constructor in InheritanceConstructors in a base class are not inherited in a derived class. A derived class has a base portion andderived portion. The base portion initializes the base portion, and the constructor of the derived classinitializes the derived portion.The following is the syntax of a constructor in inheritance;Accessibility modifier classname(parameterlist1) : base(parameterlist2) { body }So the base keyword refers to the base class constructor, while parameterlist2 determines whichoverloaded base class constructor is called.In the following example, the Child classs constructor calls the single-argument constructor of the baseFather class;C# codeusing System;namespace oops{//Base Classpublic class Father{//constructorpublic Father(){Console.WriteLine("Father class constructor");}public void FatherMethod(){Console.WriteLine("this property belong to Father");}}//Derived classpublic class Child : Father{public Child(): base(){Console.WriteLine("child class constructor");}public void ChildMethod()
  61. 61. {Console.WriteLine("this property belong to Child");}}class Inheritance{//Entry pointstatic void Main(string[] args){//Here Child object can access both class methodsChild cObj = new Child();cObj.FatherMethod();cObj.ChildMethod();Console.ReadKey();}}}At line 4, we are defining a base Father Class constructor and in the derived class Child, at line 8 we areinitializing it explicitly via base keyword. If we pass any parameter in the base class constructor then wehave to provide them in the base block of the child class constructor.Virtual MethodsBy declaring a base class function as virtual, you allow the function to be overridden in any derived class.The idea behind a virtual function is to redefine the implementation of the base class method in thederived class as required. If a method is virtual in the base class then we have to provide the overridekeyword in the derived class. Neither member fields nor static functions can be declared as virtual.C# codeusing System;namespace oops{class myBase{//virtual functionpublic virtual void VirtualMethod(){Console.WriteLine("virtual method defined in the base class");}}
  62. 62. class myDerived : myBase{// redifing the implementation of base class methodpublic override void VirtualMethod(){Console.WriteLine("virtual method defined in the Derive class");}}class virtualClass{static void Main(string[] args){// class instancenew myDerived().VirtualMethod();Console.ReadKey();}}}Hiding MethodsIf a method with the same signature is declared in both base and derived classes, but the methods are notdeclared as virtual and overriden respectively, then the derived class version is said to hide the base classversion. In most cases, you would want to override methods rather than hide them. Otherwise .NETautomatically generates a warning.In the following example, we are defining a VirutalMethod() in the myBase class but not overriding it inthe derived class, so in that case the compiler will generate a warning. The compiler will assume that youare hiding the base class method. So to overcome that problem, if you prefix the new keyword in thederived class method then the compiler will prefer the most derived version method. You can still accessthe base class method in the derived class by using the base keyword.C# codeusing System;namespace oops{class myBase{//virtual functionpublic virtual void VirtualMethod(){Console.WriteLine("virtual method defined in the base class");
  63. 63. }}class myDerived : myBase{// hiding the implementation of base class methodpublic new void VirtualMethod(){Console.WriteLine("virtual method defined in the Derive class");//still access the base class methodbase.VirtualMethod();}}class virtualClass{static void Main(string[] args){// class instancenew myDerived().VirtualMethod();Console.ReadKey();}}}Abstract ClassesC# allows both classes and functions to be declared abstract using the abstract keyword. You cant createan instance of an abstract class. An abstract member has a signature but no function body and they mustbe overridden in any non-abstract derived class. Abstract classes exist primarily for inheritance. Memberfunctions, properties and indexers can be abstract. A class with one or more abstract members must beabstract as well. Static members cant be abstract.In this example, we are declaring an abstract class Employess with a method displayData() that does nothave an implementation. Then we are implementing the displayData() body in the derived class. One pointto be noted here is that we have to prefixe the abstract method with the override keyword in the derivedclass.C# codeusing System;namespace oops{//abstract classpublic abstract class Employess{//abstract method with no implementation
  64. 64. public abstract void displayData();}//derived classpublic class test : Employess{//abstract class method implementationpublic override void displayData(){Console.WriteLine("Abstract class method");}}class abstractClass{static void Main(string[] args){// class instancenew test().displayData();}}}Sealed ClassesSealed classes are the reverse of abstract classes. While abstract classes are inherited and are refined inthe derived class, sealed classes cannot be inherited. You can create an instance of a sealed class. A sealedclass is used to prevent further refinement through inheritance.Suppose you are a developer of a class library and some of the classes in the class library are extensiblebut other classes are not extensible so in that case those classes are marked as sealed.C# codeusing System;namespace oops{sealed class SealedClass{void myfunv();}public class test : SealedClass //wrong. will give compilation error{}}
  65. 65. InterfaceAn interface is a set of related functions that must be implemented in a derived class. Members of aninterface are implicitly public and abstract. Interfaces are similar to abstract classes. First, both types mustbe inherited; second, you cannot create an instance of either. Although there are several differences as inthe following;An Abstract class can contain some implementations but an interface cant.An Interface can only inherit other interfaces but abstract classes can inherit from other classesand interfaces.An Abstract class can contain constructors and destructors but an interface cant.An Abstract class contains fields but interfaces dont.So the question is, which of these to choose? Select interfaces because with an interface, the derived typestill can inherit from another type and interfaces are more straightforward than abstract classes.C# codeusing System;namespace oops{// interfacepublic interface xyz{void methodA();void methodB();}// interface method implementationclass test : xyz{public void methodA(){Console.WriteLine("methodA");}public void methodB(){Console.WriteLine("methodB");}}class interfaceDemo{static void Main(string[] args){test obj = new test();obj.methodA();obj.methodB();}