1

Access Modifiers:
C# Access Modifier Public Private (default) Protected Meaning Marks a member as accessible from an object variable as well as any derived classes. Marks a method as accessible only by the class that has defined the method. In C#, all members are private by default. Marks a method as usable by the defining class, as well as any derived classes. Protected methods, however, are not accessible from an object variable. Defines a method that is accessible by any type in the same assembly, but not outside the assembly. Defines a method whose access is limited to the current assembly or types derived from the defining class in the current assembly. Unmarked members are private by default in C#.

Internal protected internal

class SomeClass { // Accessible anywhere. public void PublicMethod(){} // Accessible only from SomeClass types. private void PrivateMethod(){} // Accessible from SomeClass and any descendent. protected void ProtectedMethod(){} // Accessible from within the same assembly. internal void InternalMethod(){} // Assembly-protected access. protected internal void ProtectedInternalMethod(){} // Unmarked members are private by default in C#. void SomeMethod(){} }

2) What is default modifier of class, function and variables? Prepare list for same. Class Methods Variables Constructor Interface Static Method Internal Private Private Private Public Private

3) Can we create static internal method? Method can be declared as static internal and can be used with Class name. 4) Can Non Static class contain static functions? Static Methods can be declared in a non static class.

2

ASP.NET Interview Questions
1. Describe the role of inetinfo.exe, aspnet_isapi.dll and aspnet_wp.exe in the page loading process. Inetinfo.exe is theMicrosoft IIS server running, handling ASP.NET requests among other things. When an ASP.NET request is received (usually a file with .aspx extension),the ISAPI filter aspnet_isapi.dll takes care of it by passing the request to the actual worker process aspnet_wp.exe. 2. What’s the difference between Response.Write() andResponse.Output.Write()? The latter one allows you to write formatted output. 3. What methods are fired during the page load? Init() - when the pageis instantiated, Load() when the page is loaded into server memory,PreRender() - the brief moment before the page is displayed to the user asHTML, Unload() - when page finishes loading. 4. Where does the Web page belong in the .NET Framework class hierarchy?System.Web.UI.Page 5. Where do you store the information about the user’s locale? System.Web.UI.Page.Culture

6. What’s the difference between Codebehind="MyCode.aspx.cs" and Src="MyCode.aspx.cs"? CodeBehind is relevant to Visual Studio.NET only. 7. What’s a bubbled event? When you have a complex control, like DataGrid, writing an event processing routine for each object (cell, button, row, etc.) is quite tedious. The controls can bubble up their eventhandlers, allowing the main DataGrid event handler to take care of its constituents. 8. Suppose you want a certain ASP.NET function executed on MouseOver overa certain button. Where do you add an event handler? It’s the Attributesproperty, the Add function inside that property. So btnSubmit.Attributes.Add ("onMouseOver","someClientCode();") 9. What data type does the RangeValidator control support? Integer,String and Date.

10. Explain the differences between Server-side and Client-side code? Server-side code runs on the server. Client-side code runs in the clients’ browser. 11. What type of code (server or client) is found in a Code-Behind class? Server-side code.

12. Should validation (did the user enter a real date) occur server-side or client-side? Why? Client-side. This reduces an additional request to the server to validate the users input. 13. What does the "EnableViewState" property do? Why would I want it on or off? It enables the viewstate on the page. It allows the page to save the users input on a form. 14. What is the difference between Server.Transfer and Response.Redirect? Why would I choose one over the other? Server.Transfer is used to post a form to another page. Response.Redirect is used to redirect the user to another page or site. _____________________________________________________________________________ The Response .Redirect () method can be used to redirect the browser to specified url, pointing to any resource and may contain query strings and causes an extra roundtrip Server.Transfer() performs server side redirection of the page avoiding extra roundtrip. Server.Transfer() is preferred over Response.Redirect to avoid rountrip but the limitation is the aspx page should reside on same web server. _____________________________________________________________________________

3 15. Can you explain the difference between an ADO.NET Dataset and an ADO Recordset? · A DataSet can represent an entire relational database in memory, complete with tables, relations, and views. · A DataSet is designed to work without any continuing connection to the original data source. · Data in a DataSet is bulk-loaded, rather than being loaded on demand. · There's no concept of cursor types in a DataSet. · DataSets have no current record pointer You can use For Each loops to move through the data. · You can store many edits in a DataSet, and write them to the original data source in a single operation. · Though the DataSet is universal, other objects in ADO.NET come in different versions for different data sources. 16. Can you give an example of what might be best suited to place in the Application_Start and Session_Start subroutines? This is where you can set the specific variables for the Application and Session objects. 17. If I’m developing an application that must accommodate multiple security levels though secure login and my ASP.NET web application is spanned across three web-servers (using round-robin load balancing) what would be the best approach to maintain login-in state for the users? Maintain the login state security through a database. 18. Can you explain what inheritance is and an example of when you might use it? When you want to inherit (use the functionality of) another class. Base Class Employee. A Manager class could be derived from the Employee base class. 19. Whats an assembly? Assemblies are the building blocks of the .NET framework. Overview of assemblies from MSDN 20. Describe the difference between inline and code behind. Inline code written along side the html in a page. Code-behind is code written in a separate file and referenced by the .aspx page. 21. Explain what a diffgram is, and a good use for one? The DiffGram is one of the two XML formats that you can use to render DataSet object contents to XML. For reading database data to an XML file to be sent to a Web Service. 22. Whats MSIL, and why should my developers need an appreciation of it if at all? MSIL is the Microsoft Intermediate Language. All .NET compatible languages will get converted to MSIL. 23. Which method do you invoke on the DataAdapter control to load your generated dataset with data? The .Fill() method 24. Can you edit data in the Repeater control? No, it just reads the information from its data source 25. Which template must you provide, in order to display data in a Repeater control? ItemTemplate 26. How can you provide an alternating color scheme in a Repeater control? Use the AlternatingItemTemplate 27. What property must you set, and what method must you call in your code, in order to bind the data from some data source to the Repeater control? You must set the DataSource property and call the DataBind method. 28. What base class do all Web Forms inherit from? The Page class.

29. Name two properties common in every validation control? ControlToValidate property and Text property.

4 30. What tags do you need to add within the asp:datagrid tags to bind columns manually? Set AutoGenerateColumns Property to false on the datagrid tag 31. What tag do you use to add a hyperlink column to the DataGrid?

32. What is the transport protocol you use to call a Web service? SOAP is the preferred protocol. 33. 34. 35. True or False: A Web service can only be written in .NET? False What does WSDL stand for? (Web Services Description Language) Where on the Internet would you look for Web services? (http://www.uddi.org)

36. Which property on a Combo Box do you set with a column name, prior to setting the DataSource, to display data in the combo box? DataTextField property 37. Which control would you use if you needed to make sure the values in two different controls matched? CompareValidator Control 38. True or False: To test a Web service you must create a windows application or Web application to consume this service? False, the webservice comes with a test page and it provides HTTP-GET method to test. 39. How many classes can a single .NET DLL contain? It can contain many classes.

- Briefly explain how code behind works and contrast that using the inline style. - What are HTML controls, Web controls, and server controls? - Briefly explain how the server control validation controls work. - Briefly explain what user controls are and what server controls are and the differences between the two. - Briefly explain how server form post-back works (perhaps ask about view state as well). - Can the action attribute of a server-side <form> tag be set to a value and if not how can you possibly pass data from a form page to a subsequent page. (Extra credit: Have you heard of comdna. :-) - Briefly describe the role of global.asax. - How would ASP and ASP.NET apps run at the same time on the same server? - What are good ADO.NET object(s) to replace the ADO Recordset object. Seems like some pretty tough questions for an interview (and certainly questions like the ones above should not be the only type asked at an interview) but it's a tough job market out there, a lot of people claim to have a lot of experience with ASP.NET but have really just installed Beta 1 and maybe Beta 2 and played around for a week, and something like the above should give a quick sense as to whether someone has hands-on with ASP.NET or not. - Oh, and ofcourse, what is the correct language to code ASP.NET pages with? (The only correct answer would be C#. :-) Maybe this should be the first question. 1. Explain the code behind wors and contrast that using the inline style. 2. Different types of HTML,Web and server controls (also how Server control validation controls work) 4. Difference between user and server controls 4. How server form post-back works (perhaps ask about view state as well). 5. Can the action attribute of a server-side <form> tag be set to a value and if not how can you possibly pass data from a form page to a subsequent page. 6. What is the role of global.asax. 7. How would ASP and ASP.NET apps run at the same time on the same server? 8. What are good ADO.NET object(s) to replace the ADO Recordset object.

5 Answers: 3. Server controls are built-in. User controls are created by the developer to allow for the reuse of controls that need specific functionality. 4. By default all pages in .NET post back to themselves. The view state keeps the users input updated on the page. 5. No, You have to use Server.Transfer to pass the data to another page. 6. Store global information about the application 8. There are alot...but the base once are SqlConnection, OleDbConnection, etc... In addition to the above some couple of basic questions, a couple of additional questions listed below. Good luck! ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 1. Explain the differences between Server-side and Client-side code? 2. What type of code (server or client) is found in a Code-Behind class? 3. Should validation (did the user enter a real date) occur server-side or client-side? Why? 4. What does the "EnableViewState" property do? Why would I want it on or off? 5. What is the difference between Server.Transfer and Response.Redirect? Why would I choose one over the other? 6. Can you give an example of when it would be appropriate to use a web service as opposed to a non-serviced .NET component 7. Let's say I have an existing application written using Visual Studio 6 (VB 6, InterDev 6) and this application utilizes Windows 2000 COM+ transaction services. How would you approach migrating this application to .NET 8. Can you explain the difference between an ADO.NET Dataset and an ADO Recordset? 9. Can you give an example of what might be best suited to place in the Application_Start and Session_Start subroutines? 10. If I'm developing an application that must accomodate multiple security levels though secure login and my ASP.NET web appplication is spanned across three web-servers (using round-robbin load balancing) what would be the best approach to maintain login-in state for the users? 11. What are ASP.NET Web Forms? How is this technology different than what is available though ASP (1.0-3.0)? 12. How does VB.NET/C# achieve polymorphism? 11. Can you explain what inheritance is and an example of when you might use it? 13. How would you implement inheritance using VB.NET/C#? 14. Whats an assembly 15. Describe the difference between inline and code behind - which is best in a 16. loosely coupled solution 17. Explain what a diffgram is, and a good use for one 18. Where would you use an iHTTPModule, and what are the limitations of any 19. approach you might take in implementing one 20. What are the disadvantages of viewstate/what are the benefits 21 Describe session handling in a webfarm, how does it work and what are the > limits 22. How would you get ASP.NET running in Apache web servers - why would you even do this? 23. Whats MSIL, and why should my developers need an appreciation of it if at all?

6 24. In what order do the events of an ASPX page execute. As a developer is it important to undertsand these events? 25. Which method do you invoke on the DataAdapter control to load your generated dataset with data? 26. Can you edit data in the Repeater control? 27. Which template must you provide, in order to display data in a Repeater control? 28. How can you provide an alternating color scheme in a Repeater control? 29. What property must you set, and what method must you call in your code, in order to bind the data from some data source to the Repeater control? 30. What base class do all Web Forms inherit from? 31. What method do you use to explicitly kill a user s session? 32 How do you turn off cookies for one page in your site? 33. Which two properties are on every validation control? 34. What tags do you need to add within the asp:datagrid tags to bind columns manually? 35. How do you create a permanent cookie? 36. What tag do you use to add a hyperlink column to the DataGrid? 37. What is the standard you use to wrap up a call to a Web service 38. Which method do you use to redirect the user to another page without performing a round trip to the client? 39. What is the transport protocol you use to call a Web service SOAP 40. True or False: A Web service can only be written in .NET 41. What does WSDL stand for? 42. What property do you have to set to tell the grid which page to go to when using the Pager object? 43. Where on the Internet would you look for Web services? 44. What tags do you need to add within the asp:datagrid tags to bind columns manually. 45. Which property on a Combo Box do you set with a column name, prior to setting the DataSource, to display data in the combo box? 46. How is a property designated as read-only? 47. Which control would you use if you needed to make sure the values in two different controls matched? 48. True or False: To test a Web service you must create a windows application or Web application to consume this service? 49. How many classes can a single .NET DLL contain? ~~~~~~~~~~~~~~~~~~~~ ANSWERS: 1. Server-side code runs on the server, Client-side code runs on the client. 2. Server 3. Client...so the user doesn't have to wait for the page to be posted to the server and then returned. 4. Enables the ability to maintain the state of the page and all data within it. 5. Server.Trasfer allows you to pass variables to another page. Server.Redirect just redirects the user to another page. 6. When there is no need for a UI to perform the required task. 8. By default Datasets are disconnected. 9. Any variables that need to be set for the application or session objects. Example: For the path of a image directory Application("ImagePath") = "C:\Images\" 13. VB.NET use the Implements keyword to inherit from another class or interface. C# use : to inherit example Code: VB.NET class myClass Inherits baseClass

7 End class C# class myClass : baseClass 14. An assembly is the collection of all information required by the runtime to execute your application. 15. Inline is mixed with the html, code-behind is separated. Use code-behind. 17. An XML format. Can be used by other platforms so send and receive data to a .NET application 23. Microsoft Intermediate Language 24. You mean the steps of the page lifetime? or that .NET is event driven? 25. Fill method 26. Yes 27. ItemTemplate 28. AlternatingItemTemplate 29. Set the datasource property and call the DataBind method 30. Page...but all .NET objects inherit form the Object Base Class. 31. Session.Contents.Remove 32. You can't (not that I am aware of...since there is no Page level directive to do this) 34. Set AutoGenerateColumns Property to false on the datagrid tag 36. <asp:HyperLinkColumn> 39. SOAP is preferred protocol 40. False 41. Web Services Description Language 42. CurrentPageIndex 43. www.uddi.org 45. DataTextField 46. Only a Get method...no, Set method 47. CompareValidator 48. False, the webservice comes with a test page and it provides HTTP-GET method to test. 49. Many TOUGH ONE ::::  From constructor to destructor (taking into consideration Dispose() and the concept of nondeterministic finalization), what the are events fired as part of the ASP.NET System.Web.UI.Page lifecycle. Why are they important? What interesting things can you do at each? What are ASHX files? What are HttpHandlers? Where can they be configured? What is needed to configure a new extension for use in ASP.NET? For example, what if I wanted my system to serve ASPX files with a *.jsp extension? What events fire when binding data to a data grid? What are they good for? Explain how PostBacks work, on both the client-side and server-side. How do I chain my own JavaScript into the client side without losing PostBack functionality? How does ViewState work and why is it either useful or evil? What is the OO relationship between an ASPX page and its CS/VB code behind file in ASP.NET 1.1? in 2.0? What happens from the point an HTTP request is received on a TCP/IP port up until the Page fires the On_Load event? How does IIS communicate at runtime with ASP.NET? Where is ASP.NET at runtime in IIS5? IIS6? What is an assembly binding redirect? Where are the places an administrator or developer can affect how assembly binding policy is applied? Compare and contrast LoadLibrary(), CoCreateInstance(), CreateObject() and Assembly.Load().

         

8

Interview Questions ASP.NET
1. Describe the role of inetinfo.exe, aspnet_isapi.dll andaspnet_wp.exe in the page loading process. inetinfo.exe is theMicrosoft IIS server running, handling ASP.NET requests among other things.When an ASP.NET request is received (usually a file with .aspx extension),the ISAPI filter aspnet_isapi.dll takes care of it by passing the request tothe actual worker process aspnet_wp.exe. 2. What’s the difference between Response.Write() andResponse.Output.Write()? The latter one allows you to write formattedoutput. 0 3. What methods are fired during the page load? Init() - when the pageis instantiated, Load() - when the page is loaded into server memory,PreRender() - the brief moment before the page is displayed to the user asHTML, Unload() - when page finishes loading. 4. Where does the Web page belong in the .NET Framework class hierarchy?System.Web.UI.Page 5. Where do you store the information about the user’s locale? System.Web.UI.Page.Culture 6. What’s the difference between Codebehind="MyCode.aspx.cs" andSrc="MyCode.aspx.cs"? CodeBehind is relevant to Visual Studio.NET only. 7. What’s a bubbled event? When you have a complex control, like DataGrid, writing an event processing routine for each object (cell, button, row, etc.) is quite tedious. The controls can bubble up their eventhandlers, allowing the main DataGrid event handler to take care of its constituents. 8. Suppose you want a certain ASP.NET function executed on MouseOver overa certain button. Where do you add an event handler? It’s the Attributesproperty, the Add function inside that property. So btnSubmit.Attributes.Add("onMouseOver","someClientCode();") 9. What data type does the RangeValidator control support? Integer,String and Date. 10. Explain the differences between Server-side and Client-side code? Server-side code runs on the server. Client-side code runs in the clients’ browser. 11. What type of code (server or client) is found in a Code-Behind class? Server-side code. 12. Should validation (did the user enter a real date) occur server-side or client-side? Why? Client-side. This reduces an additional request to the server to validate the users input. 13. What does the "EnableViewState" property do? Why would I want it on or off? It enables the viewstate on the page. It allows the page to save the users input on a form. 14. What is the difference between Server.Transfer and Response.Redirect? Why would I choose one over the other? Server.Transfer is used to post a form to another page. Response.Redirect is used to redirect the user to another page or site. 3 15. Can you explain the difference between an ADO.NET Dataset and an ADO Recordset?        A DataSet can represent an entire relational database in memory, complete with tables, relations, and views. A DataSet is designed to work without any continuing connection to the original data source. Data in a DataSet is bulk-loaded, rather than being loaded on demand. There's no concept of cursor types in a DataSet. DataSets have no current record pointer You can use For Each loops to move through the data. You can store many edits in a DataSet, and write them to the original data source in a single operation. Though the DataSet is universal, other objects in ADO.NET come in different versions for different data sources.

16. Can you give an example of what might be best suited to place in the Application_Start and Session_Start subroutines? This is where you can set the specific variables for the Application and Session objects. 17. If I’m developing an application that must accommodate multiple security levels though secure login and my ASP.NET web application is spanned across three web-

9 servers (using round-robin load balancing) what would be the best approach to maintain login-in state for the users? Maintain the login state security through a database. 18. Can you explain what inheritance is and an example of when you might use it? When you want to inherit (use the functionality of) another class. Base Class Employee. A Manager class could be derived from the Employee base class. 19. Whats an assembly? Assemblies are the building blocks of the .NET framework. Overview of assemblies from MSDN 20. Describe the difference between inline and code behind. Inline code written along side the html in a page. Code-behind is code written in a separate file and referenced by the .aspx page. 21. Explain what a diffgram is, and a good use for one? The DiffGram is one of the two XML formats that you can use to render DataSet object contents to XML. For reading database data to an XML file to be sent to a Web Service. 22. Whats MSIL, and why should my developers need an appreciation of it if at all? MSIL is the Microsoft Intermediate Language. All .NET compatible languages will get converted to MSIL. 23. Which method do you invoke on the DataAdapter control to load your generated dataset with data? The .Fill() method 24. Can you edit data in the Repeater control? No, it just reads the information from its data source 25. Which template must you provide, in order to display data in a Repeater control? ItemTemplate 26. How can you provide an alternating color scheme in a Repeater control? Use the AlternatingItemTemplate 27. What property must you set, and what method must you call in your code, in order to bind the data from some data source to the Repeater control? You must set the DataSource property and call the DataBind method. 28. What base class do all Web Forms inherit from? The Page class. 29. Name two properties common in every validation control? ControlToValidate property and Text property. 30. What tags do you need to add within the asp:datagrid tags to bind columns manually? Set AutoGenerateColumns Property to false on the datagrid tag 31. What tag do you use to add a hyperlink column to the DataGrid? <asp:HyperLinkColumn> 32. What is the transport protocol you use to call a Web service? SOAP is the preferred protocol. 33. True or False: A Web service can only be written in .NET? False 34. What does WSDL stand for? (Web Services Description Language) 35. Where on the Internet would you look for Web services? (http://www.uddi.org) 36. Which property on a Combo Box do you set with a column name, prior to setting the DataSource, to display data in the combo box? DataTextField property 37. Which control would you use if you needed to make sure the values in two different controls matched? CompareValidator Control 38. True or False: To test a Web service you must create a windows application or Web application to consume this service? False, the webservice comes with a test page and it provides HTTP-GET method to test. 39. How many classes can a single .NET DLL contain? It can contain many classes.

10

ASPLife cycle
The following are the main ten steps in the ASP.NET page life cycle. 1. Object Initialization A page's controls (and the page itself) are first initialized in their raw form. By declaring your objects within the constructor of your C# code-behind file, the page knows what types of objects and how many to create. Once you have declared your objects within your constructor, you may then access them from any sub class, method, event, or property. However, if any of your objects are controls specified within your ASPX file, at this point the controls have no attributes or properties. It is dangerous to access them through code, as there is no guarantee of what order the control instances will be created (if they are created at all). The initialization event can be overridden using the OnInit method.

Figure 1 - Controls are initialized based on their declaration. 2. Load Viewstate Data After the Init event, controls can be referenced using their IDs only (no DOM is established yet for relative references). At LoadViewState event, the initialized controls receive their first properties: viewstate information that was persisted back to the server on the last submission. The page viewstate is managed by ASP.NET and is used to persist information over a page roundtrip to the server. Viewstate information is saved as a string of name/value pairs and contains information such as control text or value. The viewstate is held in the value property of a hidden <input> control that is passed from page request to page request. As you can see, this is a giant leap forward from the old ASP 3.0 techniques of maintaining state. This event can be overridden using the LoadViewState method and is commonly used to customize the data received by the control at the time it is populated.

Figure 2 - When LoadViewState is fired, controls are populated with the appropriate viewstate data.

11 3. LoadPostData Processes Postback Data During this phase of the page creation, form data that was posted to the server (termed postback data in ASP.NET) is processed against each control that requires it. When a page submits a form, the framework will implement the IPostBackDataHandler interface on each control that submitted data. The page then fires the LoadPostData event and parses through the page to find each control that implements this interface and updates the control state with the correct postback data. ASP.NET updates the correct control by matching the control's unique ID with the name/value pair in the NameValueCollection. This is one reason that ASP.NET requires unique IDs for each control on any given page. Extra steps are taken by the framework to ensure each ID is unique in situations, such as several custom user controls existing on a single page. After the LoadPostData event triggers, the RaisePostDataChanged event is free to execute (see below). 4. Object Load Objects take true form during the Load event. All object are first arranged in the page DOM (called the Control Tree in ASP.NET) and can be referenced easily through code or relative position (crawling the DOM). Objects are then free to retrieve the client-side properties set in the HTML, such as width, value, or visibility. During Load, coded logic, such as arithmetic, setting control properties programmatically, and using the StringBuilder to assemble a string for output, is also executed. This stage is where the majority of work happens. The Load event can be overridden by calling OnLoad.

Figure 3 - The OnLoad event is an ideal location to place logic. 5. Raise PostBack Change Events As stated earlier, this occurs after all controls that implement the IPostBackDataHandler interface have been updated with the correct postback data. During this operation, each control is flagged with a Boolean on whether its data was actually changed or remains the same since the previous submit. ASP.NET then sweeps through the page looking for flags indicating that any object's data has been updated and fires RaisePostDataChanged. The RaisePostDataChanged event does not fire until all controls are updated and after the Load event has occurred. This ensures data in another control is not manually altered during the RaisePostDataChanged event before it is updated with postback data. 6. Process Client-Side PostBack Event After the server-side events fire on data that was changed due to postback updates, the object which caused the postback is handled at the RaisePostBackEvent event. The offending object is usually a control that posted the page back to the server due to a state change (with autopostback enabled) or a form submit button that was clicked. There is often code that will execute in this event, as this is an ideal location to handle event-driven logic. The RaisePostBackEvent event fires last in the series of postback events due to the accuracy of the data that is rendered to the browser. Controls that are

12 changed during postback should not be updated after the executing function is called due to the consistency factor. That is, data that is changed by an anticipated event should always be reflected in the resulting page. The RaisePostBackEvent can be trapped by catching RaisePostBackEvent.

Figure 4 - The RaisePostDataChanged and RaisePostBackEvent events are defined by the IPostBackDataHandler interface. 7. Prerender the Objects The point at which the objects are prerendered is the last time changes to the objects can be saved or persisted to viewstate. This makes the PreRender step a good place to make final modifications, such as changing properties of controls or changing Control Tree structure, without having to worry about ASP.NET making changes to objects based off of database calls or viewstate updates. After the PreRender phase those changes to objects are locked in and can no longer be saved to the page viewstate. The PreRender step can be overridden using OnPreRender. 8. ViewState Saved The viewstate is saved after all changes to the page objects have occurred. Object state data is persisted in the hidden <input> object and this is also where object state data is prepared to be rendered to HTML. At the SaveViewState event, values can be saved to the ViewState object, but changes to page controls are not. You can override this step by using SaveViewState.

Figure 5 - Values are set for controls in OnPreRender. During the SaveViewState event, values are set for the ViewState object. 9. Render To HTML The Render event commences the building of the page by assembling the HTML for output to the browser. During the Render event, the page calls on the objects to render them into HTML. The page

13 then collects the HTML for delivery. When the Render event is overridden, the developer can write custom HTML to the browser that nullifies all the HTML the page has created thus far. The Render method takes an HtmlTextWriter object as a parameter and uses that to output HTML to be streamed to the browser. Changes can still be made at this point, but they are reflected to the client only. 10. Disposal After the page's HTML is rendered, the objects are disposed of. During the Dispose event, you should destroy any objects or references you have created in building the page. At this point, all processing has occurred and it is safe to dispose of any remaining objects, including the Page object. You can override Dispose, as well as Render by setting the appropriate selection in the object parameter

Figure 6 - The Render event will output custom HTML to the browser through the HtmlTextWriter object. The following are the some of the guidelines to create a good ASP.NET application.  Disable session when not using it. This can be done at the application level in the "machine.config" file or at a page level.  The in-proc model of session management is the fastest of the three options. SQL Server option has the highest performance hit.  Minimize the amount and complexity of data stored in a session state. The larger and more complex the data is, the cost of serializing/deserializing of the data is higher (for SQL Server and State server options).  Use Server.Transfer for redirecting between pages in the same application. This will avoid unnecessary client-side redirection.  Choose the best suited session-state provider - In-process is the fastest option.  Avoid unnecessary round-trips to the server - Code like validating user input can be handled at the client side itself.  Use Page.IsPostback to avoid unnecessary processing on a round trip.  Use server controls in appropriate circumstances. Even though are they are very easy to implement, they are expensive because they are server resources. Sometimes, it is easier to use simple rendering or data-binding.  Save server control view state only when necessary.  Buffering is on by default. Turning it off will slow down the performance. Don't code for string buffering - Response.Write will automatically buffer any responses without the need for the user to do it. Use multiple Response.Writes rather than create strings via concatenation, especially if concatenating long strings.  Don't rely on exceptions in the code. Exceptions reduce performance. Do not catch the exception itself before handling the condition. // Consider changing this... try { result = 100 / num;} catch (Exception e) { result = 0;}

14 // to this... if (num != 0) result = 100 / num; else result = 0;  Use early binding in VB.NET and Jscript code. Enable Option Strict in the page directive to ensure that the type-safe programming is maintained.  Port call-intensive COM components to managed code. While doing Interop try avoiding lot of calls. The cost of marshalling the data ranges from relatively cheap (i.e. int, bool) to more expensive (i.e. strings). Strings, a common type of data exchanged for web applications, can be expensive because all strings in the CLR are in Unicode, but COM or native methods may require other types of encoding (i.e. ASCII).  Release the COM objects or native resources as soon as the usage is over. This will allow other requests to utilize them, as well as reducing performance issues, such as having the GC release them at a later point.  Use SQL server stored procedures for data access.  Use the SQLDataReader class for a fast forward-only data cursor.  Datagrid is a quick way of displaying data, but it slows down the application. The other alternative, which is faster, is rendering the data for simple cases. But this is difficult to maintain. A middle of the road solution could be a repeater control, which is light, efficient, customizable and programmable.  Cache data and page output whenever possible.  Disable debug mode before deploying the application.  For applications that rely extensively one external resource, consider enabling web gardening on multiprocessor computers. The ASP.NET process model helps enable scalability by distributing work to several processes, one on each CPU. If the application is using a slow database server or calls COM objects that access external resources, web gardening could be a solution.  Enumerating into collections sometimes is more expensive than index access in a loop. This is because the CLR can sometimes optimize array indexes and bounds checks away in loops, but can't detect them in for each type of code.  JScript .NET allows methods within methods - to implement these in the CLR required a more expensive mechanism which can be much slower, so avoid them by moving inner methods to be just regular methods of the page.  Do a "pre-batch" compilation. To achieve this, request a page from the site.  Avoid making changes to pages or assemblies that are there in the bin directory of the application. A changed page will only recompile the page. Any change to the bin directory will result in recompile of the entire application.  The config file is configured to enable the widest set of features. For a performance boost it is better to tune it to the requirements. Some key points here are:  Encoding - Request/Response - The default is UTF-8 encoding. If the site is completely ASCII, change the option to ASCII encoder.  Session State - By default is ON. If session state is not maintained then the value should be changed to OFF.  ViewState - Default is ON. Turn it off if not being used. If ViewState is being used there are different levels of security that need to be considered which can impact the performance of the application.  AutoEventWireup - Turning off AutoEventWireup means that the page will not try and match up method names to events and hook them up (i.e. Page_Load, etc). Instead, if the application writer wishes to receive them, they need to override the methods in the base class (i.e. override OnLoad for the page load event instead of using a Page_Load method). By doing so, the page will get a slight performance boost by not having to do the extra work itself, but leaving it to the page author.  For efficient debugging Use ASP.NET trace feature instead of Response.Write.

15 Phase Initialize What a control needs to do Method or event to override Initialize settings needed during the Init event (OnInit method) lifetime of the incoming Web request. See Handling Inherited Events. At the end of this phase, the LoadViewState method ViewState property of a control is automatically populated as described in Maintaining State in a Control. A control can override the default implementation of the LoadViewState method to customize state restoration. Process incoming form data and LoadPostData method update properties accordingly. See (if IPostBackDataHandler is Processing Postback Data. implemented) Note Only controls that process postback data participate in this phase. Perform actions common to all requests, such as setting up a database query. At this point, server controls in the tree are created and initialized, the state is restored, and form controls reflect client-side data. See Handling Inherited Events. Raise change events in response to state changes between the current and previous postbacks. See Processing Postback Data.

Load view state

Process postback data

Load

Load event (OnLoad method)

Send postback change notifications

RaisePostDataChangedEvent method (if IPostBackDataHandler is implemented)

Handle postback events

Note Only controls that raise postback change events participate in this phase. Handle the client-side event that RaisePostBackEvent method caused the postback and raise appropriate events on the server. See (if IPostBackEventHandler is implemented) Capturing Postback Events. Note Only controls that process postback events participate in this phase. Perform any updates before the PreRender event output is rendered. Any changes made to the state of the control in the (OnPreRender method) prerender phase can be saved, while changes made in the rendering phase are lost. See Handling Inherited Events. The ViewState property of a control is SaveViewState method automatically persisted to a string object after this stage. This string object is sent to the client and back

Prerender

Save state

16 as a hidden variable. For improving efficiency, a control can override the SaveViewState method to modify the ViewState property. See Maintaining State in a Control. Generate output to be rendered to the client. See Rendering an ASP.NET Server Control. Perform any final cleanup before the control is torn down. References to expensive resources such as database connections must be released in this phase. See Methods in ASP.NET Server Controls. Perform any final cleanup before the control is torn down. Control authors generally perform cleanup in Dispose and do not handle this event.

Render

Render method

Dispose

Dispose method

Unload

UnLoad event (On UnLoad method)

Note To override an EventName event, override the OnEventName method (and call base. OnEventName). The methods and events in the third column are inherited from System.Web.UI.Control, with the following exceptions: LoadPostData and RaisePostDataChangedEvent are methods of the IPostBackDataHandler interface, and RaisePostBackEvent belongs to the IPostBackEventHandler interface. If your control participates in postback data processing you must implement IPostBackDataHandler. If your control receives postback events you must implement IPostBackEventHandler. The CreateChildControls method is not listed in the table because it is called whenever the ASP.NET page framework needs to create the controls tree and this method call is not limited to a specific phase in a control's lifecycle. For example, CreateChildControls can be invoked when loading a page, during data binding, or during rendering.

C__ [1] [1].NET

1. How big is the datatype int in .NET? 32 bits. 2. How big is the char? 16 bits (Unicode). 3. How do you initiate a string without escaping each backslash? Put an @ sign in front of the double-quoted string. 4. What are valid signatures for the Main function?  public static void Main()  public static int Main()  public static void Main( string[] args )  public static int Main(string[] args ) 5. Does Main() always have to be public? No. 6. How do you initialize a two-dimensional array that you don’t know the dimensions of?  int [, ] myArray; //declaration  myArray= new int [5, 8]; //actual initialization 7. What’s the access level of the visibility type internal? Current assembly. 8. What’s the difference between struct and class in C#? 2  Structs cannot be inherited.  Structs are passed by value, not by reference.  Struct is stored on the stack, not the heap.

17 9. Explain encapsulation. The implementation is hidden, the interface is exposed. 10. What data type should you use if you want an 8-bit value that’s signed? sbyte. 11. Speaking of Boolean data types, what’s different between C# and C/C++? There’s no conversion between 0 and false, as well as any other number and true, like in C/C++. 12. Where are the value-type variables allocated in the computer RAM? Stack. 13. Where do the reference-type variables go in the RAM? The references go on the stack, while the objects themselves go on the heap. However, in reality things are more elaborate. 14. What is the difference between the value-type variables and reference-type variables in terms of garbage collection? The value-type variables are not garbage-collected, they just fall off the stack when they fall out of scope, the reference-type objects are picked up by GC when their references go null. 15. How do you convert a string into an integer in .NET? Int32.Parse(string), Convert.ToInt32() (3) 16. How do you box a primitive data type variable? Initialize an object with its value, pass an object, cast it to an object 17. Why do you need to box a primitive variable? To pass it by reference or apply a method that an object supports, but primitive doesn’t. 18. What’s the difference between Java and .NET garbage collectors? Sun left the implementation of a specific garbage collector up to the JRE developer, so their performance varies widely, depending on whose JRE you’re using. Microsoft standardized on their garbage collection. 0 19. How do you enforce garbage collection in .NET? System.GC.Collect(); 3 20. Can you declare a C++ type destructor in C# like ~MyClass()? Yes, but what’s the point, since it will call Finalize(), and Finalize() has no guarantees when the memory will be cleaned up, plus, it introduces additional load on the garbage collector. The only time the finalizer should be implemented, is when you’re dealing with unmanaged code. (5) 21. What’s different about namespace declaration when comparing that to package declaration in Java? No semicolon. Package declarations also have to be the first thing within the file, can’t be nested, and affect all classes within the file. 22. What’s the difference between const and readonly? You can initialize readonly variables to some runtime values. Let’s say your program uses current date and time as one of the values that won’t change. This way you declare public readonly string DateT = new DateTime().ToString(). 23. Can you create enumerated data types in C#? Yes. 5 24. What’s different about switch statements in C# as compared to C++? No fall-throughs allowed. 25. What happens when you encounter a continue statement inside the for loop? The code for the rest of the loop is ignored, the control is transferred back to the beginning of the loop. 26. Is goto statement supported in C#? How about Java? Gotos are supported in C#to the fullest. In Java goto is a reserved keyword that provides absolutely no functionality. 5 27. Describe the compilation process for .NET code? Source code is compiled and run in the .NET Framework using a two-stage process. First, source code is compiled to Microsoft intermediate language (MSIL) code using a .NET Framework-compatible compiler, such as that for Visual Basic .NET or Visual C#. Second, MSIL code is compiled to native code. ---(4) 28. Name any 2 of the 4 .NET authentification methods. ASP.NET, in conjunction with Microsoft Internet Information Services (IIS), can authenticate user credentials such as names and passwords using any of the following authentication methods:  Windows: Basic, digest, or Integrated Windows Authentication (NTLM or Kerberos).  Microsoft Passport authentication  Forms authentication  Client Certificate authentication --29. How do you turn off SessionState in the web.config file? In the system.web section of web.config, you should locate the httpmodule tag and you simply disable session by doing a remove tag with attribute name set to session.

18 <httpModules> <remove name="Session” /> mode =off </httpModules> 0 30. What is main difference between Global.asax and Web.Config? ASP.NET uses the global.asax to establish any global objects that your Web application uses. The .asax extension denotes an application file rather than .aspx for a page file. Each ASP.NET application can contain at most one global.asax file. The file is compiled on the first page hit to your Web application. ASP.NET is also configured so that any attempts to browse to the global.asax page directly are rejected. However, you can specify application-wide settings in the web.config file. The web.config is an XML-formatted text file that resides in the Web site’s root directory. Through Web.config you can specify settings like custom 404 error pages, authentication and authorization settings for the Web site, compilation options for the ASP.NET Web pages, if tracing should be enabled, etc. 3 1. What do you know about .NET assemblies? Assemblies are the smallest units of versioning and deployment in the .NET application. Assemblies are also the building blocks for programs such as Web services, Windows services, serviced components, and .NET remoting applications. (more…) What’s the advantage of using System.Text.StringBuilder over System.String? StringBuilder is more efficient in the cases, where a lot of manipulation is done to the text. Strings are immutable, so each time it’s being operated on, a new instance is created. What is SOAP and how does it relate to XML? 4 The Simple Object Access Protocol (SOAP) uses XML to define a protocol for the exchange of information in distributed computing environments. SOAP consists of three components: an envelope, a set of encoding rules, and a convention for representing remote procedure calls. Unless experience with SOAP is a direct requirement for the open position, knowing the specifics of the protocol, or how it can be used in conjunction with HTTP, is not as important as identifying it as a natural application of XML. Using XSLT, how would you extract a specific attribute from an element in an XML document? Successful candidates should recognize this as one of the most basic applications of XSLT. If they are not able to construct a reply similar to the example below, they should at least be able to identify the components necessary for this operation: xsl:template to match the appropriate XML element, xsl:value-of to select the attribute value, and the optional xsl:apply-templates to continue processing the document. (2) What are the core protocols/standards behind XML Web services? XML (for message format), HTTP and others (for transport), WSDL (Web Service Definition Language, to describe the Web services and define the contract), and UDDI (Universal Description, Discovery and Integration, to dynamically discover and invoke Web services). (3)

19

Interview Questions C#
1. What’s the implicit name of the parameter that gets passed into the class’ set method? Value, and its datatype depends on whatever variable we’re changing. 2. How do you inherit from a class in C#? Place a colon and then the name of the base class. Notice that it’s double colon in C++. 3. Does C# support multiple inheritance? No, use interfaces instead. 0 4. When you inherit a protected class-level variable, who is it available to? Classes in the same namespace. 5. Are private class-level variables inherited? Yes, but they are not accessible, so looking at it you can honestly say that they are not inherited. But they are. 6. Describe the accessibility modifier protected internal. It’s available to derived classes and classes within the same Assembly (and naturally from the base class it’s declared in). 7. C# provides a default constructor for me. I write a constructor that takes a string as a parameter, but want to keep the no parameter one. How many constructors should I write? Two. Once you write at least one constructor, C# cancels the freebie constructor, and now you have to write one yourself, even if there’s no implementation in it. 8. What’s the top .NET class that everything is derived from? System.Object. 0 9. How’s method overriding different from overloading? When overriding, you change the method behavior for a derived class. Overloading simply involves having a method with the same name within the class. 10. What does the keyword virtual mean in the method definition? The method can be overridden. 11. Can you declare the override method static while the original method is non-static? No, you can’t, the signature of the virtual method must remain the same, only the keyword virtual is changed to keyword override. 12. Can you override private virtual methods? No, moreover, you cannot access private methods in inherited classes, have to be protected in the base class to allow any sort of access. 13. Can you prevent your class from being inherited and becoming a base class for some other classes? Yes, that’s what keyword sealed in the class definition is for. The developer trying to derive from your class will get a message: cannot inherit from Sealed class WhateverBaseClassName. It’s the same concept as final class in Java. 14. Can you allow class to be inherited, but prevent the method from being over-ridden? Yes, just leave the class public and make the method sealed. 15. What’s an abstract class? A class that cannot be instantiated. A concept in C++ known as pure virtual method. A class that must be inherited and have the methods over-ridden. Essentially, it’s a blueprint for a class without any implementation. 16. When do you absolutely have to declare a class as abstract (as opposed to free-willed educated choice or decision based on UML diagram)? When at least one of the methods in the class is abstract. When the class itself is inherited from an abstract class, but not all base abstract methods have been over-ridden. 17. What’s an interface class? It’s an abstract class with public abstract methods all of which must be implemented in the inherited classes. 18. Why can’t you specify the accessibility modifier for methods inside the interface? They all must be public. Therefore, to prevent you from getting the false impression that you have any freedom of choice, you are not allowed to specify any accessibility, it’s public by default. 19. Can you inherit multiple interfaces? Yes, why not. 20. And if they have conflicting method names? It’s up to you to implement the method inside your own class, so implementation is left entirely up to you. This might cause a problem on a higher-level scale if similarly named methods from different interfaces expect different data, but as far as compiler cares you’re okay. 21. What’s the difference between an interface and abstract class? In the interface all methods must be abstract; in the abstract class some methods can be concrete. In the interface no accessibility modifiers are allowed, which is ok in abstract classes. 22. How can you overload a method? Different parameter data types, different number of parameters, different order of parameters.

20 23. If a base class has a bunch of overloaded constructors, and an inherited class has another bunch of overloaded constructors, can you enforce a call from an inherited constructor to an arbitrary base constructor? Yes, just place a colon, and then keyword base (parameter list to invoke the appropriate constructor) in the overloaded constructor definition inside the inherited class. 24. What’s the difference between System.String and System.StringBuilder classes? System.String is immutable; System.StringBuilder was designed with the purpose of having a mutable string where a variety of operations can be performed. 25. What’s the advantage of using System.Text.StringBuilder over System.String? StringBuilder is more efficient in the cases, where a lot of manipulation is done to the text. Strings are immutable, so each time it’s being operated on, a new instance is created. 26. Can you store multiple data types in System.Array? No. 27. What’s the difference between the System.Array.CopyTo() and System.Array.Clone()? The first one performs a deep copy of the array, the second one is shallow. Clone() just implements the ICloneable interface. It creates new instance of array holding the same elements, but returns object you have to cast. ArrayCopy() is static helper method. It copies elements from one array to another. The destination array has to be already created with right dimension. You can use this method instead for loop. 28. How can you sort the elements of the array in descending order? By calling Sort() and then Reverse() methods. 29. What’s the .NET datatype that allows the retrieval of data by a unique key? HashTable. 30. What’s class SortedList underneath? A sorted HashTable. 31. Will finally block get executed if the exception had not occurred? Yes. 32. What’s the C# equivalent of C++ catch (…), which was a catch-all statement for any possible exception? A catch block that catches the exception of type System.Exception. You can also omit the parameter data type in this case and just write catch {}. 33. Can multiple catch blocks be executed? No, once the proper catch code fires off, the control is transferred to the finally block (if there are any), and then whatever follows the finally block. 34. Why is it a bad idea to throw your own exceptions? Well, if at that point you know that an error has occurred, then why not write the proper code to handle that error instead of passing a new Exception object to the catch block? Throwing your own exceptions signifies some design flaws in the project. 35. What’s a delegate? A delegate object encapsulates a reference to a method. In C++ they were referred to as function pointers. 36. What’s a multicast delegate? It’s a delegate that points to and eventually fires off several methods. 37. How’s the DLL Hell problem solved in .NET? Assembly versioning allows the application to specify not only the library it needs to run (which was available under Win32), but also the version of the assembly. 38. What are the ways to deploy an assembly? An MSI installer, a CAB archive, and XCOPY command. 39. What’s a satellite assembly? When you write a multilingual or multi-cultural application in .NET, and want to distribute the core application separately from the localized modules, the localized assemblies that modify the core application are called satellite assemblies. 40. What namespaces are necessary to create a localized application? System.Globalization, System.Resources. 41. What’s the difference between // comments, /* */ comments and /// comments? Single-line, multi-line and XML documentation comments. 42. How do you generate documentation from the C# file commented properly with a command-line compiler? Compile it with a /doc switch. 43. What’s the difference between <c> and <code> XML documentation tag? Single line code example and multiple-line code example. 44. Is XML case-sensitive? Yes, so <Student> and <student> are different elements.

21 45. What debugging tools come with the .NET SDK? CorDBG – command-line debugger, and DbgCLR – graphic debugger. Visual Studio .NET uses the DbgCLR. To use CorDbg, you must compile the original C# file using the /debug switch. 46. What does the This window show in the debugger? It points to the object that’s pointed to by this reference. Object’s instance data is shown. 47. What does assert() do? In debug compilation, assert takes in a Boolean condition as a parameter, and shows the error dialog if the condition is false. The program proceeds without any interruption if the condition is true. 48. What’s the difference between the Debug class and Trace class? Documentation looks the same. Use Debug class for debug builds, use Trace class for both debug and release builds. 49. Why are there five tracing levels in System.Diagnostics.TraceSwitcher? The tracing dumps can be quite verbose and for some applications that are constantly running you run the risk of overloading the machine and the hard drive there. Five levels range from None to Verbose, allowing to fine-tune the tracing activities. 50. Where is the output of TextWriterTraceListener redirected? To the Console or a text file depending on the parameter passed to the constructor. 51. How do you debug an ASP.NET Web application? Attach the aspnet_wp.exe process to the DbgClr debugger. 52. What are three test cases you should go through in unit testing? Positive test cases (correct data, correct output), negative test cases (broken or missing data, proper handling), exception test cases (exceptions are thrown and caught properly). 53. Can you change the value of a variable while debugging a C# application? Yes, if you are debugging via Visual Studio.NET, just go to Immediate window. 54. Explain the three services model (three-tier application). Presentation (UI), business (logic and underlying code) and data (from storage or other sources). 55. What are advantages and disadvantages of Microsoft-provided data provider classes in ADO.NET? SQLServer.NET data provider is high-speed and robust, but requires SQL Server license purchased from Microsoft. OLE-DB.NET is universal for accessing other sources, like Oracle, DB2, Microsoft Access and Informix, but it’s a .NET layer on top of OLE layer, so not the fastest thing in the world. ODBC.NET is a deprecated layer provided for backward compatibility to ODBC engines. 56. What’s the role of the DataReader class in ADO.NET connections? It returns a read-only dataset from the data source when the command is executed. 57. What is the wildcard character in SQL? Let’s say you want to query database with LIKE for all employees whose name starts with La. The wildcard character is % , the proper query with LIKE would involve ‘La% ’. 58. Explain ACID rule of thumb for transactions. Transaction must be Atomic (it is one unit of work and does not dependent on previous and following transactions), Consistent (data is either committed or roll back, no “in-between” case where something has been updated and something hasn’t), Isolated (no transaction sees the intermediate results of the current transaction), Durable (the values persist if the data had been committed even if the system crashes right after). 59. What connections does Microsoft SQL Server support? Windows Authentication (via Active Directory) and SQL Server authentication (via Microsoft SQL Server username and passwords). 60. Which one is trusted and which one is untrusted? Windows Authentication is trusted because the username and password are checked with the Active Directory, the SQL Server authentication is untrusted, since SQL Server is the only verifier participating in the transaction. 61. Why would you use untrusted verificaion? Web Services might use it, as well as nonWindows applications. 62. What does the parameter Initial Catalog define inside Connection String? The database name to connect to. 63. What’s the data provider name to connect to Access database? Microsoft.Access. 64. What does Dispose method do with the connection object? Deletes it from the memory. 65. What is a pre-requisite for connection pooling? Multiple processes must agree that they will share the same connection, where every parameter is the same, including the security settings.

22

Caching Overview
Caching is a technique widely used in computing to increase performance by keeping frequently accessed or expensive data in memory. In the context of a Web application, caching is used to retain pages or data across HTTP requests and reuse them without the expense of recreating them. ASP.NET has three kinds of caching that can be used by Web applications:  Output caching, which caches the dynamic response generated by a request.  Fragment caching, which caches portions of a response generated by a request.  Data caching, which caches arbitrary objects programmatically. To support this, ASP.NET provides a full-featured cache engine that allows programmers to easily retain data across requests. Output caching is useful when the contents of an entire page can be cached. On a heavily accessed site, caching frequently accessed pages for even a minute at a time can result in substantial throughput gains. While a page is cached by the output cache, subsequent requests for that page are served from the output page without executing the code that created it. Sometimes it is not practical to cache an entire page - perhaps portions of the page must be created or customized for each request. In this case, it is often worthwhile to identify objects or data that are expensive to construct and are eligible for caching. Once these items are identified, they can be created once and then cached for some period of time. Additionally, fragment caching can be used to cache regions of a page's output. Choosing the time to cache an item can be an interesting decision. For some items, the data might be refreshed at regular intervals or the data is valid for a certain amount of time. In that case, the cache items can be given an expiration policy that causes them to be removed from the cache when they have expired. Code that accesses the cache item simply checks for the absence of the item and recreates it, if necessary. The ASP.NET cache supports file and cache key dependencies, allowing developers to make a cache item dependent on an external file or another cache item. This technique can be used to invalidate items when their underlying data source changes.

Introduction In classic ASP, one of the techniques developers commonly relied on to speed up processing was the use of caching. One could, fairly easily, build their own caching system using Application variables, as highlighted in the FAQ, How can I use Application-level variables to cache information? There were also third-party options, like XCache. The main benefits of caching are performance-related: operations like accessing database information can be one of the most expensive operations of an ASP page's life cycle. If the database information is fairly static, this database-information can be cached. When information is cached, it stays cached either indefinitely, until some relative time, or until some absolute time. Most commonly, information is cached for a relative time frame. That is, our database information may be fairly static, updated just a few times a week. Therefore, we might want to invalidate the cache every other day, meaning every other day the cached content is rebuilt from the database. While caching in classic ASP was a bit of a chore, it is quite easy in ASP.NET. There are a number of classes in the .NET Framework designed to aid with caching information. In this article, I will explain how .NET supports caching and explain in detail how to properly incorporate each supported method into Web-based applications. Caching Options in ASP.NET ASP.NET supports three types of caching for Web-based applications:  Page Level Caching (called Output Caching)

23   Page Fragment Caching (often called Partial-Page Output Caching) Programmatic or Data Caching

We'll look at each of these options, including how, and when, to use each option to increase your site's performance! Output Caching Page level, or output caching, caches the HTML output of dynamic requests to ASP.NET Web pages. The way ASP.NET implements this (roughly) is through an Output Cache engine. Each time an incoming ASP.NET page request comes in, this engine checks to see if the page being requested has a cached output entry. If it does, this cached HTML is sent as a response; otherwise, the page is dynamically rendered, it's output is stored in the Output Cache engine. Output Caching is particularly useful when you have very static pages. For example, the articles here on 4GuysFromRolla.com are very static. The only dynamic content is the banners, the dynamic selection being performed on a separate ad server. Hence, the articles on 4Guys would be prime candidates for Output Caching. Output caching is easy to implement. By simply using the @OuputCache page directive, ASP.NET Web pages can take advantage of this powerful technique. The syntax looks like this: <% @OutputCache Duration="60" VaryByParam="none" % >

The Duration parameter specifies how long, in seconds, the HTML output of the Web page should be held in the cache. When the duration expires, the cache becomes invalid and, with the next visit, the cached content is flushed, the ASP.NET Web page's HTML dynamically generated, and the cache repopulated with this HTML. The VaryByParam parameter is used to indicate whether any GET (QueryString) or POST (via a form submit with method="POST") parameters should be used in varying what gets cached. In other words, multiple versions of a page can be cached if the output used to generate the page is different for different values passed in via either a GET or POST. The VaryByParam is a useful setting that can be used to cache different "views" of a dynamic page whose content is generated by GET or POST values. For example, you may have an ASP.NET Web page that reads in a Part number from the QueryString and displays information about a particular widget whose part number matches the QueryString Part number. Imagine for a moment that Output Caching ignored the QueryString parameters altogether (which you can do by setting VaryByParam="none"). If the first user visited the page with QueryString /ProductInfo.aspx?PartNo=4, she would see information out widget #4. The HTML for this page would be cached. The next user now visits and wished to see information on widget #8, a la /ProductInfo.aspx?PartNo=8. If VaryByParam is set to VaryByParam="none", the Output Caching engine will assume that the requests to the two pages are synonymous, and return the cached HTML for widget #4 to the person wishing to see widget #8! To solve for this problem, you can specify that the Output Caching engine should vary its caches based on the PartNo parameter by either specifying it explicitly, like VaryByParam="PartNo", or by saying to vary on all GET/POST parameters, like: VaryByParam="*". Partial-Page Output Caching More often than not, it is impractical to cache entire pages. For example, you may have some content on your page that is fairly static, such as a listing of current inventory, but you may have other information, such as the user's shopping cart, or the current stock price of the company, that you wish to not be cached at all. Since Output Caching caches the HTML of the entire ASP.NET Web page, clearly Output Caching cannot be used for these scenarios: enter Partial-Page Output Caching. Partial-Page Output Caching, or page fragment caching, allows specific regions of pages to be cached. ASP.NET provides a way to take advantage of this powerful technique, requiring that the part(s) of the page you wish to have cached appear in a User Control. One way to specify that the contents of a User Control should be cached is to supply an OutputCache directive at the top of the User Control. That's it! The content inside the User Control will now be cached for the specified period, while the ASP.NET Web page that contains the User Control will continue to serve dynamic

24 content. (Note that for this you should not place an OutputCache directive in the ASP.NET Web page that contains the User Control - just inside of the User Control.) Now that we've tackled Output Caching and Fragment Caching, there is still one more caching technique worth discussing: Data Caching. In Part 2 we'll examine what, exactly, Data Caching is and how you can use it to improve the performance of your ASP.NET Web pages. We'll also examine a really cool, real-world caching demo! In Part 1 we looked at how to use Output Caching and Fragement Caching of an ASP.NET Web page. These two techniques cached either the full HTML output of an ASP.NET Web page, or a portion of the HTML output of an ASP.NET Web page (by caching the HTML output of a User Control). In this part, we'll examine Data Caching, which is an in-memory cache used for caching objects. Data Catching Sometimes, more control over what gets cached is desired. ASP.NET provides this power and flexibility by providing a cache engine. Programmatic or data caching takes advantage of the .NET Runtime cache engine to store any data or object between responses. That is, you can store objects into a cache, similar to the storing of objects in Application scope in classic ASP. (As with classic ASP, do not store open database connections in the cache!) Realize that this data cache is kept in memory and "lives" as long as the host application does. In other words, when the ASP.NET application using data caching is restarted, the cache is destroyed and recreated. Data Caching is almost as easy to use as Output Caching or Fragment caching: you simply interact with it as you would any simple dictionary object. To store a value in the cache, use syntax like this: Cache["foo"] = bar; // C# Cache("foo") = bar ' VB.NET To retrieve a value, simply reverse the syntax like this: bar = Cache["foo"]; // C# bar = Cache("foo") ' VB.NET Note that after you retrieve a cache value in the above manner you should first verify that the cache value is not null prior to doing something with the data. Since Data Caching uses an in-memory cache, there are times when cache elements may need to be evicted. That is, if there is not enough memory and you attempt to insert something new into the cache, something else has gotta go! The Data Cache engine does all of this scavenging for your behind the scenes, of course. However, don't forget that you should always check to ensure that the cache value is there before using it. This is fairly simply to do - just check to ensure that the value isn't null/Nothing. If it is, then you need to dynamically retrieve the object and restore it into the cache. For example, if we were storing a string myString in the cache whose value was set from some method named SetStringToSomething(), and we wanted to read the value of myString from the cache, we'd want to: 1. Read the myString from the cache: str = Cache("myString") 2. Ensure that str wasn't null/Nothing. If it was, we'd want to get the value of str from SetStringToSomething(), and then put it in the cache, like so: 'Try to read the cache entry MyString into str str = Cache("myString") 'Check if str is Nothing If str is Nothing then 'If it is, populate str from SetStringToSomething() str = SetStringToSomething() 'Now insert str into the cache entry myString Cache("myString") = str

25 End If Besides using the dictionary-like key/value assignment, as shown in the example above, you can also use the Insert or Add method to add items to the cache. Both of these methods are overloaded to accommodate a variety of situations. The Add and the Insert methods operate exactly the same except the Add method returns a reference to the object being inserted to the cache. Because of the similarity of the two methods, I will concentrate on the Insert method. Note that the Insert method allows you to simply add items to the cache using a key and value notation as well. For example to simply add an instance of the object bar to the cache named foo, use syntax like this: Cache.Insert("foo", bar); // C# Cache.Insert("foo", bar) ' VB.NET (Note that this is synonymous to using the Cache("foo") = bar syntax we looked at earlier.) Note that with inserting items into the Data Cache using the Cache(key) = value method or the Cache.Insert(key, value) we have no control over when (if ever) the items are evicted from the cache. However, there are times when we'd like to have control over when items leave the cache. For example, perhaps we want to have an inserted item in the cache to only live for n seconds, as with Output Caching. Or perhaps we'd like to have it exit the cache n seconds after it's last accessed. With Data Caching, you can optionally specify when the cache should have a member evicted. Additionally, you can have an item evicted from the cache when a file changes. Such an eviction dependency is called a file dependency, and has many real-world applications, especially when working with XML files. For example, if you want to pull data out of an XML file, but you don't want to constantly go to disk to read the data, you can tell the ASP.NET caching engine to expire the cached XML file whenever the XML file on disk is changed. To do this, use the following syntax: Cache.Insert("foo", bar, new CacheDependancy(Server.MapPath("BarData.xml"))) By using this syntax, the cache engine takes care of removing the object bar from the cache when BarData.xml file is changed. Very cool! There are also means to have the inserted cache value expire based on an interval, or at an absolute time, as discussed before. For more information on these methods, consult the documentation for the Cache.Insert method. A Cached XML File Example Hopefully by now you'll agree that one of the most interesting and useful uses of the Cache.Insert method involves using the version of the method that takes advantage of the CacheDependancy parameter. By using this parameter, developers can create web pages that contain "semi-static" data. In other words, the rendering of the pages is based on configuration-like data which can be stored in an XML file (or anywhere really, I just like to use XML for this type of data). But I digress. The point is, why go back to disk or, worse yet, a SQL Server just to retrieve data that only changes periodically when I can have it done automatically. To illustrate this point, I've created a simple example. In this example, an XML file is used to house data that is used to create a simple navigation control. Each <Destination> element contains a <LinkText> and a <NavigateURL> tag to house the appropriate data. Below is a section of this XML file: <Destinations> <Destination> <LinkText> Bazquirk </LinkText> <NavigateURL> Bazquik.aspx </NavigateURL> </Destination> <Destination> <LinkText>Blah</LinkText> <NavigateURL>Blah.aspx</NavigateURL> </Destination> .... In a User Control a DataList control is used to bind the XML data using a HyperLink control. The Text property is set to the values contained in the <LinkText> tags. The HyperLink control's NavigateUrl property is set to the values contained in the <NavigateURL> tags. A Label control is

26 used in the code behind class to output the time the cache is updated. (All of the code, and the output, can be seen at this live demo!) A simple method, BindDestinations, does the work of binding the XML data to the DataList control. This method is called everytime the Page_Load event is fired. A DataSet object is created and then filled with the XML data by using the DataSet's ReadXML method. In the BindDestinations method, an attempt is made to pull the data out of the Cache object. If nothing is found, as is the case when the XML file is changed, the data is re-read from the XML file and re-inserted into the Cache object. The time this occurs is also displayed via the lblTime Label control. Finally, the data is bound to the DataList control and displayed. In this manner, the data of the page is cached until it needs to be refreshed (i.e., the XML file data is changed). Neat! Conclusion The .NET caching services will prove to be one of the most powerful ways to squeeze performance out of new Web-based applications. Whether using Output Caching, Fragment Caching, or the Cache object directly, your web applications will see dramatic improvements in throughput and scalability through the technique of caching expensive dynamic data computations. Caching-XML-Trace Introduction Data caching was introduced with Internet Information Server (IIS) in order to optimize the transfer of Web pages and speed up the user’s access to these pages. ASP 2.x did not have any native caching ability and simply made use of the caching provided by IIS.Third-party utilities could also be used to increase the caching abilities of ASP 2.x and provide a greater level of control over the IIS cache. Caching is now available natively within ASP.NET and has three new faces: utput, data, and fragment caching. Each of these methods provides new and powerful ethods of optimizing the utilization of system resources and increasing pplication performance. utput caching is more like the old method of caching provided by IIS; a ingle page is stored within memory for a small period of time, for any reason hat the programmer sees fit.While this model is troublesome in some instances, it can be helpful to the end-user at times.This allows for faster access to pages hat contain some dynamic content without having to regenerate the entire page. ragment caching is an innovation to output caching; it enables the programmer to determine which parts of a page should be cached for future reference.This is done by breaking the code into separate user controls and then caching the control.This new feature greatly expands on our caching options.Data caching enables the programmer to have full control over the caching at the object level.You can define which objects and which areas are to be cached and for what length of time, as you see fit.This detailed level of control enables you to save any object to memory that you wish, in order to speed up access to that object. In this chapter, we are going to go over the three methods of caching that are available in ASP.NET.We will also discuss how and why to use each method and in what situations each method should be used.The options and parameters for each method will be discussed and illustrated. By using this information, you can greatly increase the performance of your application.This objective is key in creating an application that fits well with the needs of your users.

Caching Overview Caching is a technique used in various aspects of computing to increase performance by decreasing access times for obtaining data.This is accomplished by retaining frequently accessed data within memory.This technique is used by many operating systems to cut down on the number of times that a hard drive must be accessed or a network connection utilized, by storing the needed data in the system’s memory. It is also used by some databases to store data retrieved from queries that may be needed again later.As it pertains to a Web application, data is retained from across multiple HTTP requests, and can then be reused without incurring additional access times that would normally be necessary to recreate the data. ASP.NET makes available three different types of caching, which, when used properly, can greatly increase the overall performance of your application.These types are as follows: _ Output Caching _ Fragment Caching _ Data Caching We will go into detail in this chapter on each of these caching types, but they all are based off of the basic concept of saving all or a portion of the data generated by your application, with the purpose of presenting the same data again at a later time. Output caching basically caches the entire content of an output Web page. This can be very useful when the content of your pages changes very little.

27 Programmers familiar with ASP 2.x should be familiar with this concept, as it was the only available caching method for ASP.This method provides the greatest performance increase, but can only be used when nothing on the output page is expected to change within the valid timeframe of the cache. Fragment caching, which is new in ASP.NET, allows for the caching of portions of your output page.This is an excellent improvement in caching technique, and is best used when your application’s output page has content that changes constantly in addition to content that changes very little.While this method does not provide as much of a performance increase as output caching, it does increase performance for applications that would formerly have been unable to use any caching at all due to the strict requirements of output caching. Data caching, also new in ASP.NET, provides the ability to cache individual objects. Placing objects into the cache in this manner is similar to adding items to a dictionary. By using a simple dictionary-style interface, this method makes for an easy-to-use temporary data storage area while conserving server resources by releasing memory as cached objects expire. A major consideration in planning your caching strategy is the appropriate utilization of server resources.There is a trade-off when it comes to the use of any kind of caching, in that for every item cached, less memory is available for other uses.While output caching provides the greatest performance increase, it also utilizes more memory than caching a few objects using data caching. On the other hand, due to the overhead required to store multiple objects by using data caching, it may be more logical to cache a portion of the output page by using fragment caching. Suggested uses are listed in Table 6.1; however, the best caching method for your specific application is dependant upon your output. www.syngress.com Table 6.1 Suggested Uses of Caching Types Situation Suggested Caching Type 1.The generated page generally stays the same, but there are several tables shown within the output that change regularly. 2.The generated page constantly changes, but there are a few objects that don’t change very often. 3.The generated page changes every few hours as information is loaded into a database through automated processes. 1.Use Fragment Caching in this situation. Cache the portions of the page that remain somewhat static, while dynamically generating the table contents. Also consider using Data Caching for storing some individual objects. 2.Use Data Caching for the objects. 3.Use Output Caching and set the duration to match the frequency of the data changes. Components of an XML Document In this section, we will introduce the major components of an XML document. An XML document contains a variety of constructs. Some of the frequently used ones are as follows: _ Declaration Each XML document may have the optional entry <?xml version=“1.0”?>. This standard entry is used to identify the document as an XML document conforming to the W3C (World Wide Web Consortium) recommendation for version 1.0. _ Comment An XML document may contain html-style comments like <!--Catalog data -->. _ Schema or Document Type Definition (DTD) In certain situations, a schema or DTD may precede the XML document. A schema or DTD contains the rules about the elements of the document. For example, we may specify a rule like “A product element must have a ProductName, but a ListPrice element is optional.”We will discuss schemas later in the chapter. _ Elements An XML document is mostly composed of elements.An element has a start-tag and end-tag. In between the start-tag and end-tag, we include the content of the element.An element may contain a piece of character data, or it may contain other elements. For example, in the Catalog1.xml, the Product element contains three other elements: ProductId,ProductName, and ListPrice. On the other hand, the first ProductName element contains a piece of character data like Shimano Calcutta. _ Root Element In an XML document, one single main element must contain all other elements inside it.This specific element is often called the root element. In our example, the root element is the Catalog element. The XML document may contain many Product elements, but there must be only one instance of the Catalog element. _ Attributes Okay, we agree that we didn’t tell you the whole story in our first example. So far, we have said that an element may contain other elements, or it

28 may contain data, or both. Besides these, an element may also contain zero or more so-called attributes. An attribute is just an additional way to attach a piece of data to an element. An attribute is always placed inside the start-tag of an element, and we specify its value using the “name=value” pair protocol. Let us revise our Catalog1.xml and include some attributes to the Product element. Here, we will assume that a Product element will have two attributes named Type and SupplierId.As shown in Figure 8.5, we will simply add the Type=“Spinning Reel” and SupplierId=“5” attributes in the first product element. Similarly, we will also add the attributes to the second product element. Table 9.2 Sections in a Trace Page Sections Description Request Details Describes information pertaining to the request (e.g., SessionID, Encoding, and time of request). Trace Information Contains detailed information about the application currently running. Trace information is displayed in this section. Control Tree Displays information about controls used in a page and the size of the Viewstate hidden field. Cookies Collection Displays the cookie set by the page and its value. Headers Collection Displays HTTP header information like content length and user agent. Forms Collection Displays the name of controls in a page and its value. Server Variables Displays the environment variables on the server side. Notice that our Trace message is written under the “Trace Information” section. The Trace class contains the following members (Table 9.3 and Table 9.4). Table 9.3 Properties in the Trace Class Property Description IsEnabled Indicates whether tracing is enabled for the current request. TraceMode Sets the trace mode: sortByCategory or sortByTime. Methods in the Trace Class Methods() Description Warn Writes the trace information in red. Write Writes the trace information. Solutions Fast Track Handling Errors @ There are four main categories of programming errors: syntax, compilation, runtime, and logic errors. @ Visual Studio .NET IDE provides help for detecting syntax errors. Runtime errors can be handled using structured and unstructured error handling mechanisms. @ Structured handling using the Try-Catch-Finally statement is the recommended mode for handling runtime errors in .NET. Page Tracing @ The Trace class provides tracing capability. @ Turning tracing on and off is easy. @ Trace information can be grouped into multiple categories for easier viewing and it can be written into log files, viewable using the Event Viewer. @ Tracing can be done at the page level or at the application level. www.syngress.com

29 Debugging ASP.NET • Chapter 9 439 Using Visual Studio .NET Debugging Tools @ Programmers can use the Visual Studio .NET IDE to set breakpoints in their application. @ Breakpoints allow you to examine variables and trace the execution flow of your application. @ The Object Browser and Class Viewer provide quick reference to the various class libraries. Q: Is the Try-Catch-Finally block available in C# as well? A:Yes, the Try-Catch-Finally block is available in both VB.NET and C#. Q: Can I use both structured and unstructured error handling within a function/ subroutine? A: No, you cannot use both error handling mechanisms at the same time. It is recommended you use structured error handling in .NET. Q: When I try to run my ASP.NET application in VS.NET, I encounter this error message “Error while trying to run project: Unable to start debugging on the Web server.The project is not configured to be debugged.”Why does this occur? A: This is caused by the setting of the debug attribute within the <compilation> element. During development stage, set the value of the debug attribute to “true.” Remember, however, to set this attribute to “false” when you are ready to deploy your application. www.syngress.com Frequently Asked Questions The following Frequently Asked Questions, answered by the authors of this book, are designed to both measure your understanding of the concepts presented in this chapter and to assist you with real-life implementation of these concepts. To have your questions about this chapter answered by the author, browse to www.syngress.com/solutions and click on the “Ask the Author” form. 440 Chapter 9 • Debugging ASP.NET Q: I noticed during tracing that the Session ID for my application changes when I refresh my page or when I do a postback.Why is this happening? A: For performance reasons, the .NET Framework does not maintain state between the Web server and the Web browser automatically, hence the Session ID is always different between submissions. However, when the Session object is used or when the Session_OnStart() event is added to the global.asax file, the Session ID would be maintained between postbacks. Frequently Asked Questions(Web Services) Q:Why replace COM objects with Web Services? A:Web Services have a platform neutral interface.This enables Web Services to be easily utilized by multiple clients on different platforms developed with different programming languages. Note that existing COM components can be wrapped by Web Services. Q: Can I create access to Web Services from a standard ASP page? A:Yes, you can; however, you might want to look into Microsoft’s SOAP toolkit. Q: How do I know I need Web Services? A: If you have data that is needed by various customers (different departments, different levels of management, vendors, industry partners, consumers and so on) and getting to that data is hindered or prevented by issues involving platform, programming language, legacy hardware or other types of incompatibility, developing Web Services can help. Q: What area of development are Web Services best for? A: I believe that Web Services development like COM development will remain in the hands of the middle tier programmer.Traditionally this was accomplished with C++ and VB programmers, however simple data access type components may be developed by intermediate and advanced ASP developers. While this might still be the case,ASP.NET developers need a firmer grasp of programming with a strongly typed compiled language then their ASP predecessors.This makes the ASP.NET developer more of a middle tier programmer and less of a front-end Web developer. Since building and deploying Web classes and Web Services are relatively easy with VS.NET as compared to traditional COM development. I think the proportion of components built by the ASP developer (using ASP.NET) will be larger than it has been in the past. Q: Is it possible to try out Web Services using only my local computer?

30 A:Yes, it is. Using the WSDL.exe command line tool, you can point to any Web server.This is even easier with the VS.NET UI. Simply right-click Web references, then select any Web service from the UDDI directory or your local machine, or simply type the URL of a disco file on any server.You can easily generate a WSDL proxy and use it as long as you are connected to the Internet. Q: I’m currently in the process of migrating.What considerations should I take with my existing COM components? A: Here are a few things to consider: _ Who is the customer? If the customer is only within the intranet and there are no external customers in the foreseeable future, an existing DCOM infrastructure needn’t be changed. _ What type of clients do I have? If the client is a desktop application, switching to Web Services would require updating the client, which may include updating the OS, and possibly the hardware so that the client has enough memory to host the .NET Framework. _ Will I need to support Mobile devices in the near future? Using the .NET Mobile Framework to access Web Services is as simple as it is with .NET. Updating the existing clients to .NET will make adding future clients simple and cost-effective.

Choosing Between User Controls and Custom Controls
ASP.NET provides two models of creating Web controls – user controls and custom controls. This article assumes basic knowledge of the two models and will not provide detailed information on writing controls. Instead, this article will present the reasons why one should choose one model over the other. User Controls User controls are authored in the same fashion as a standard Web Form. This makes user controls relatively easy to create, especially when aided by a visual designer such as Visual Studio .NET. Hence, given the same WYSIWYG and declarative environment as an ASP.NET page, user controls can be created with or without a code-behind file, and can handle their own events independent of the parent page. Design-time support for user controls, however, is limited. User controls are represented only by a dull placeholder and properties cannot be set via the Properties window. Also, user controls cannot be added to the Toolbox; sharing of user controls is achieved through placing the necessary user control files in each Web application directory. Custom Controls Unlike user controls which are authored in the same fashion as a Web Form, custom controls are compiled and distributed in binary format. Control authors must create their own classes which subclass from System.Web.UI.Control either directly or indirectly by subclassing another control. Custom controls are created without the aid of a designer and require the author to overcome a much steeper learning curve. On the other hand, custom controls provide strong designer-time support. Once compiled, custom controls can be added to the Toolbox and be used the same fashion as the other controls that ship with the .NET SDK such as the TextBox and Button controls. Furthermore, custom controls can expose properties which can easily be set by page developers using the Properties window of the visual designer. Finally, custom controls allow authors to extend or modify the functionality provided by existing controls. Performance With regards to performance, neither has a distinct advantage over the other. Both derive from System.Web.UI.Control and both are compiled into assemblies. Hence, performance is not a factor to consider when choosing between user and custom controls. Conclusion In conclusion, the single most important factor is how the control will be used – will the control be application specific or generic and redistributable? If the control is application specific and contains a lot of static layout, such as a site header and footer, a user control would make sense. If the

31 control is generic, redistributable, and contains dynamic layout, such as the server controls that ship with the .NET SDK, then a custom control would be more suitable. Summary Ease of Authoring – User controls win hands down Design-Time Support – Custom controls can be added to the toolbox, can expose simple or complex properties, and can be bound to a data source Deployment – Custom controls are compiled into binary format and are easily deployed across applications Layout – User controls suite static layout while custom controls are better suited for complex layouts Performance – Equal. Consider the other factors.

collectionBase
Introduction System.Collections namespace has several collection type classes like Stack, Queue, Dictionary, Collectionbase,Arraylist etc; each one is out there to meet specific development requirements. In the snippet we will not get into the nuts and bolts of all the collection type but we will restrict ourselves to CollectionBase type. Built-in functionality The CollectionBase class has implementations for the Clear method and the Count property, and a List property, which it uses for the internal storage and organization. Other methods, such as Add and Remove, as well as the Item property, require implementation. This sample uses two classes: Author and Authors. Authors inherit from System.Collections.CollectionBase in order to create a type-safe collection to manage multiple Author instances. Author Class -----------using System; namespace collection { public class Author { private Int16 vid; private string vname; private string vtitle; public Author(Int16 id,string name,string title ) { this.ID=id; this.Name=name; this.Title=title; } public Int16 ID { get{return vid;} set{vid=value;} }

32 public string Name { get{return vname;} set{vname=value;} } public string Title { get{return vtitle;} set{vtitle=value;} } }

Authors Class ------------public class Authors:System.Collections.CollectionBase { public Authors() { } //Add author to collection public void Add(Author oAuthor) { List.Add(oAuthor); } public Author Item(int Index) { // explicitly cast to the Author type return (Author) List[Index]; } }} How To Use? private void Test() { //Create instance of collection Authors oCol=new Authors(); //Add authors to collection oCol.Add(new Author(1,"David","CollectionBase class")); oCol.Add(new Author(2,"Gentry","Imaging sysyems")); oCol.Add(new Author(3,"Peter",".net Framework")); Debug.WriteLine("ID " +" Name " + " Title "); //Print results foreach(Author obj in oCol) {Debug.WriteLine(obj.ID + " " +obj.Name+" " +obj.Title);} } Results This is a proof that author objects have been added to the collection. ID Name Title 1 David CollectionBase class 2 Gentry Imaging sysyems 3 Peter .net Framework

33

COMInteroperability
The .NET platform is a major shift from the earlier COM technology, which dominated the Microsoft world for many years. Although new development may be carried out using .NET, there will be a need to reuse some of the functionality existing in the form of COM components. In this article, I examine some COM and .NET interoperability techniques. COM to .NET: A shift in technology Though a COM component and a .NET assembly share the same .dll extension, things are not the same internally. A .NET assembly does not need information about it to be stored in the registry, but instead holds the type information in the form of metadata. This metadata is present within the assembly itself. Further, a .NET assembly is not based on the IUnknown interface, which is an interface exposed by all COM objects. The code that exists in the form of COM is known as unmanaged code, because the execution of this code is not managed by the common language runtime (CLR). Code written with the .NET Framework is managed by the CLR and is hence known as managed code. It is impractical to rewrite every piece of code in .NET, because a lot of functionality exists in COM form. Moreover, more code exists in COM today than .NET, because .NET is a relatively new platform. From this fact arises the need for interoperating between COM and .NET. The .NET Framework has dedicated a namespace for this purpose. The System.Runtime.InteropServices namespace provides classes that can be used for accessing COM objects from .NET. We will begin by calling COM objects from .NET—a common necessity. Calling COM objects from .NET The code within a COM object is not executed by the CLR. The mechanism followed to expose a COM object to .NET is as follows: The COM object is encapsulated within a wrapper class, and this exposes the COM object as a .NET assembly to the CLR. This wrapper is known as the runtime callable wrapper (RCW). This process is illustrated in Figure A. Figure A

Runtime callable wrapper (RCW) This wrapper class (RCW) acts as a bridge between the unmanaged and managed code, and all operations are routed through this class. That's enough theory; let’s take a quick look at how this can be done. The entire process of generating an RCW is automatically handled by Visual Studio.NET. Interoperability using Visual Studio.NET Let’s assume we need to utilize Microsoft Excel in our application. We can do so by accessing the Project menu and References and choosing Microsoft Excel Object Library from the COM tab, as shown in Figure B.

34

Choosing the Microsoft Excel Object Library As soon as we do so, Visual Studio.NET automatically generates an RCW. The naming convention followed is Interop.COMObject.dll. In this case, the RCW is called Interop.Excel.dll, which is referenced in the .NET application; we can instantiate and use Excel objects in code. The same is true for any custom COM component authored by you. The only requirement is that the COM component must be registered. You can also use ActiveX Controls from .NET. To do so, right-click on the Toolbox and select Customize Toolbox. From the COM Components tab, select (for example) Microsoft ListView Control and check the checkbox beside it (see Figure C). The Listview control will be added to the Toolbox.

35 Figure C

Selecting the Microsoft ListView Control

As soon as you place the Listview control on the form, Visual Studio.NET generates the RCW for the ActiveX Control. The naming convention followed is AxInterop.ActiveXControl.dll, so in this case it is called AxInterop.MSComctlLib.dll. Interoperability without Visual Studio.NET Suppose you are not using Visual Studio.NET. Another way of achieving the same result is to use the .Net Framework tool called the Type Library Importer (tlbimp.exe). This tool can be used to convert type definitions in a COM library into a .NET assembly. For example, if you have a COM DLL named MyCOMComponent.dll, you can build an RCW for it as follows: Tlbimp MyCOMComponent.dll /out:MyRCW.dll In the case of ActiveX Controls, you can use the .NET Framework tool called the ActiveX Importer to convert the type definitions in an ActiveX Control into a Windows Forms Control. It can be used from the command line as follows: Aximp MyOCX.ocx Wrap it up If you are wondering how Visual Studio.NET or the command-line tools generate these wrappers, here is the key. The .NET Framework Class Library has a class called TypeLibConverter (System.Runtime.IneropServices.TypeLibConverter), which exposes a method called ConvertTypeLibToAssembly that can be used to write your own tool; this tool generates an RCW. The same is true for the ActiveX controls—the AxImporter Class (System.Windows.Forms.Design.AxImporter) can be used to generate RCWs for ActiveX controls. Memory management One of the main architectural differences between .NET and COM is memory management. The CLR provides automatic memory management by means of a garbage collector that manages the allocation and release of memory. This is done periodically, so an object is not immediately destroyed when it goes out of scope or when it is set to Nothing (Visual Basic.NET, the same as null in C#).

36 When an RCW goes out of scope or is set to Nothing, the object is not destroyed immediately, and the corresponding COM object will also reside in memory—which might not be desirable. In such situations, steps should be taken to clean up the memory. You can do so by calling the garbage collector, by calling the System.GC.Collect method, or—the preferred way—by calling the Marshal.ReleaseComObject method on the RCW. Apart from providing backward compatibility, the .NET framework also provides forward compatibility, which means that it is possible to expose a .NET assembly so that it can be consumed from COM. We will now shift our focus to this aspect of utilizing .NET assemblies from COM. Calling .NET assemblies from COM Let us now see how we can utilize .NET assemblies from COM (see Figure A). Figure A

Utilizing .NET assemblies from COM

Similar to the process of calling COM Objects from .NET, here we have a wrapper class over a .NET Assembly, which can be accessed from a COM-based application. This wrapper class is known as the “COM Callable Wrapper” (CCW). Let’s see how we can do this using Visual Studio.NET. Start Visual Studio.NET and start a new project of type Class Library. Call it DotnetForCOM (for example). Add a default constructor to the class and some public methods, which you want available in COM. Once you have this ready, right-click on the project in the Solution Explorer and select Properties to bring up the project property pages. Here, choose Configuration properties and select the Build option. You will be presented with the screen displayed in Figure B. Figure B

37 Working with property pages

Check the checkbox Register For COM Interop (in Figure B). Now, when you build this project, the .NET assembly is automatically registered for COM Interop. You will now be able to use this assembly from COM, for example from Visual Basic 6.0. If you start a new Visual Basic 6 project and choose the Project Menu and References, this .NET assembly is available to reference from COM (see Figure C). Figure C

Visual Basic project references Once this is done, you can access the functionality provided by the .NET assembly from Visual Basic 6. Working outside Visual Studio.NET Let us now see what we need to do if we are not using Visual Studio.NET. There are certain requirements for a .NET assembly to be exposed to COM. Provide a default constructor Firstly, .NET assembly must provide a default constructor. This is because COM Clients do not support parameterized constructors available in .NET, so make sure you provide a default constructor to the class. You can have constructors with parameters, as well, along with the default constructor, but the default constructor needs to be present to instantiate the .NET assembly from COM client. Generating type libraries Generate the type library for the .NET assembly, and make entries in the System Registry. There are two ways to achieve this: Use the Type Library Exporter tool provided with the .NET Framework SDK to generate the type library for the .NET assembly. Then register the type library using the Assembly Registration tool. Tlbexp test.dll /out:test.tlb Regasm test.dll Directly generate the type library, and register it using Regasm. Regasm test.dll /tlb:test.tlb The .NET Assembly must have a Strong Name and must reside in the Global Assembly Cache. For this purpose you will need to generate a key for the Assembly using the Strong Name tool (Sn.exe). Once this is done, you can add the assembly to the Global Assembly Cache (GAC) using the Global Assembly Cache Tool (Gacutil.exe). You can add an assembly to the GAC using: gacutil –I SampleAssembly.dll Once this has been done, you will be able to add a reference to the .NET assembly from COM and

38 use it. The COM Callable Wrapper (CCW) is generated at the time when a call is given to the .NET Assembly from COM; it acts as a bridge between the managed and unmanaged boundaries.

Concept
Web garden: An application pool that uses more than one worker process is called a Web garden. The worker processes in a Web garden share the requests that arrive for that particular application pool. If a worker process fails, another worker process can continue to process requests. This feature of IIS 6.0 is available only when IIS is running in worker process isolation mode. In IIS 6.0 worker process isolation mode, application pools enhance Web site or application reliability by isolating applications and the worker processes that service those applications. For even greater reliability, you can configure an application pool to be supported by multiple worker processes. An application pool that uses more than one worker process is called a Web garden. The worker processes in a Web garden share the requests that arrive for that particular application pool. If a worker process fails, another worker process can continue to process requests. Note Web gardens are different from Web farms. A Web garden is configured on a single server by specifying multiple worker processes for an application pool. Web farms use multiple servers for a Web site. Creating a Web garden for an application pool can also enhance performance in the following situations: • Robust processing of requests: When a worker process in an application pool is tied up (for example, when a script engine stops responding), other worker processes can accept and process requests for the application pool. Reduced contention for resources: When a Web garden reaches a steady state, each new TCP/IP connection is assigned, according to a round-robin scheme, to a worker process in the Web garden. This helps smooth out workloads and reduce contention for resources that are bound to a worker process.

Procedures Important You must be a member of the Administrators group on the local computer to perform the following procedure or procedures. As a security best practice, log on to your computer by using an account that is not in the Administrators group, and then use the runas command to run IIS Manager as an administrator. At a command prompt, type runas /user:Administrative_AccountName "mmc %systemroot%\system32\inetsrv\iis.msc". To configure a Web garden by using IIS Manager 1. In IIS Manager, expand the local computer, expand Application Pools, right-click the application pool, and then click Properties. 2. Click the Performance tab, and under Web garden, in the Maximum number of worker processes box, type the number of worker processes that you want to assign to the application pool. (You must type a number greater than 1 for the application pool to become a Web garden. 3. Click OK. Optionally, you can configure a Web garden by setting the metabase property MaxProcesses. The MaxProcesses property determines the maximum number of worker processes that an application

39 pool allows to service its requests. A value of zero indicates an unmanaged application pool that is not served by a worker process. The default value for the MaxProcesses property is 1, which is the default number of worker processes that service an application pool. To configure an application pool so that it is a Web garden, set the MaxProcesses property to a value greater than 1. Important You must be a member of the Administrators group on the local computer to run scripts and executables. As a security best practice, log on to your computer by using an account that is not in the Administrators group, and then use the runas command to run your script or executable as an administrator. At a command prompt, type runas /profile /user:MyComputer\Administrator cmd to open a command window with administrator rights and then type cscript.exeScriptName (include the script's full path and any known parameters). To configure a Web garden by using Adsutil.vbs 1. In the Run dialog box, type cmd, and then click OK. 2. At the command prompt, type: cscript %SystemDrive%\Inetpub\AdminScripts\adsutil.vbs set W3SVC/AppPools/ApplicationPoolName/MaxProcesses n Replace n with the number of worker processes that you want to service the application pool.

Custom Control Overview
Embedding user controls in a Windows form is just like adding a simple button or text box that are already provided with .NET. These basic controls were written essentially like you code your own controls. Typically the controls you design are to be used in multiple forms or to modularize your code. These reasons help reduce the amount of code you have to type as well as make it easier for you to change your implementation. There should almost never be any reason to duplicate code because it leaves a lot of room for bugs. So, implementing functionality specific to your control in the control's source code is a good idea. This reduces code duplication as well as modularize your code, which is a good programming guideline. Custom controls are a key theme in .NET development. They can help your programming style by improving encapsulation, simplifying a programming model, and making user interface more "pluggable" (i.e., making it easier to swap out one control and replace it with a completely different one without rewriting your form code). Of course, custom controls can have other benefits, including the ability to transform a generic window into a state-of-the-art modern interface. Generally, developers tackle custom control development for one of three reasons: To create controls that abstract away unimportant details and are tailored for a specific type of data. You saw this model in Chapter 6 with custom ListView and TreeView examples. To create controls that provide entirely new functionality, or just combine existing UI elements in a unique way. To create controls with a distinct original look, or ones that mimic popular controls in professional applications (like Microsoft's Outlook bar) that aren't available to the masses.

40 In .NET, creating a custom control is as easy as creating an ordinary class. You simply inherit from the best possible ancestor and add the specific features you need. Best of all, you can create a custom control class as part of an existing project, and then decide later to place it in a separate assembly that can be shared with other programmers. Types of Custom Controls Developers often make a distinction between three or four types of controls: User controls are the simplest type of control. They inherit from the System.Windows.Forms.UserControl class, and follow a model of composition. Usually, user controls combine more than one control in a logical unit (like a group of text boxes for entering address information). Inherited controls are generally more powerful and flexible. With an inherited control, you choose the existing .NET control that is closest to what you want to provide. Then, you derive a custom class that overrides or adds properties and methods. The examples you've looked at so far in this book, including the custom TreeViews and ListViews, have all been inherited controls. Owner-drawn controls generally use GDI+ drawing routines to generate their interfaces from scratch. Because of this, they tend to inherit from a base class like System.Windows.Forms.Control. Owner-drawn controls require the most work and provide the most customizable user interface. Extender providers, which aren't necessarily controls at all. These components add features to other controls on a form, and provide a remarkable way to implement extensible user interface.

Communication between User Controls and subscribing Applications Because the basic .NET controls are contained within our user control, events are not fired for the contained applications. Our user control is treated like any other and must implement it's own properties (besides those inherited from System.Windows.Forms.Control) and events. Publising and Subscribing Events The Event model in C# finds its roots in the event programming model that is popular in asynchronous programming. The basic foundation behind this programming model is the idea of "publisher and subscribers." In this model, you have publishers who will do some logic and publish an "event." Publishers will then send out their event only to subscribers who have subscribed to receive the specific event. In C#, any object can publish a set of events to which other applications can subscribe. When the publishing class raises an event, all the subscribed applications are notified. The following figure shows this mechanism.

41

Events and Delegates At the heart of Events in C# are Delegates. When an object generates an events, it must send the event out. The way that events are dispatched is through the use of delegates. Let's look how Events are declared in C#. [attributes] [modifier] event type member-name; Modifier is any allowable scope modifier. Type must be a delegate. Member-name is the Name of the Event with which you will refer to the event in your code. The important thing to note here is the delegate type that events should use. In the strictest sense, the delegate can be any legal delegate. But there is a convention that you should follow and is one that Window Forms uses. By Convention, the delegate should accept two parameters: 1. The object that generated the event 2. The parameters for the specific event An example of an event / delegate is as follows: public delegate void SubmitClickedHandler(object sender, EventArgs e); public event SubmitClickedHandler SubmitClicked; SubmitClickedHandler is the name of the delegate, sender is self explanatory. EventArgs is defined under the System namespace and is a very plain class. SubmitClicked is the name of the event, which is published to the Subscriber. Submit Button User Control Create the Submit Button User Control The control we will create will contain a text box for your name and a button that will fire an event. To begin, open Visual Studio .NET and begin a new C# Windows Control Library. You may name it whatever you like, for this sample the project name will be SubmitButton.

42

using using using using using using

System; System.Collections; System.ComponentModel; System.Drawing; System.Data; System.Windows.Forms;

namespace Akadia { namespace SubmitButton { // User Control which contain a text box for your // name and a button that will fire an event. public class SubmitButtonControl : System.Windows.Forms.UserControl { private System.Windows.Forms.TextBox txtName; private System.Windows.Forms.Label lblName; private System.Windows.Forms.Button btnSubmit; private System.ComponentModel.Container components = null; // Declare delegate for submit button clicked. // // Most action events (like the Click event) in Windows Forms // use the EventHandler delegate and the EventArgs arguments. // We will define our own delegate that does not specify parameters. // Mostly, we really don't care what the conditions of the // click event for the Submit button were, we just care that // the Submit button was clicked. public delegate void SubmitClickedHandler(); // Constructor public SubmitButtonControl() { // Create visual controls InitializeComponent(); } // Clean up any resources being used. protected override void Dispose( bool disposing ) { if( disposing ) { if( components != null ) components.Dispose(); } base.Dispose( disposing ); } .....

43 ..... // Declare the event, which is associated with our // delegate SubmitClickedHandler(). Add some attributes // for the Visual C# control property. [Category("Action")] [Description("Fires when the Submit button is clicked.")] public event SubmitClickedHandler SubmitClicked; // Add a protected method called OnSubmitClicked(). // You may use this in child classes instead of adding // event handlers. protected virtual void OnSubmitClicked() { // If an event has no subscribers registerd, it will // evaluate to null. The test checks that the value is not // null, ensuring that there are subsribers before // calling the event itself. if (SubmitClicked != null) { SubmitClicked(); // Notify Subscribers } } // Handler for Submit Button. Do some validation before // calling the event. private void btnSubmit_Click(object sender, System.EventArgs e) { if (txtName.Text.Length == 0) { MessageBox.Show("Please enter your name."); } else { OnSubmitClicked(); } } // Read / Write Property for the User Name. This Property // will be visible in the containing application. [Category("Appearance")] [Description("Gets or sets the name in the text box")] public string UserName { get { return txtName.Text; } set { txtName.Text = value; } } } } } Using the Submit User Control in a Windows Application Using the control in a Windows form is trivial. It's just like adding any other control like a button or a DataGrid. First, create a new Windows Application project named: TestApp. Add a reference to the Submit Button User Control DLL named: SubmitButton.dll. Now you are ready to customize the Toolbox: Right-Click the Toolbox, .NET Framework Components, Browse, select the SubmitButton.dll.

44

The Submit Button User Control is now added to the Toolbox and can be inserted in Windows Form as any other control. Now we want to handle the SubmitClicked event for the user control. This will simply close the form. The control itself will take care of validation and the event won't be fired unless the text is valid. Click on the lightning-looking button (for events) with the control selected and you'll see the event, SubmitClicked, listed under the "Action" category. Click on it once and you'll see the description we added previously. Now double-click it and VS.NET will add an event handler SubmitClicked() which displays the name from the user control and close the form when the event is fired.

using System; using System.Drawing; using System.Collections;

45 using System.ComponentModel; using System.Windows.Forms; using System.Data; namespace TestApp { // Test Application for the Submit Button User Control public class TestApp : System.Windows.Forms.Form { private Akadia.SubmitButton.SubmitButtonControl submitButtonControl; private System.ComponentModel.Container components = null; .... ..... [STAThread] static void Main() { Application.Run(new TestApp()); } // Handle the SubmitClicked Event private void SubmitClicked() { MessageBox.Show(String.Format("Hello, {0}!", submitButtonControl.UserName)); this.Close(); } } } Login Validation User Control Create the Login Validation User Control The following sample shows how to implement a Login user control. When the user clicks the Login button, the control will validate the data entered by the user. If the user has left either the User name or the Password text boxes empty, the loginError validation control will display an error icon against the offending control. The Password will then be checked by a "secret algorithm", if the Password is valid, the user control will raise an event called LoginSuccess; otherwise it will fire a different event called LoginFailed. In this sample we use the predefined System.EventHandler delegate. This delegate is useful if you want to define an event that has no additional data. The event will be passed an empty System.EventArgs parameter instead. This is the delegate used by many of the Windows Forms.

46

using using using using using using

System; System.Collections; System.ComponentModel; System.Drawing; System.Data; System.Windows.Forms;

namespace Akadia { namespace LoginControl { // Implementation of a Login User Control public class LoginControl : System.Windows.Forms.UserControl { private System.Windows.Forms.Label lblUserName; private System.Windows.Forms.Label lblPassword; private System.Windows.Forms.TextBox txtUserName; private System.Windows.Forms.TextBox txtPassword; private System.Windows.Forms.Button btnLogin; private System.Windows.Forms.ErrorProvider erpLoginError; private System.Windows.Forms.StatusBar stbMessage; private System.ComponentModel.Container components = null; // Here we use the predefined System.EventHandler delegate. // This delegate is useful if you want to define an event // that has no additional data. The event will be passed an // empty System.EcentArgs parameter instead. This is the // delegate used by many of the Windows Forms. public delegate void EventHandler(Object sender, EventArgs e); public event EventHandler LoginSuccess; public event EventHandler LoginFailed;

// Constructor public LoginControl() { InitializeComponent(); }

47 .... .... // This is the very simple Login Check Validation // The Password mus be ... "secret" ..... private bool LoginCheck(string pName, string pPassword) { return pPassword.Equals("secret"); } // Validate Login, in any case call the LoginSuccess or // LoginFailed event, which will notify the Application's // Event Handlers. private void loginButtonClicked(object sender, System.EventArgs e) { // User Name Validation if (txtUserName.Text.Length == 0) { erpLoginError.SetError(txtUserName,"Please enter a user name"); stbMessage.Text = "Please enter a user name"; return; } else { erpLoginError.SetError(txtUserName,""); stbMessage.Text = ""; } // Password Validation if (txtPassword.Text.Length == 0) { erpLoginError.SetError(txtPassword,"Please enter a password"); stbMessage.Text = "Please enter a password"; return; } else { erpLoginError.SetError(txtPassword,""); stbMessage.Text = ""; } // Check Password if (LoginCheck(txtUserName.Text, txtPassword.Text)) { // If there any Subscribers for the LoginSuccess // Event, notify them ... if (LoginSuccess != null) { LoginSuccess(this, new System.EventArgs()); } } else { // If there any Subscribers for the LoginFailed // Event, notify them ... if (LoginFailed != null) { LoginFailed(this, new System.EventArgs()); } }

48 } // Read-Write Property for User Name Label public string LabelName { get { return lblUserName.Text; } set { lblUserName.Text = value; } } // Read-Write Property for User Name Password public string LabelPassword { get { return lblPassword.Text; } set { lblPassword.Text = value; } } // Read-Write Property for Login Button Text public string LoginButtonText { get { return btnLogin.Text; } set { btnLogin.Text = value; } } // Read-Only Property for User Name [Browsable(false)] public string UserName { set { txtUserName.Text = value; } } // Read-Only Property for Password [Browsable(false)] public string Password { set { txtPassword.Text = value; } }

49 } } } Using the Login Validation User Control in a Windows Application Create a new Windows Application project named: TestApp. Add a reference to the Login Validation User Control DLL named: LoginControl.dll. Now you are ready to customize the Toolbox: Right-Click the Toolbox, .NET Framework Components, Browse, select the LoginControl.dll.

using using using using using using

System; System.Drawing; System.Collections; System.ComponentModel; System.Windows.Forms; System.Data;

namespace TestApp { // Test Application for the Login Validation User Control public class TestApp : System.Windows.Forms.Form { private Akadia.LoginControl.LoginControl loginControl; private System.ComponentModel.Container components = null; .... .... [STAThread] static void Main() { Application.Run(new TestApp()); } // This Event is fired by the Login Validation User Control private void LoginFailed(object sender, System.EventArgs e) { MessageBox.Show("Login falied ....", "Login Validation", MessageBoxButtons.OK, MessageBoxIcon.Exclamation); }

50 // This Event is fired by the Login Validation User Control private void LoginSuccess(object sender, System.EventArgs e) { MessageBox.Show("Login success ....", "Login Validation", MessageBoxButtons.OK, MessageBoxIcon.Exclamation); } } } Format Mask Control Create the Format Mask Control An inherited control example is one for a custom masked text box. A masked text box is one that automatically formats the user's input into the correct format. For example, it may add dashes or brackets to make sure it looks like a phone number. This task is notoriously difficult. One useful tool is Microsoft's masked edit text box, which is provided as an ActiveX control with previous versions of Visual Studio. The example of a masked text box is important because it demonstrates how features (rather than data) might be added to an existing control by subclassing. The example is still quite limitednotably, it restricts deletions and the use of the arrow keys. Tracking the cursor position, which is required to allow inline masked edits, results in a good deal of tedious code that only obscures the point.

using using using using using using

System; System.Collections; System.ComponentModel; System.Drawing; System.Data; System.Windows.Forms;

namespace Akadia { namespace FormatMask { // Extended User Control to implement an Edit Mask Text Box public class EditMask : System.Windows.Forms.TextBox { // Fields private string _mask; // Properties public string Mask { get { return _mask; }

51 set { _mask = value; this.Text = ""; } } // To use the masked control, the application programmer chooses // a mask and applies it to the Mask property of the control. // The number sign (#) represents any number, and the period (.) // represents any letter. All other characters in the mask // are treated as fixed characters, and are inserted automatically // when needed. For example, in the phone number mask (###) ###-#### // the first bracket is inserted automatically when the user types // the first number. protected override void OnKeyPress(KeyPressEventArgs e) { if (Mask != "") { // Suppress the typed character. e.Handled = true; string newText = this.Text; // Loop through the mask, adding fixed characters as needed. // If the next allowed character matches what the user has // typed in (a number or letter), that is added to the end. bool finished = false; for (int i = this.SelectionStart; i < _mask.Length; i++) { switch (_mask[i].ToString()) { case "#" : // Allow the keypress as long as it is a number. if (Char.IsDigit(e.KeyChar)) { newText += e.KeyChar.ToString(); finished = true; break; } else { // Invalid entry; exit and don't change the text. return; } case "." : // Allow the keypress as long as it is a letter. if (Char.IsLetter(e.KeyChar)) { newText += e.KeyChar.ToString(); finished = true; break; } else { // Invalid entry; exit and don't change the text. return; } default : // Insert the mask character.

52 newText += _mask[i]; break; } if (finished) { break; } } // Update the text. this.Text = newText; this.SelectionStart = this.Text.Length; } // base.OnKeyPress(e); } // Stop special characters. protected override void OnKeyDown(KeyEventArgs e) { e.Handled = true; } } } } Using the Edit Mask User Control in a Windows Application Create a new Windows Application project named: TestApp. Add a reference to the Edit Mask User Control DLL named: FormatMask.dll. Now you are ready to customize the Toolbox: Right-Click the Toolbox, .NET Framework Components, Browse, select the FormatMask.dll. using using using using using using System; System.Drawing; System.Collections; System.ComponentModel; System.Windows.Forms; System.Data;

namespace TestApp { // Test Application for the Edit mask User Control public class TestApp : System.Windows.Forms.Form { private Akadia.FormatMask.EditMask editMask; private System.Windows.Forms.Label lblText; private System.ComponentModel.Container components = null; public TestApp() { InitializeComponent(); } ...... private void InitializeComponent() { .... this.editMask.Location = new System.Drawing.Point(93, 63); this.editMask.Mask = "[###]-(##)-#####"; this.editMask.Name = "editMask"; this.editMask.TabIndex = 0; .... }

53 static void Main() { Application.Run(new TestApp()); } } } Toggle Button User Control Create the Toggle Button User Control The Toggle Button User Control is an inherited control. When the user clicks a toggle Button, the Text and BackColor properties should be set according to the Checked state of the button. The natural place to do this is the Click event. However, keep in mind that you only want to extend the default Click event supplied with the CheckBox class rather than replacing is. In the .NET Framework documentation, you will be notice that controls typically have a protected OnXXX method that raises each event (where XXX is the name of the event) - for example the Click event is raised by the OnClick method. The Control call these methods when an event occurs. If you want to extend the Click event, the Trick is therefore to override the OnClick method. If the Appearance value is set to Appearance.Normal, then the check box has a typical appearance. If the value is set to Button, the check box appears like a toggle button, which may be toggled to an up or down state.

using using using using using using

System; System.Collections; System.ComponentModel; System.Drawing; System.Data; System.Windows.Forms;

namespace Akadia { namespace ToggleButton { // The ToggleButton class is inherited from the // System.Windows.Forms.CheckBox Class public class ToggleButton : System.Windows.Forms.CheckBox { // Fields private string _checkedText;

54 private string _uncheckedText; private Color _checkedColor; private Color _uncheckedColor; // Constructor public ToggleButton() { // If Appearance value is set to Appearance.Normal, // the check box has a typical appearance. // If the value is set to Button, the check box appears // like a toggle button, which may be toggled to // an up or down state. this.Appearance = Appearance.Button; // Set Default toggled Text this._checkedText = "Checked"; this._uncheckedText = "Unchecked"; // Set Default toggled Color this._checkedColor = Color.Gray; this._uncheckedColor = this.BackColor; } // Public Properties, can be accessed in Property Panel public string CheckedText { get { return this._checkedText; } set { this._checkedText = value; } } public string UncheckedText { get { return this._uncheckedText; } set { this._uncheckedText = value; } } public Color CheckedColor { get { return this._checkedColor; } set { this._checkedColor = value; } } public Color UncheckedColor { get { return this._uncheckedColor; } set { this._uncheckedColor = value; } } // // // // // // // // // // // // When the user clicks a toggle Button, the Text and BackColor properties should be set according to the Checked state of the button. The natural place to do this is the Click event. However, keep in mind that you only want to extend the default Click event supplied with the CheckBox class rather than replacing is. In the .NET Framework documentation, you will be notice that controls typically have a protected OnXXX method that raises each event (where XXX is the name of the event) - for example the Click event is raised by the OnClick method. The Control call these methods when an event occurs. If you want to extend the Click event, the Trick is therefore to override

55 // the OnClick method. protected override void OnClick(EventArgs e) { base.OnClick(e); // Call the CheckBox Baseclass // Set Text and Color according to the // current state if (this.Checked) { this.Text = this._checkedText; this.BackColor = this._checkedColor; } else { this.Text = this._uncheckedText; this.BackColor = this._uncheckedColor; } } } } } Using the Toggle Button User Control in a Windows Application Create a new Windows Application project named: TestApp. Add a reference to the Toggle Button User Control DLL named: ToggleButton.dll. Now you are ready to customize the Toolbox: Right-Click the Toolbox, .NET Framework Components, Browse, select the ToggleButton.dll. using using using using using using System; System.Drawing; System.Collections; System.ComponentModel; System.Windows.Forms; System.Data;

namespace TestApp { // Test Application for the toggled CheckBox und Button public class TestApp : System.Windows.Forms.Form { private Akadia.ToggleButton.ToggleButton btnToggle1; private Akadia.ToggleButton.ToggleButton btnToggle2; private Akadia.ToggleButton.ToggleButton btnToggle3; private System.Windows.Forms.Label lblText1; private System.Windows.Forms.Label lblText2; private Akadia.ToggleButton.ToggleButton btnToggle4; private System.ComponentModel.Container components = null; public TestApp() { InitializeComponent(); // Set Appearance to CheckBox btnToggle1.Appearance = Appearance.Normal; btnToggle2.Appearance = Appearance.Normal; } ...... private void InitializeComponent() {

56 this.btnToggle1 = new Akadia.ToggleButton.ToggleButton(); this.btnToggle2 = new Akadia.ToggleButton.ToggleButton(); this.btnToggle3 = new Akadia.ToggleButton.ToggleButton(); ..... } static void Main() { Application.Run(new TestApp()); } } }

Custom control vs User Control

Overview In this month's column, I'll discuss the following topics: • What are user controls? • What are custom controls? • What are the basic differences between user controls and custom controls? I'll also introduce a few of the advanced topics that concern custom controls, such as state management and the rendering of custom controls. What are user controls? User controls are custom, reusable controls, and they use the same techniques that are employed by HTML and Web server controls. They offer an easy way to partition and reuse common user interfaces across ASP.NET Web applications. They use the same Web Forms programming model on which a Web Forms page works. For more details about the Web Forms programming model, visit the following Microsoft Developer Network (MSDN) Web sites: Introduction to Web Forms pages http://msdn.microsoft.com/library/default.asp?url=/library/enus/vbcon/html/vbconIntroductionToWebForms.asp (http://msdn.microsoft.com/library/default.asp?url=/library/enus/vbcon/html/vbconIntroductionToWebForms.asp) Web Forms code model http://msdn.microsoft.com/library/default.asp?url=/library/enus/vbcon/html/vbconwebformscodemodel.asp (http://msdn.microsoft.com/library/default.asp?url=/library/enus/vbcon/html/vbconwebformscodemodel.asp) How to create a user control The syntax you use to create a user control is similar to the syntax you use to create a Web Forms page (.aspx). The only difference is that a user control does not include the <html>, <body>, and <form> elements since a Web Forms page hosts the user control. To create a user control, follow these steps: Open a text or HTML editor, and create a server-side code block exposing all the properties, methods, and events. 1. <script language="C#" runat="server">

57 public void button1_Click(object sender, EventArgs e) { label1.Text = "Hello World!!!"; } </script> Create a user interface for the user control. <asp:Label id="label1" runat="server"/> 2. <br><br> <asp:button id="button1" text="Hit" OnClick="button1_Click" runat="server" />

How to use a user control in a Web Forms page Create a new Web Forms page (.aspx) in Microsoft Visual Studio .NET 2002, Microsoft Visual 1. Studio .NET 2003, Microsoft Visual Studio 2005, or any text editor. Declare the @ Register directive. For example, use the following code. 2. <% @ Register TagPrefix="UC" TagName="TestControl" Src="test.ascx" %> Note Assume that the user control and the Web Forms page are in the same location. To use the user control in the Web Forms page, use the following code after the @ Register directive. <html> <body> <form runat="server"> 3. <UC:TestControl id="Test1" runat="server"/> </form> </body> </html>

How to create an instance of a user control programmatically in the code behind file of a Web Forms page The previous example instantiated a user control declaratively in a Web Forms page using the @ Register directive. However, you can instantiate a user control dynamically and add it to the page. Here are the steps for doing that: 1. Create a new Web Forms page in Visual Studio.

58 2. Navigate to the code behind file generated for this Web Forms page. In the Page_Load event of the Page class, write the following code. // Load the control by calling LoadControl on the page class. Control c1 = LoadControl("test.ascx");

// Add the loaded control in the page controls collection. Page.Controls.Add(c1); Note You can add a user control dynamically at certain events of the page life cycle. 3. For more information, visit the following Web sites: Adding controls to a Web Forms page programmatically http://msdn.microsoft.com/library/default.asp?url=/library/enus/vbcon/html/vbtskAddingControlsToWebFormsPageProgrammatically.asp (http://msdn.microsoft.com/library/default.asp?url=/library/enus/vbcon/html/vbtskAddingControlsToWebFormsPageProgrammatically.asp) Control execution lifecycle http://msdn.microsoft.com/library/default.asp?url=/library/enus/cpguide/html/cpconcontrolexecutionlifecycle.asp (http://msdn.microsoft.com/library/default.asp?url=/library/enus/cpguide/html/cpconcontrolexecutionlifecycle.asp) Dynamic Web controls, postbacks, and view state, by Scott Mitchell http://aspnet.4guysfromrolla.com/articles/092904-1.aspx (http://aspnet.4guysfromrolla.com/articles/092904-1.aspx) How a user control is processed When a page with a user control is requested, the following occurs: The page parser parses the .ascx file specified in the Src attribute in the @ Register directive and generates a class that derives from the System.Web.UI.UserControl class. The parser then dynamically compiles the class into an assembly. If you are using Visual Studio, then at design time only, Visual Studio creates a code behind file for the user control, and the file is precompiled by the designer itself. Finally, the class for the user control, which is generated through the process of dynamic code generation and compilation, includes the code for the code behind file (.ascx.cs) as well as the code written inside the .ascx file.

• • • •

What are custom controls? Custom controls are compiled code components that execute on the server, expose the object model, and render markup text, such as HTML or XML, as a normal Web Form or user control does. How to choose the base class for your custom control To write a custom control, you should directly or indirectly derive the new class from the System.Web.UI.Control class or from the System.Web.UI.WebControls.WebControl class: You should derive from System.Web.UI.Control if you want the control to render nonvisual • elements. For example, <meta> and <head> are examples of nonvisual rendering. • You should derive from System.Web.UI.WebControls.WebControl if you want the control to

59 render HTML that generates a visual interface on the client computer. If you want to change the functionality of existing controls, such as a button or label, you can directly derive the new class with these existing classes and can change their default behavior. In brief, the Control class provides the basic functionality by which you can place it in the control tree for a Page class. The WebControl class adds the functionality to the base Control class for displaying visual content on the client computer. For example, you can use the WebControl class to control the look and styles through properties like font, color, and height.

How to create and use a simple custom control that extends from System.Web.UI.Control using Visual Studio 1. Start Visual Studio. 2. Create a class library project, and give it a name, for example, CustomServerControlsLib. 3. Add a source file to the project, for example, SimpleServerControl.cs. 4. Include the reference of the System.Web namespace in the references section. Check whether the following namespaces are included in the SimpleServerControl.cs file. System System.Collections System.ComponentModel 5. System.Data System.Web System.Web.SessionState System.Web.UI System.Web.UI.WebControls Inherit the SimpleServerControls class with the Control base class. 6. public class SimpleServerControl : Control Override the Render method to write the output to the output stream. protected override void Render(HtmlTextWriter writer) { 7. } Note The HtmlTextWriter class has the functionality of writing HTML to a text stream. The Write method of the HtmlTextWriter class outputs the specified text to the HTTP response stream and is the same as the Response.Write method. Compile the class library project. It will generate the DLL output. Open an existing or create a new ASP.NET Web application project. Add a Web Forms page where the custom control can be used. writer.Write("Hello World from custom control");

8. 9. 10.

60 11. Add a reference to the class library in the references section of the ASP.NET project. Register the custom control on the Web Forms page. <% @ Register TagPrefix="CC " Namespace=" CustomServerControlsLib " Assembly="CustomServerControlsLib " % > To instantiate or use the custom control on the Web Forms page, add the following line of code in the <form> tags. <form id="Form1" method="post" runat="server"> 13. <CC:SimpleServerControl id="ctlSimpleControl" runat="server"> </CC:SimpleServerControl > </form> Note In this code, SimpleServerControl is the control class name inside the class library. 14. Run the Web Forms page, and you will see the output from the custom control. If you are not using Visual Studio, you need to perform the following steps: 1. Open any text editor. 2. Create a file named SimpleServerControl.cs, and write the code as given in steps 1 through 14. In the PATH variable, add the following path: 3. c:\windows (winnt)\Microsoft.Net\Framework\v1.1.4322 4. Start a command prompt, and go to the location where SimpleServerControl.cs is present. Run the following command: csc /t:library /out: CustomServerControlsLib. SimpleServerControl.dll /r:System.dll /r:System.Web.dll SimpleServerControl.cs For more information about the C# compiler (csc.exe), visit the following MSDN Web site: 5. http://msdn.microsoft.com/library/default.asp?url=/library/enus/cscomp/html/vcgrfbuildingfromcommandline.asp (http://msdn.microsoft.com/library/default.asp?url=/library/enus/cscomp/html/vcgrfbuildingfromcommandline.asp) To run the custom control on the Web Forms page, do the following: a. Create a directory under the wwwroot folder. Start Microsoft Internet Information Services (IIS) Manager, and mark the new directory as the b. virtual root directory. c. Create a Bin folder under the new directory. 6. d. Copy the custom control DLL into the Bin folder. Place the sample Web Forms page that you created in the previous steps inside the new e. directory. f. Run the sample page from IIS Manager. Now that you have built a simple custom control, let's look at how to expose properties and apply design-time attributes on that custom control. How to expose properties on the custom control I will build on the previous example and introduce one or more properties that can be configured while using the custom control on the Web Forms page. The following example shows how to define a property that will display a message from the control a certain number of times, as specified in the property of the control: 1. Open SimpleServerControl.cs in a text editor. 2. Add a property in the SimpleServerControl class.

12.

61 public class SimpleServerControl : Control { private int noOfTimes; public int NoOfTimes { get { return this.noOfTimes; } set { this.noOfTimes = value; } } protected override void Render (HtmlTextWriter writer) { for (int i=0; i< NoOfTimes; i++) { write.Write("Hello World.."+"<BR>"); } } } 3. Compile the custom control. To use the custom control on the Web Forms page, add the new property to the control declaration. 4. <CC:SimpleServerControl id="ctlSimpleControl" NoOfTimes="5" runat="server"></CC:SimpleServerControl> Running the page will display the message "Hello world" from the custom control as many times as specified in the property of the control.

5.

How to apply design-time attributes on the custom control Why design-time attributes are needed The custom control that you built in the previous example works as expected. However, if you want to use that control in Visual Studio, you may want the NoOfTimes property to be automatically highlighted in the Properties window whenever the custom control is selected at design time. To make this happen, you need to provide the metadata information to Visual Studio, which you can do by using a feature in Visual Studio called attributes. Attributes can define a class, a method, a property, or a field. When Visual Studio loads the custom control's class, it checks for any attributes defined at the class, method, property, or field level and changes the behavior of the custom control at design time accordingly.

62 To find more information about attributes, visit the following MSDN Web site: http://msdn.microsoft.com/library/default.asp?url=/library/enus/csref/html/vclrfintroductiontoattributes.asp (http://msdn.microsoft.com/library/default.asp?url=/library/enus/csref/html/vclrfintroductiontoattributes.asp) Let's build a sample that uses commonly used attributes: 1. Open SimpleServerControl.cs in a text editor. Introduce some basic attributes at the class level, for example, DefaultProperty, ToolboxData, and TagPrefixAttrbute. We'll build our sample on these three attributes. [ // Specify the default property for the control. DefaultProperty("DefaultProperty"), // Specify the tag that is written to the aspx page when the // control is dragged from the Toolbox to the Design view. // However this tag is optional since the designer automatically // generates the default tag if it is not specified. ToolboxData("<{0}:ControlWithAttributes runat=\"server\">" + "</{0}:ControlWithAttributes>") ] 2. public class ControlWithAttributes : Control { private string _defaultProperty; public string DefaultProperty { get { return "This is a default property value"; } set { this._defaultProperty = value; } } protected override void Render(HtmlTextWriter writer) { writer.Write("Default Property --> <B>" + DefaultProperty + "</B>"); } } There is one more tag called TagPrefixAttrbute. It is an assembly-level attribute that provides a prefix to a tag when you drag the control from the Toolbox to the designer. Otherwise, the 3. designer generates a prefix such as "cc1" by default. TagPrefixAttrbute is not directly applied to the control class. To apply TagPrefixAttrbute, open AssemblyInfo.cs, include the following line of code, and then rebuild the project.

63 [assembly:TagPrefix("ServerControlsLib ", "MyControl")] Note If you want to build the source using the command line, you need to create the AssemblyInfo.cs file, place the file in the directory that contains all the source files, and run the following command to build the control: > csc /t:library /out: ServerControlsLib.dll /r:System.dll /r :System.Web.dll *.cs What are the basic differences between user controls and custom controls? Now that you have a basic idea of what user controls and custom controls are and how to create them, let's take a quick look at the differences between the two. Factors User control Designed for single-application scenarios Custom control Designed so that it can be used by more than one application Deployed either in the application's Bin directory or in the global assembly cache Distributed easily and without problems associated with redundancy and maintenance

Deployed in the source form (.ascx) along with the source code of the Deployment application If the same control needs to be used in more than one application, it introduces redundancy and maintenance problems Creation is similar to the way Web Forms pages are created; well-suited for rapid application development (RAD) A much better choice when you need static content within a fixed layout, for example, when you make headers and footers Writing doesn't require much application designing because they are authored at design time and mostly contain static data

Creation

Writing involves lots of code because there is no designer support More suited for when an application requires dynamic content to be displayed; can be reused across an application, for example, for a data bound table control with dynamic rows Writing from scratch requires a good understanding of the control's life cycle and the order in which events execute, which is normally taken care of in user controls

Content

Design

Delegets

Introduction
A delegate is an object that can refer to a method. Thus, when you create a delegate, you are creating an object that can hold a reference to a method. Furthermore, the method can be called through this reference. Thus, a delegate can invoke the method to which it refers (It’s Like a function pointer in c/c++).

Paragraph Heading 1
Even though a method is not an object, it still has a physical location in memory. This address is the entry point of the method and is the address called when the method is invoked. The address of a method can be assigned to a delegate. Once a delegate refers to a method, the method can be called through that delegate. Furthermore, the same delegate can be used to call a different method by simply changing the method to which the delegate refers. The principal advantage of a delegate is that it allows you to specify a call to a method, but the method actually invoked is determined at runtime, not at compile time.

64
A delegate is declared using the keyword delegate. The general form of a delegate declaration is shown here: delegate ret-type name(parameter-list); Here, ret-type is the type of value returned by the methods that the delegate will be calling. The name of the delegate is specified by name. The parameters required by the methods called through the delegate are specified in the parameter-list. Once declared, a delegate can call only methods whose return type and parameter list match those specified by the delegate. As mentioned, the key point about delegates is that a delegate can be used to call any method that agrees with its signature. This makes it possible to determine which method to invoke at runtime. Furthermore, the method invoked can be an instance method associated with an object, or a static method associated with a class. All that matters is that the signature of the method agrees with that of the delegate. To see delegates in action, let’s begin with the simple example shown here: []CODE] // A simple delegate example. using System; // Declare a delegate. delegate string strMod(string str); class DelegateTest { // Replaces spaces with hyphens. static string replaceSpaces(string a) { Console.WriteLine("Replaces spaces with hyphens."); return a.Replace(' ', '-'); } // Remove spaces. static string removeSpaces(string a) { string temp = ""; int i; Console.WriteLine("Removing spaces."); for(i=0; i < a.Length; i++) if(a[i] != ' ') temp += a[i]; return temp; } // Reverse a string. static string reverse(string a) { string temp = ""; int i, j; Console.WriteLine("Reversing string."); for(j=0, i=a.Length-1; i >= 0; i--, j++) temp += a[i]; return temp; } public static void Main() { // Construct delegates. strMod strOp = new strMod(replaceSpaces); string str; // Call methods through delegates. str = strOp("This is a test."); Console.WriteLine("Resulting string: " + str); Console.WriteLine(); strOp = new strMod(removeSpaces); str = strOp("This is a test."); Console.WriteLine("Resulting string: " + str);

65
Console.WriteLine(); strOp = new strMod(reverse); str = strOp("This is a test."); Console.WriteLine("Resulting string: " + str); } []/CODE]}

Multicasting One of the most exciting features of a delegate is its support for multicasting. In simple terms, multicasting is the ability to create a chain of methods that will be automatically called when a delegate is invoked. Such a chain is very easy to create. Simply instantiate a delegate, and then use the += operator to add methods to the chain. To remove a method, use – =. (You can also use the +, –, and = operators separately to add and subtract delegates, but += and – = are more convenient.) The only restriction is that the delegate being multicast must have a void return type. Example []CODE] // Demonstrate multicasting. using System; // Declare a delegate. delegate void strMod(ref string str); class StringOps { // Replaces spaces with hyphens. static void replaceSpaces(ref string a) { Console.WriteLine("Replaces spaces with hyphens."); a = a.Replace(' ', '-'); } // Remove spaces. static void removeSpaces(ref string a) { string temp = ""; int i; Console.WriteLine("Removing spaces."); for(i=0; i < a.Length; i++) if(a[i] != ' ') temp += a[i]; a = temp; } // Reverse a string. static void reverse(ref string a) { string temp = ""; int i, j; Console.WriteLine("Reversing string."); for(j=0, i=a.Length-1; i >= 0; i--, j++) temp += a[i]; a = temp; } public static void Main() { // Construct delegates. strMod strOp; strMod replaceSp = new strMod(replaceSpaces); strMod removeSp = new strMod(removeSpaces); strMod reverseStr = new strMod(reverse); string str = "This is a test"; // set up multicast strOp = replaceSp; strOp += reverseStr;

66
// Call multicast strOp(ref str); Console.WriteLine("Resulting string: " + str); Console.WriteLine(); // remove replace and add remove strOp -= replaceSp; strOp += removeSp; str = "This is a test."; // reset string // Call multicast strOp(ref str); Console.WriteLine("Resulting string: " + str); Console.WriteLine(); } [/CODE]} In general, delegates are useful for two main reasons. First, delegates support events. Second, delegates give your program a way to execute a method at runtime without having to know precisely what that method is at compile time. This ability is quite useful when you want to create a framework that allows components to be plugged in. For example, imagine a drawing program (a bit like the standard Windows Paint accessory). Using a delegate, you could allow the user to plug in special color filters or image analyzers. Furthermore, the user could create a sequence of these filters or analyzers. Such a scheme would be easily handled using a delegate.

Destructor,Finalize and IDisposable Interface
Destructors Destructors are used to destruct instances of classes. Remarks Destructors cannot be defined in structs. They are only used with classes.  A class can only have one destructor.     Destructors cannot be inherited or overloaded. Destructors cannot be called. They are invoked automatically. A destructor does not take modifiers or have parameters.

For example, the following is a declaration of a destructor for the class Car: class Car { ~ Car() // destructor { // cleanup statements... } } The destructor implicitly calls Finalize on the object's base class. Therefore, the preceding destructor code is implicitly translated to: protected override void Finalize() { try { // cleanup statements... } finally { base.Finalize(); } } This means the Finalize method is called recursively for all of the instances in the inheritance chain, from the most-derived to the least-derived. Note Empty destructors should not be used. When a class contains a destructor, an entry is created in the Finalize queue. When the destructor is called, the garbage collector is invoked to process the queue. If the destructor is empty, this simply results in a needless loss of performance. The programmer has no control over when the destructor is called because this is determined by the garbage collector. The garbage collector checks for objects that are no longer being used by the application. If it considers an object eligible for destruction, it calls the destructor (if any) and reclaims the memory used to store the object. Destructors are also called when the program exits.

67 It is possible to force garbage collection by calling Collect but in most cases, this should be avoided because it may result in performance issues.

68

Using Destructor to release resources
Explicit Release of Resources If your application is using an expensive external resource, it is also recommended that you provide a way to explicitly release the resource before the garbage collector frees the object. You do this by implementing a Dispose method from the IDisposable interface that performs the necessary cleanup for the object. This can considerably improve the performance of the application. Even with this explicit control over resources, the destructor becomes a safeguard to clean up resources if the call to the Dispose method failed. Example The following example creates three classes that make a chain of inheritance. The class First is the base class, Second is derived from First, and Third is derived from Second. All three have destructors. In Main(), an instance of the most-derived class is created. When the program runs, notice that the destructors for the three classes are called automatically, and in order, from the most-derived to the least-derived. class First { ~First() { System.Console.WriteLine("First's destructor is called"); } } class Second: First { ~Second() { System.Console.WriteLine("Second's destructor is called"); } } class Third: Second { ~Third() { System.Console.WriteLine("Third's destructor is called"); } } class TestDestructors { static void Main() { Third t = new Third(); } } Output Third's destructor is called Second's destructor is called First's destructor is called Object.Finalize Method Allows an object to attempt to free resources and perform other cleanup operations before the Object is reclaimed by garbage collection. Remarks Finalize is protected and, therefore, is accessible only through this class or a derived class. This method is automatically called after an object becomes inaccessible, unless the object has been exempted from finalization by a call to SuppressFinalize. During shutdown of an application domain, Finalize is automatically called on objects that are not exempt from finalization, even those that are still accessible. Finalize is automatically called only once on a given instance, unless the object is re-registered using a mechanism such as ReRegisterForFinalize and GC.SuppressFinalize has not been subsequently called. Every implementation of Finalize in a derived type must call its base type's implementation of Finalize. This is the only case in which application code is allowed to call Finalize. Finalize operations have the following limitations:  The exact time when the finalizer executes during garbage collection is undefined. Resources are not guaranteed to be released at any specific time, unless calling a Close method or a Dispose method. The finalizers of two objects are not guaranteed to run in any specific order, even if one object refers to the other. That is, if Object A has a reference to Object B and both have finalizers, Object B might have already finalized when the finalizer of Object A starts. The thread on which the finalizer is run is unspecified.

The Finalize method might not run to completion or might not run at all in the following exceptional circumstances:

69  Another finalizer blocks indefinitely (goes into an infinite loop, tries to obtain a lock it can never obtain and so on). Because the runtime attempts to run finalizers to completion, other finalizers might not be called if a finalizer blocks indefinitely. The process terminates without giving the runtime a chance to clean up. In this case, the runtime's first notification of process termination is a DLL_PROCESS_DETACH notification.

The runtime continues to Finalize objects during shutdown only while the number of finalizable objects continues to decrease. If Finalize or an override of Finalize throws an exception, and the runtime is not hosted by an application that overrides the default policy, the runtime terminates the process and no active tryfinally blocks or finalizers are executed. This behavior ensures process integrity if the finalizer cannot free or destroy resources. Notes to Implementers: Object.Finalize does nothing by default. It must be overridden by a derived class only if necessary, because reclamation during garbage collection tends to take much longer if a Finalize operation must be run. If an Object holds references to any resources, Finalize must be overridden by a derived class in order to free these resources before the Object is discarded during garbage collection. A type must implement Finalize when it uses unmanaged resources such as file handles or database connections that must be released when the managed object that uses them is reclaimed. See the IDisposable interface for a complementary and more controllable means of disposing resources. Finalize can take any action, including resurrecting an object (that is, making the object accessible again) after it has been cleaned up during garbage collection. However, the object can only be resurrected once; Finalize cannot be called on resurrected objects during garbage collection. Destructors are the C# mechanism for performing cleanup operations. Destructors provide appropriate safeguards, such as automatically calling the base type's destructor. In C# code, Object.Finalize cannot be called or overridden. IDisposable Interface Defines a method to release allocated unmanaged resources. C# [ComVisibleAttribute(true)] public interface IDisposable Remarks The garbage collector automatically releases the memory allocated to a managed object when that object is no longer used, however, it is not possible to predict when garbage collection will occur. Furthermore, the garbage collector has no knowledge of unmanaged resources such as window handles, or open files and streams. Use the Dispose method of this interface to explicitly release unmanaged resources in conjunction with the garbage collector. The consumer of an object can call this method when the object is no longer needed. Calling the IDisposable Interface When calling a class that implements the IDisposable interface, use the try-finally pattern to make sure that unmanaged resources are disposed of even if an exception interrupts your application. Note that you can use the using statement (Using in Visual Basic) instead of the try-finally pattern. Example C# using System; using System.ComponentModel; // The following example demonstrates how to create // a resource class that implements the IDisposable interface // and the IDisposable.Dispose method. public class DisposeExample { // A base class that implements IDisposable. // By implementing IDisposable, you are announcing that

70 // instances of this type allocate scarce resources. public class MyResource: IDisposable { // Pointer to an external unmanaged resource. private IntPtr handle; // Other managed resource this class uses. private Component component = new Component(); // Track whether Dispose has been called. private bool disposed = false; // The class constructor. public MyResource(IntPtr handle) { this.handle = handle; } // Implement IDisposable. // Do not make this method virtual. // A derived class should not be able to override this method. public void Dispose() { Dispose(true); // This object will be cleaned up by the Dispose method. // Therefore, you should call GC.SupressFinalize to // take this object off the finalization queue // and prevent finalization code for this object // from executing a second time. GC.SuppressFinalize(this); } // Dispose(bool disposing) executes in two distinct scenarios. // If disposing equals true, the method has been called directly // or indirectly by a user's code. Managed and unmanaged resources // can be disposed. // If disposing equals false, the method has been called by the // runtime from inside the finalizer and you should not reference // other objects. Only unmanaged resources can be disposed. private void Dispose(bool disposing) { // Check to see if Dispose has already been called. if(!this.disposed) { // If disposing equals true, dispose all managed // and unmanaged resources. if(disposing) { // Dispose managed resources. component.Dispose(); } // Call the appropriate methods to clean up // unmanaged resources here. // If disposing is false, // only the following code is executed. CloseHandle(handle); handle = IntPtr.Zero; // Note disposing has been done. disposed = true; } } // Use interop to call the method necessary // to clean up the unmanaged resource. [System.Runtime.InteropServices.DllImport("Kernel32")] private extern static Boolean CloseHandle(IntPtr handle); // Use C# destructor syntax for finalization code. // This destructor will run only if the Dispose method

71 // does not get called. // It gives your base class the opportunity to finalize. // Do not provide destructors in types derived from this class. ~MyResource() { // Do not re-create Dispose clean-up code here. // Calling Dispose(false) is optimal in terms of // readability and maintainability. Dispose(false); } } public static void Main() { // Insert code here to create // and use the MyResource object. } }

Developing Multilingual Applications

The need for applications that span different cultures increased the demand for the creation of multilingual applications. The necessity for these applications originated due to the use of multiple languages across the globe and the different emerging cultures within a locale. Depending on the languages in a locale, the application needs to display the user’s locale-specific information in the locale-specific language. This is often referred as localization. Locale-specific settings include formatting of date, time, calendar specifications, and so on. The .NET framework provides support for multilingual applications by creating resource files. These resource files allow you to specify the locale-specific settings. For each locale, you can create one resource file and specify the settings for that locale in the resource file. These resource files are then compiled into satellite assemblies and can be accessed in the applications by the classes provided by .NET framework. The .NET framework allows you to create resource files in three different formats namely text file (.txt) format, .resx format and .resources format. After the creation of these files, you need to create the satellite assembly. Satellite Assembly can be created in two methods. One method is to use the AL.exe (Assembly Linker) utility and the other method is to use the VS.NET utility. You can create the text format of the resource files, if the resource information is a string data. If the resources need to contain any embedded objects, then you need to create .resx file or .resources file. These two file formats can hold object(s) and string data. The text file format can be created using a text editor such as Notepad. The information will be specified in the form of key-value pairs. The .resx file can be created by using the VS.NET IDE. To create a .resx file: 1. In the Project Menu, select Add New Item to display the Add New Item dialog box. 2. Select the Assembly Resource File option from the dialog box. This will add a new .resx file to your project.

72 You can specify the name and value of the resource information in the created .resx file. You can also create a resource file to specify a particular locale. There are certain naming conventions to be followed while creating such files. They should adhere to the syntax specified below: < baseFileName >.< locale >.txt < baseFileName >.< locale >.resx. For example, when you create a resource file for the locale “kn-IN”, the resource file name takes the form: MyResource.kn-IN.txt – in case of the text file MyResource.kn-IN.resx – in case of the .resx file When the created resource file is compiled with ResGen.exe (Resource Generation File) utility, the output will be a CLR binary .resources file. This file can be embedded into a runtime executable or compiled into a satellite assembly. Once the .resources file is created, you need to create the satellite assembly. Satellite assemblies are compiled DLL’s which contains only resource data. These assemblies are useful to load the data dynamically depending upon the current culture of your application. These are two methods to create the assembly. One method is to use the AL.exe utility provided by the .NET SDK. The utility has the following switches: /t: Represents the type of the output file /culture: Represents the name of the locale for which the assembly is being created /embed: Represents the name of the resource file that needs to be embedded into the assembly /out: Represents the name of the output assembly generated For example, if the the the the type of output file is a dll file, locale is ta-IN, name of the resource file is MyResource.ta-IN.resources and name of the output assembly is Myresource.resources.dll

then, AL.exe is invoked as, AL /t: lib /culture: ta-IN /embed: MyResource.ta-IN.resources /out: Myresource.resources.dll The assembly thus created is a satellite assembly. The alternate method of creating a satellite assembly is by using the VS.NET IDE. You can add a new resource file from the Add New Item submenu of the Project menu. After the resource information is stored, you need to set the Build option of the resource file to “Embedded Resource” in the Property window of the file. When the project is compiled, VS.NET automatically embeds the resource file into the assembly being generated. Once the required resource files and satellite assemblies are created, the information from the resource files has to be retrieved to apply it to the GUI application. When a new form is created, you need to enable the Localization property of the form from its Property window.

73 After enabling the Localization property, any controls that are added to the form will follow the same localization property. You can choose the language supported by the form using the Language property of the form. For each language chosen, a resource file will be created. You can store the resource information in those files. Retrieving data from the resource files and satellite assemblies can be performed with the help of the ResourceManager class defined in the System.Resources namespace. In order to retrieve data from the resource file, you need to create a .resx file by selecting Add New Item sub-menu of the Project menu. You then specify the file name as MyResources.ta-IN.resx and specify the key and value for the assembly. For example, you can create a resource file with the key and value as follows: Key : f1 ; Value : Sun Flower Key : f2 ; Value : Lilly. After saving the file, you have to create the .resources file from the .resx file using the resgen.exe utility. You have to embed the resource file into an assembly using the al.exe utility. You then have to write code to read data from the resource files. The following code shows how to retrieve data from the resource files using the ResourceManager class: using System; using System.Collections; using System.ComponentModel; using System.Data; using System.Drawing; using System.Text; using System.Windows.Forms; using System.Resources. namespace Resource { partial class Form2 : Form { public Form2() { InitializeComponent(); } private void button1_Click(object sender, EventArgs e) { ResourceManager rm = new ResourceManager("Resource.MyResource", typeof(Form2).Assembly); System.Threading.Thread.CurrentThread.CurrentUICulture = new System.Globalization.CultureInfo("ta-IN"); label1.Text = rm.GetString("f2"); } }

74 In the above code, Resource.MyResource refers to namespace.resource file name. The GetString method of the ResourceManager class reads the value from the resource file and applies it to the Label control. The following figure displays the output of executing the above code:

The following code shows how to retrieve data from the satellite assemblies using the ResourceManager class: System.Resources.ResourceManager rm = new System.Resources.ResourceManager(Resource.Form2_ta_IN); System.Resources.ResourceManager x; System.Globalization.CultureInfo ci = new CultureInfo("ta-IN"); System.Threading.Thread.CurrentThread.CurrentCulture = ci; x = new ResourceManager("myresource.ta-IN", [Assembly].GetExecutingAssembly.GetSatelliteAssembly(ci)); Label1.Text=x.GetString("f1"); In the above code, you retrieve the value of the satellite assembly with respect to the culture specified by the ci variable. Thus, the resource files created manually or by the VS.NET runtime allows you to store the locale specific settings for a particular form. When a form is localized to more than one culture, the application developed becomes a multilingual application.

The Microsoft .NET Framework was designed keeping in mind the international markets and the necessity of globalization or internationalization of the software applications designed on top of the .NET Framework. The .NET Framework provides a powerful support for localization through the System.Globalization, System.Resources and System.Threading namespaces. This article discusses the concepts of Globalization and Localization and how we can implement a multilingual application in .NET. What is Localization and Globalization? [ Back To Top ] Localization is the process of adapting a software application for a specific locale. It is defined as the process of creating and configuring an application for supporting a specific language or locale. Globalization is defined as the process of identifying the specific portion of the application that needs to be different for different languages and how to isolate them from the application's core. Therefore, it is the process of identifying the localizable resources of the application.

75 The Microsoft .NET library provides support for globalization and localization using the following namespaces. System.Globalization System.Resources System.Text System.Threading The System.Globalization namespace provides support for developing multilingual applications in Microsoft .NET by allowing the developers to define culture specific information. The sections that follow discuss cultures and how to work with them in .NET. The System.Resources namespace provides support to create, store and manage various culture-specific resources used in an application. It contains a class called ResourceManager that allows access to resources either from the main assembly or those that are present in Satellite Assemblies. We will discuss both ResourceManager and Satellite Assemblies in more detail later in this article. The System.Text namespace provides support for representing various character encodings like ASCII, Unicode, UTF7 and UTF-8. The System.Threading namespace contains classes and interfaces that provide support for multithreaded programming. Culture [ Back To Top ] The term Culture denotes a combination of a geographical location and the language spoken in it. A Culture can be represented in any of the ways shown below. en-US en-GB The former refers to English language that is spoken in the US while the latter implies that which is spoken in Great Britain. Working with Culture Information [ Back To Top ] Microsoft .NET provides support for working with culture specific information using the CultureInfo class in the System.Globalization namespace. Culture information can be set both at the page level as well as at the application level. To set the Culture information at the page levels use the following in the Page directive of the ASP.NET page. Listing 1 <% @ Page language="C#" Culture="fr-FR"%> This statement in listing 1 would ensure that the culture information is applicable only for this particular page in the application. To set the Culture information at the application level, use the following in the Globalization section of the web.config file. Listing 2 <configuration> <system.web> <globalization culture="en-GB" /> </system.web> </configuration> This specification as shown in listing 2 in the web.config file would ensure that the culture information is applicable throughout the application. Resource Files

76 [ Back To Top ] A resource file consists of non-executable data that is required by the application and is deployed along with it. Bitmaps, icons, cursors, etc. are typical examples of resource files. Microsoft .NET provides support for multilingual applications using resource files. The resource files used to create a multilingual application contain the culture dependent resources for the application. A resource file can be used to specify the locale-specific settings. Note that to support each locale in the application, there should be one resource file created. These resource files are then compiled into satellite assemblies and accessed by the application. Resource files can be either text files or resx files in .NET. The basic advantages of using resource files are given below. Support for Globalization with isolation of the resource content from the application Reusability and the provision for change of the resource content without the need to change the application's code It should be noted that each resource file has support for a specific culture. Hence, if we need to have support for "n" cultures, we need to have "n" different resource files. Creating Resource Files First create a resource file using the VS.NET IDE and save using either a .txt or a .resx extension. The resource file should be created using the intended culture if it is to be used for Globalization or Localization purposes. When creating resource files for specific locales, the following naming convention should be followed. <base file name>.<locale>.txt or <base file name>.<locale>.resx Therefore the resource file targetted at en-GB locale should be named as TestResource.en-GB.txt or TestResource.en-GB.resx. Note that the resource file name TestResource.en-GB.resx contains the name of the resource that it is intended at. The ResourceWriter class in the System.Resources namespace is used to create a resource programmatically. The sample code below creates a resource file called Test.Resources in the root directory of the C drive. Listing 3 using System; using System.Resources; class CreateResources { public static void Main(string[]args) { ResourceWriter rw = new ResourceWriter("C:\\Test.resources"); rw.AddResource("CopyRight", "CopyRight Message in English"); rw.Close(); } } The ResourceWriter class can also be used to store any other serializable object in the resource file. Reading Resource Files The content of the resource files can be read in the application using the ResourceManager class defined in the System.Resources namespace. The ResourceManager class looks up culture-specific resources and provides convenient access to culture-specific resources at runtime. According to MSDN, "The Resource Manager class looks up culture-specific resources, provides resource fallback when a localized resource does not exist, and supports resource serialization." Listing 4 ResourceManager resourceManager = new ResourceManager("Internationalization.en-GB"+culture, Assembly.GetExecutingAssembly());

77 CultureInfo cultureInfo = new CultureInfo(culture); string message = resourceManager.GetString("ID",cultureInfo); Compiling Resource Files Refer to the section above. Note that we had created a resource file named TestResource.enGB.resx. Now let us compile the resource using the ResGen utility shipped with the Microsoft .NET Framework to create a compiled resource that would have a .resources extension. Listing 5 resgen Internationalization.en-GB.resx Internationalization.en-GB.resources When used, the above command line tool would compile the .resx file to a compiled binary .resources file for the en-GB locale. Working with Embedded Resource Files [ Back To Top ] An embedded resource is one that is embedded inside the application's code. Thus, when the application is compiled, this resource gets stored in the assembly that is generated after the compilation of the application's code. Let us create a text resource file called TextFile.txt and make the same an embedded resource by selecting the properties of the same file and then setting the Build Action in the item properties to "Embedded Resource." This means the resource will be embedded directly into the current assembly along with the code. Further, let the resource file that has just been created contain a text message. The following code snippet shows how we can retrieve the content of the resource as a string from the current executing assembly. Listing 6 public string GetResourceFromAssembly(string resourceName) { Assembly assembly = Assembly.GetExecutingAssembly(); TextReader txtReader = new StreamReader(assembly.GetManifestResourceStream(resourceName)); string str = txtReader.ReadToEnd(); txtReader.Close(); return str; } The above method accepts the fully qualified path to the resource as a parameter and returns the resource as a string from the current executing assembly. Invoke the above method as shown below. Listing 7 Response.Write(GetResourceFromAssembly("Test.TextFile.txt")); The GetResourceFromAssembly method would return the resource value from the specified resource file. It is also possible to list all the embedded resources in the assembly as shown in the section below. The following method shows how we can display the names of all the embedded resources in the current executing assembly. Listing 8 public string GetResourceNamesFromAssembly() { Assembly assembly = Assembly.GetExecutingAssembly(); string [] resourceNames = assembly.GetManifestResourceNames(); StringBuilder stringBuilder = new StringBuilder(); foreach(string str in resourceNames) { stringBuilder.Append(str); stringBuilder.Append("<BR>"); } return stringBuilder.ToString(); }

78 The above method would return all the resource names from the current executing assembly. Invoke the above method as shown in the listing below. Listing 9 Response.Write(GetResourceNamesFromAssembly()); Satellite Assemblies [ Back To Top ] An assembly is essentially a portable executable or library file containing partially compiled code for use in deployment, security and versioning in Microsoft .NET's managed environment. The assembly is compiled into the machine language instructions by the CLR. Satellite Assemblies are special assemblies that only contain resources and are associated with the main assembly. Satellite assemblies are used to store compiled localized application resources. They contain only resource data and no other code. Satellite assemblies are used to load the data dynamically depending upon the culture of the application. They can be created using the AL utility tool provided with Microsoft .NET SDK. With satellite assemblies, resources are embedded in a binary format within a DLL. This makes the resources not very visible to the user and ensures faster access. These assemblies can be deployed even after deployment of the application. Refer to the earlier sections where we had already created a resource file that was intended for UK English culture. We had then compiled the same to create a compiled resource file using the resgen utility. Now we can use the AL utility shipped with the Microsoft .NET SDK to create a satellite assembly from a compiled resource file as shown below. Listing 10 al /t:lib /culture:en-GB /embed: Internationalization.en-GB.resources /out: Internationalization.resources.dll The output file Internationalization.en-GB.resources is a satellite assembly file that is created for the en-GB locale from the compiled resource file. The .NET Framework Developer's Guide, MSDN, states, "Ideally, you should package the resources for the default or neutral assembly with the main assembly and create a separate satellite assembly for each language that your application supports." Implementing Multilingual Applications [ Back To Top ] A Multilingual application is one that provides support for multiple languages. This section discusses how we can implement a multilingual application in .NET using the concepts explained earlier. The steps for implementing a multilingual application in .NET can be summarized as the following. Create a resource file for each locale. Save the resource files with a .resx extension. Compile the resource files using resgen utility of .NET SDK to create a compiled binary resource file. Create satellite assembly using al utility of .NET SDK. Create folders for storing the satellite assembly and store the satellite assembly there. Read resources from the satellite assembly in the application's source code. First, we have to create culture specific resources in resource files. Then we can store the culture specific data in the resource file and save the same with a .resx extension. Note that the culture name should be provided in the resource file name to follow the resource file naming convention. We can use Visual Studio .NET to create a resource for a particular culture. Resource files have been explained in more detail earlier. Let us assume that a file Internationalization.en-GB.resx be created for en-GB culture and compiled (as shown in listing 4) to create the Internationalization.enGB.resources file. This file is the complied resources file. This compiled resource file can be used to create a satellite assembly. This satellite assembly can then be used by the application. Refer to code listing 9. The file Internationalization.resources.dll is a satellite assembly. This satellite assembly should now be placed in a sub folder inside the application's main folder and the name of

79 this sub folder should be the same as the name of the culture that the satellite assembly is targeted for. This satellite assembly can now be used to display locale specific information in the application. The CultureInfo class [ Back To Top ] The CultureInfo class of the .NET Framework SDK provides access to the properties of a locale. An instance of the CultureInfo class can be created by passing the culture name as a string parameter. The following code can be used to create a CultureInfo instance for French spoken in France. Listing 11 CultureInfo c = new CultureInfo("en-FR"); The following code can be used to create a CultureInfo instance for UK English locale. Listing 12 CultureInfo c = new CultureInfo("en-GB"); Configuring Localization in our Application [ Back To Top ] In order to ensure that we do not require changing the application source code each time we require to have support for a newer culture in the application, we can ensure even loose coupling by setting the culture name in the web.config file. This ensures that the application's culture settings are configurable. This information can be read by the application at run time and the appropriate culture settings set accordingly. The <appSettings> element of the web.config file can be used to specify the culture name as shown below. Listing 13 <appSettings> <add key = "Culture" value = "fr-FR"> </add> </appSettings> Or Listing 14 <appSettings> <add key = "Culture" value = "en-GB"> </add> </appSettings> Note that fr-FR refers to French language that is spoken in France while en-GB refers to English language that is spoken in Great Britain. The culture type that is specified in the web.config file can be read by using System.ConfigurationSettings.AppSettings in the source code. Note that System.Configuration.ConfigurationSettings.AppSettings is a class in the System.Configuration namespace in the system.dll assembly. The source code is provided below. Listing 15 string culture = System.Configuration.ConfigurationSettings.AppSettings["Culture"].ToString(); ResourceManager resourceManager = new ResourceManager(typeof(TestForm).Namespace.ToString()+"."+culture, Assembly.GetExecutingAssembly()); CultureInfo cultureInfo = new CultureInfo(culture); string message = resourceManager.GetString("ID",cultureInfo); Response.Write(message); In the code listing shown above, an instance of the ResourceManager class is created by passing the resource and the assembly in which the resource is embedded as parameters. Here the culture and a reference of the current executing assembly are passed to it as parameters. Then an object of the CultureInfo class is created and the culture name passed to the parameterized constructor of the

80 class. The ResourceManager class enables access to the resources for a particular culture using the GetObject and GetString methods. Now we have to call the GetString method on the ResourceManager instance and pass the ID string as key and the instance of the CultureInfo class as parameters. The resource value is returned as string and the same can now be used as needed in the application. For the sake of simplicity, I have displayed the message using Response.Write method. This concept can be used to set the text of a particular control in a specific language by reading the locale specific text from the resource. The current locale is specified in the web.config file. As an example, to set the copyright on a label control in the web from use the code provided below. Listing 16 lblCopyright.Text = resourceManager.GetString("Copyright",culture); Here the copyright message would be displayed in the label control based on the current culture that is set using the web.config file as explained earlier. Note that either the satellite assembly or the application's assembly should have the resources for all the cultures to be supported by the application.

DOT NET QUESTIONS & ANSW

Some of the questions are 1. Explain the code behind wors and contrast that using the inline style. 2. Different types of HTML,Web and server controls (also how Server control validation controls work) 4. Difference btn user and server controls 4. How server form post-back works (perhaps ask about view state as well). 5. Can the action attribute of a server-side <form> tag be set to a value and if not how can you possibly pass data from a form page to a subsequent page. 6. What is the role of global.asax. 7. How would ASP and ASP.NET apps run at the same time on the same server? 8. What are good ADO.NET object(s) to replace the ADO Recordset object. In addition to the above some couple of basic questions, a couple of additional questions listed below. Good luck! ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 1. Explain the differences between Server-side and Client-side code? 2. What type of code (server or client) is found in a Code-Behind class? 3. Should validation (did the user enter a real date) occur server-side or client-side? Why? 4. What does the "EnableViewState" property do? Why would I want it on or off? 5. What is the difference between Server.Transfer and Response.Redirect? Why would I choose one over the other? 6. Can you give an example of when it would be appropriate to use a web service as opposed to a non-serviced .NET component 7. Let's say I have an existing application written using Visual Studio 6 (VB 6, InterDev 6) and this application utilizes Windows 2000 COM+ transaction services. How would you approach migrating this application to .NET 8. Can you explain the difference between an ADO.NET Dataset and an ADO Recordset? 9. Can you give an example of what might be best suited to place in the Application_Start and Session_Start subroutines? 10. If I'm developing an application that must accomodate multiple security levels though secure login and my ASP.NET web appplication is spanned across three web-servers (using round-robbin load balancing)

81 what would be the best approach to maintain login-in state for the users? 11. What are ASP.NET Web Forms? How is this technology different than what is available though ASP (1.0-3.0)? 12. How does VB.NET/C# achieve polymorphism? 11. Can you explain what inheritance is and an example of when you might use it? 13. How would you implement inheritance using VB.NET/C#? 14. Whats an assembly 15. Describe the difference between inline and code behind - which is best in a 16. loosely coupled solution 17. Explain what a diffgram is, and a good use for one 18. Where would you use an iHTTPModule, and what are the limitations of any 19. approach you might take in implementing one 20. What are the disadvantages of viewstate/what are the benefits 21 Describe session handling in a webfarm, how does it work and what are the > limits 22. How would you get ASP.NET running in Apache web servers - why would you even do this? 23. Whats MSIL, and why should my developers need an appreciation of it if at all? 24. In what order do the events of an ASPX page execute. As a developer is it important to undertsand these events? 25. Which method do you invoke on the DataAdapter control to load your generated dataset with data? 26. Can you edit data in the Repeater control? 27. Which template must you provide, in order to display data in a Repeater control? 28. How can you provide an alternating color scheme in a Repeater control? 29. What property must you set, and what method must you call in your code, in order to bind the data from some data source to the Repeater control? 30. What base class do all Web Forms inherit from? 31. What method do you use to explicitly kill a user s session? 32 How do you turn off cookies for one page in your site? 33. Which two properties are on every validation control? 34. What tags do you need to add within the asp:datagrid tags to bind columns manually? 35. How do you create a permanent cookie? 36. What tag do you use to add a hyperlink column to the DataGrid? 37. What is the standard you use to wrap up a call to a Web service 38. Which method do you use to redirect the user to another page without performing a round trip to the client? 39. What is the transport protocol you use to call a Web service SOAP 40. True or False: A Web service can only be written in .NET 41. What does WSDL stand for? 42. What property do you have to set to tell the grid which page to go to when using the Pager object? 43. Where on the Internet would you look for Web services? 44. What tags do you need to add within the asp:datagrid tags to bind columns manually. 45. Which property on a Combo Box do you set with a column name, prior to setting the DataSource, to display data in the combo box? 46. How is a property designated as read-only? 47. Which control would you use if you needed to make sure the values in two different controls matched? 48. True or False: To test a Web service you must create a windows

82 application or Web application to consume this service? 49. How many classes can a single .NET DLL contain? ANSWEAR Alot of these answers are way to detailed to be explained in a couple of sentences...your better off researching them. I will answer the ones that can be answered pretty plainly. 3. Server controls are built-in. User controls are created by the developer to allow for the reuse of controls that need specific functionality. 4. By default all pages in .NET post back to themselves. The view state keeps the users input updated on the page. 5. No, You have to use Server.Transfer to pass the data to another page. 6. Store global information about the application 8. There are alot...but the base once are SqlConnection, OleDbConnection, etc... ---------------------------------------------------------------------------------1. Server-side code runs on the server, Client-side code runs on the client. 2. Server 3. Client...so the user doesn't have to wait for the page to be posted to the server and then returned. 4. Enables the ability to maintain the state of the page and all data within it. 5. Server.Trasfer allows you to pass variables to another page. Server.Redirect just redirects the user to another page. 6. When there is no need for a UI to perform the required task. 8. By default Datasets are disconnected. 9. Any variables that need to be set for the application or session objects. Example: For the path of a image directory Application("ImagePath") = "C:\Images\"

13. VB.NET use the Implements keyword to inherit from another class or interface. C# use : to inherit example Code: VB.NET class myClass Inherits baseClass End class C# class myClass : baseClass 14. An assembly is the collection of all information required by the runtime to execute your application. 15. Inline is mixed with the html, code-behind is separated. Use code-behind.

83 17. An XML format. Can be used by other platforms so send and receive data to a .NET application 23. Microsoft Intermediate Language 24. You mean the steps of the page lifetime? or that .NET is event driven? 25. Fill method 26. Yes 27. ItemTemplate 28. AlternatingItemTemplate 29. Set the datasource property and call the DataBind method 30. Page...but all .NET objects inherit form the Object Base Class. 31. Session.Contents.Remove 32. You can't (not that I am aware of...since there is no Page level directive to do this) 34. Set AutoGenerateColumns Property to false on the datagrid tag 36. <asp:HyperLinkColumn> 39. SOAP is preferred protocol 40. False 41. Web Services Description Language 42. CurrentPageIndex 43. www.uddi.org 45. DataTextField 46. Only a Get method...no, Set method 47. CompareValidator 48. False, the webservice comes with a test page and it provides HTTP-GET method to test. 49. Many

84

FAQNET .NET and the Microsoft .NET Framework.
Q1-What is .NET? Simply put, Microsoft® .NET is Microsoft's strategy for delivering software as a service. For complete information, read this whitepaper on the topic. An excerpt from that paper briefly describes the key points of .NET: 1. Microsoft .NET platform Includes .NET infrastructure and tools to build and operate a new generation of services, .NET user experience to enable rich clients, .NET building block services and .NET device software to enable a new generation of smart Internet devices. 2. Microsoft .NET products and services Includes Microsoft® Windows.NET (with a core integrated set of building block services), MSN.NET, personal subscription services, Microsoft® Office.NET, Microsoft® Visual Studio.NET, and Microsoft® bCentral™ for .NET. 3. Third-party .NET services A vast range of partners and developers will have the opportunity to produce corporate and vertical services built on the .NET platform. This FAQ targets the .NET Framework, which is a piece of the .NET platform's infrastructure. See the next question to learn more about the .NET Framework. Q2-What is the .NET Framework? The .NET Framework is an environment for building, deploying, and running Web Services and other applications. It consists of three main parts: the Common Language Runtime, the Framework classes, and ASP.NET. Q3-Does the .NET Framework only apply to people building Web sites? The .NET Framework enables you to create great Web applications. However, it can also help you build the same applications you build today. If you write any Windows software (using ATL/COM, MFC, Microsoft® Visual Basic®, or even standard Microsoft® Win32®), .NET offers many advantages to the way you currently build applications. Of course, if you do develop Web sites, then the .NET Framework has a lot to interest you—starting with ASP.NET. Q4-Where can I get the .NET Framework SDK? The Beta 1 of the .NET Framework SDK is now available for public download at MSDN Online Downloads. Because of its size, we offer this beta as a single download (106 MB), an 11-part download, or you can order the CD from Microsoft Developer Store: 1. United States/Canada 2. International Q5-On what platforms will the .NET Framework run? The Beta 1 version will run on Microsoft® Windows® 2000, Windows 95/98/ME, and Windows NT® 4.0. There is also a version of the .NET Framework called the .NET Compact Framework. It is designed to bring some of the capabilities of the .NET Framework to devices such as cell phones and enhanced televisions. The .NET Compact Framework will run on Windows CE and other embedded operating systems. Q6-What programming languages will the .NET Framework support? The .NET Framework is language neutral; virtually any language can target the .NET Framework. Currently, you can build .NET programs in a number of languages, including C++, Microsoft® Visual Basic.NET, _JScript®, and Microsoft's newest language—C#. A large number of third-party languages will also be available for building .NET Framework applications. These languages include COBOL, Eiffel, Perl, Python, Smalltalk, and others. Q7-What is the relationship between the .NET Framework and COM+ Services? The .NET Framework gives you full access to COM+ services, while also making it easier to build serviced components. .NET Framework components can be added to a COM+ application. There they can take advantage of automatic component services such as transactions, object pooling, queued components, events, and so on.

85 Q8-What is the relationship between the .NET Framework and DCOM? DCOM is the COM infrastructure for cross-process communication. The .NET Framework supports a number of pluggable channels and formatters for cross-process communication. When making transitions between managed and unmanaged code, the .NET Framework uses the COM infrastructure, specifically, DCOM. All scenarios using COM+ services use managed-to-unmanaged transitions, and thus use DCOM by default. The .NET Framework also supports SOAP, the Simple Object Access Protocol, for cross-process communication where interoperability is critical. Q9-Is the .NET Framework just a new name for Windows DNA? No. Windows DNA is architecture for building tightly-coupled, distributed Web applications. As the needs of distributed applications changed to require more loosely-coupled principles, Microsoft evolved the architecture to .NET. The .NET Framework is a part of the .NET architecture. Runtime Technical Questions Terminology Q10-What is the Common Language Runtime (CLR)? The Common Language Runtime is the execution engine for .NET Framework applications. It provides a number of services, including the following: 1. Code management (loading and execution) 2. Application memory isolation 3. Verification of type safety 4. Conversion of IL to native code 5. Access to metadata (enhanced type information) 6. Managing memory for managed objects 7. Enforcement of code access security 8. Exception handling, including cross-language exceptions 9. Interoperation between managed code, COM objects, and pre-existing DLLs (unmanaged code and data) 10. Automation of object layout 11. Support for developer services (profiling, debugging, and so on) Q11-What is the common type system (CTS)? The common type system is a rich type system, built into the Common Language Runtime, that supports the types and operations found in most programming languages. The common type system supports the complete implementation of a wide range of programming languages. Q12-What is the Common Language Specification (CLS)? The Common Language Specification is a set of constructs and constraints that serves as a guide for library writers and compiler writers. It allows libraries to be fully usable from any language supporting the CLS, and for those languages to integrate with each other. The Common Language Specification is a subset of the common type system. The Common Language Specification is also important to application developers who are writing code that will be used by other developers. When developers design publicly accessible APIs following the rules of the CLS, those APIs are easily used from all other programming languages that target the Common Language Runtime. Q13-What is the Microsoft Intermediate Language (MSIL)? MSIL is the CPU-independent instruction set into which .NET Framework programs are compiled. It contains instructions for loading, storing, initializing, and calling methods on objects. Combined with metadata and the common type system, MSIL allows for true cross-language integration. Prior to execution, MSIL is converted to machine code. It is not interpreted. Q14-What is managed code and managed data? Managed code is code that is written to target the services of the Common Language Runtime (see What is the Common Language Runtime?). In order to target these services, the code must provide a minimum level of information (metadata) to the runtime. All C#, Visual Basic.NET, and _JScript.NET code is managed by default. Visual Studio.NET C++ code is not managed by default, but the compiler can produce managed code by specifying a command-line switch (/CLR). Closely related to managed code is managed data—data that is allocated and de-allocated by the

86 Common Language Runtime's garbage collector. C#, Visual Basic, and _JScript.NET data is managed by default. C# data can, however, be marked as unmanaged through the use of special keywords. Visual Studio.NET C++ data is unmanaged by default (even when using the /CLR switch), but when using Managed Extensions for C++, a class can be marked as managed by using the __gc keyword. As the name suggests, this means that the memory for instances of the class is managed by the garbage collector. In addition, the class becomes a full participating member of the .NET Framework community, with the benefits and restrictions that brings. An example of a benefit is proper interoperability with classes written in other languages (for example, a managed C++ class can inherit from a Visual Basic class). An example of a restriction is that a managed class can only inherit from one base class. Assemblies Q15-What is an assembly? An assembly is the primary building block of a .NET Framework application. It is a collection of functionality that is built, versioned, and deployed as a single implementation unit (as one or more files). All managed types and resources are marked either as accessible only within their implementation unit, or as accessible by code outside that unit. Assemblies are self-describing by means of their manifest, which is an integral part of every assembly. The manifest: 1. Establishes the assembly identity (in the form of a text name), version, culture, and digital signature (if the assembly is to be shared across applications). 2. Defines what files (by name and file hash) make up the assembly implementation. 3. Specifies the types and resources that make up the assembly, including which are exported from the assembly. 4. Itemizes the compile-time dependencies on other assemblies. 5. Specifies the set of permissions required for the assembly to run properly. This information is used at run time to resolve references, enforce version binding policy, and validate the integrity of loaded assemblies. The runtime can determine and locate the assembly for any running object, since every type is loaded in the context of an assembly. Assemblies are also the unit at which code access security permissions are applied. The identity evidence for each assembly is considered separately when determining what permissions to grant the code it contains. The self-describing nature of assemblies also helps makes zero-impact install and XCOPY deployment feasible. Q16-What are private assemblies and shared assemblies? A private assembly is used only by a single application, and is stored in that application's install directory (or a subdirectory therein). A shared assembly is one that can be referenced by more than one application. In order to share an assembly, the assembly must be explicitly built for this purpose by giving it a cryptographically strong name (referred to as a shared name). By contrast, a private assembly name need only be unique within the application that uses it. By making a distinction between private and shared assemblies, we introduce the notion of sharing as an explicit decision. Simply by deploying private assemblies to an application directory, you can guarantee that that application will run only with the bits it was built and deployed with. References to private assemblies will only be resolved locally to the private application directory. There are several reasons you may elect to build and use shared assemblies, such as the ability to express version policy. The fact that shared assemblies have a cryptographically strong name means that only the author of the assembly has the key to produce a new version of that assembly. Thus, if you make a policy statement that says you want to accept a new version of an assembly, you can have some confidence that version updates will be controlled and verified by the author. Otherwise, you don’t have to accept them. For locally installed applications, a shared assembly is typically explicitly installed into the global assembly cache (a local cache of assemblies maintained by the .NET Framework). Key to the version management features of the .NET Framework is that downloaded code does not affect the execution of locally installed applications. Downloaded code is put in a special download cache and is not globally available on the machine even if some of the downloaded components are built as shared assemblies. The classes that ship with the .NET Framework are all built as shared assemblies. Q17-If I want to build a shared assembly, does that require the overhead of signing and managing key pairs?

87 Building a shared assembly does involve working with cryptographic keys. Only the public key is strictly needed when the assembly is being built. Compilers targeting the .NET Framework provide command line options (or use custom attributes) for supplying the public key when building the assembly. It is common to keep a copy of a common public key in a source database and point build scripts to this key. Before the assembly is shipped, the assembly must be fully signed with the corresponding private key. This is done using an SDK tool called SN.exe (Strong Name). Strong name signing does not involve certificates like Authenticode does. There are no third party organizations involved, no fees to pay, and no certificate chains. In addition, the overhead for verifying a strong name is much less than it is for Authenticode. However, strong names do not make any statements about trusting a particular publisher. Strong names allow you to ensure that the contents of a given assembly haven't been tampered with, and that the assembly loaded on your behalf at run time comes from the same publisher as the one you developed against. But it makes no statement about whether you can trust the identity of that publisher. Q18-What is the difference between a namespace and an assembly name? A namespace is a logical naming scheme for types in which a simple type name, such as MyType, is preceded with a dot-separated hierarchical name. Such a naming scheme is completely under the control of the developer. For example, types MyCompany.FileAccess.A and MyCompany.FileAccess.B might be logically expected to have functionality related to file access. The .NET Framework uses a hierarchical naming scheme for grouping types into logical categories of related functionality, such as the ASP.NET application framework, or remoting functionality. Design tools can make use of namespaces to make it easier for developers to browse and reference types in their code. The concept of a namespace is not related to that of an assembly. A single assembly may contain types whose hierarchical names have different namespace roots, and a logical namespace root may span multiple assemblies. In the .NET Framework, a namespace is a logical design-time naming convenience, whereas an assembly establishes the name scope for types at run time. Application Deployment and Isolation Q19-What options are available to deploy my .NET applications? The .NET Framework simplifies deployment by making zero-impact install and XCOPY deployment of applications feasible. Because all requests are resolved first to the private application directory, simply copying an application’s directory files to disk is all that is needed to run the application. No registration is required. This scenario is particularly compelling for Web applications, Web Services, and self-contained desktop applications. However, there are scenarios where XCOPY is not sufficient as a distribution mechanism. An example is when the application has little private code and relies on the availability of shared assemblies, or when the application is not locally installed (but rather downloaded on demand). For these cases, the .NET Framework provides extensive code download services and integration with the Windows Installer. The code download support provided by the .NET Framework offers several advantages over current platforms, including incremental download, code access security (no more Authenticode dialogs), and application isolation (code downloaded on behalf of one application doesn't affect other applications). The Windows Installer is another powerful deployment mechanism available to .NET applications. All of the features of Windows Installer, including publishing, advertisement, and application repair will be available to .NET applications in Windows Installer 1.5. Q20-I've written an assembly that I want to use in more than one application. Where do I deploy it? Assemblies that are to be used by multiple applications (for example, shared assemblies) are deployed to the global assembly cache. In the prerelease and Beta builds, use the /i option to the Alink SDK tool to install an assembly into the cache: al /i:myDll.dll A future version of the Windows Installer will be able to install assemblies into the global assembly cache. Q21-How can I see what assemblies are installed in the global assembly cache? The .NET Framework ships with a Windows shell extension for viewing the assembly cache. Navigating to % windir% \assembly with the Windows Explorer activates the viewer. Q22-What is an application domain?

88 An application domain (often AppDomain) is a virtual process that serves to isolate an application. All objects created within the same application scope (in other words, anywhere along the sequence of object activations beginning with the application entry point) are created within the same application domain. Multiple application domains can exist in a single operating system process, making them a lightweight means of application isolation. An OS process provides isolation by having a distinct memory address space. While this is effective, it is also expensive, and does not scale to the numbers required for large web servers. The Common Language Runtime, on the other hand, enforces application isolation by managing the memory use of code running within the application domain. This ensures that it does not access memory outside the boundaries of the domain. It is important to note that only type-safe code can be managed in this way (the runtime cannot guarantee isolation when unsafe code is loaded in an application domain). Garbage Collection Q23-What is garbage collection? Garbage collection is a mechanism that allows the computer to detect when an object can no longer be accessed. It then automatically releases the memory used by that object (as well as calling a clean-up routine, called a "finalizer," which is written by the user). Some garbage collectors, like the one used by .NET, compact memory and therefore decrease your program's working set. Q24-How does non-deterministic garbage collection affect my code? For most programmers, having a garbage collector (and using garbage collected objects) means that you never have to worry about deallocating memory, or reference counting objects, even if you use sophisticated data structures. It does require some changes in coding style, however, if you typically deallocate system resources (file handles, locks, and so forth) in the same block of code that releases the memory for an object. With a garbage collected object you should provide a method that releases the system resources deterministically (that is, under your program control) and let the garbage collector release the memory when it compacts the working set. Q25-Can I avoid using the garbage collected heap? All languages that target the runtime allow you to allocate class objects from the garbage-collected heap. This brings benefits in terms of fast allocation, and avoids the need for programmers to work out when they should explicitly 'free' each object. The CLR also provides what are called ValueTypes -- these are like classes, except that ValueType objects are allocated on the runtime stack (rather than the heap), and therefore reclaimed automatically when your code exits the procedure in which they are defined. This is how "structs" in C# operate. Managed Extensions to C++ lets you choose where class objects are allocated. If declared as managed Classes, with the __gc keyword, then they are allocated from the garbage-collected heap. If they don't include the __gc keyword, they behave like regular C++ objects, allocated from the C++ heap, and freed explicitly with the "free" method. For additional information about Garbage Collection see: 1. Garbage Collection: Automatic Memory Management in the Microsoft .NET Framework 2. Garbage Collection—Part 2: Automatic Memory Management in the Microsoft .NET Framework Remoting Q26-How do in-process and cross-process communication work in the Common Language Runtime? There are two aspects to in-process communication: between contexts within a single application domain, or across application domains. Between contexts in the same application domain, proxies are used as an interception mechanism. No marshaling/serialization is involved. When crossing application domains, we do marshaling/serialization using the runtime binary protocol. Cross-process communication uses a pluggable channel and formatter protocol, each suited to a specific purpose. 1. If the developer specifies an endpoint using the tool soapsuds.exe to generate a metadata proxy, HTTP channel with SOAP formatter is the default. 2. If a developer is doing explicit remoting in the managed world, it is necessary to be explicit about what channel and formatter to use. This may be expressed administratively, through configuration files, or with API calls to load specific channels. Options are:

89 HTTP channel w/ SOAP formatter (HTTP works well on the Internet, or anytime traffic must travel through firewalls) TCP channel w/ binary formatter (TCP is a higher performance option for local-area networks (LANs)) SMTP channel w/ SOAP formatter (only makes sense cross-machine) When making transitions between managed and unmanaged code, the COM infrastructure (specifically, DCOM) is used for remoting. In interim releases of the CLR, this applies also to serviced components (components that use COM+ services). Upon final release, it should be possible to configure any remotable component. Distributed garbage collection of objects is managed by a system called "leased based lifetime." Each object has a lease time, and when that time expires, the object is disconnected from the remoting infrastructure of the CLR. Objects have a default renew time—the lease is renewed when a successful call is made from the client to the object. The client can also explicitly renew the lease. Interoperability Q27-Can I use COM objects from a .NET Framework program? Yes. Any COM component you have deployed today can be used from managed code, and in common cases the adaptation is totally automatic. Specifically, COM components are accessed from the .NET Framework by use of a runtime callable wrapper (RCW). This wrapper turns the COM interfaces exposed by the COM component into .NET Framework-compatible interfaces. For OLE automation interfaces, the RCW can be generated automatically from a type library. For non-OLE automation interfaces, a developer may write a custom RCW and manually map the types exposed by the COM interface to .NET Framework-compatible types. Q28-Can .NET Framework components be used from a COM program? Yes. Managed types you build today can be made accessible from COM, and in the common case the configuration is totally automatic. There are certain new features of the managed development environment that are not accessible from COM. For example, static methods and parameterized constructors cannot be used from COM. In general, it is a good idea to decide in advance who the intended user of a given type will be. If the type is to be used from COM, you may be restricted to using those features that are COM accessible. Depending on the language used to write the managed type, it may or may not be visible by default. Specifically, .NET Framework components are accessed from COM by using a COM callable wrapper (CCW). This is similar to an RCW (see previous question), but works in the opposite direction. Again, if the .NET Framework development tools cannot automatically generate the wrapper, or if the automatic behavior is not what you want, a custom CCW can be developed. Q29-Can I use the Win32 API from a .NET Framework program? Yes. Using P/Invoke, .NET Framework programs can access native code libraries by means of static DLL entry points. Here is an example of C# calling the Win32 MessageBox function: using System; using System.Runtime.InteropServices; class MainApp { [DllImport("user32.dll", EntryPoint="MessageBox")] public static extern int MessageBox(int hWnd, String strMessage, String strCaption, uint uiType); public static void Main() { MessageBox( 0, "Hello, this is PInvoke in operation!", ".NET", 0 ); } } Security Q30-What do I have to do to make my code work with the security system? Usually, not a thing—most applications will run safely and will not be exploitable by malicious attacks. By simply using the standard class libraries to access resources (like files) or perform protected operations (such as a reflection on private members of a type), security will be enforced by

90 these libraries. The one simple thing application developers may want to do is include a permission request (a form of declarative security) to limit the permissions their code may receive (to only those it requires). This also ensures that if the code is allowed to run, it will do so with all the permissions it needs. Only developers writing new base class libraries that expose new kinds of resources need to work directly with the security system. Instead of all code being a potential security risk, code access security constrains this to a very small bit of code that explicitly overrides the security system.

Q31-Why does my code get a security exception when I run it from a network shared drive? Default security policy gives only a restricted set of permissions to code that comes from the local intranet zone. This zone is defined by the Internet Explorer security settings, and should be configured to match the local network within an enterprise. Since files named by UNC or by a mapped drive (such as with the NET USE command) are being sent over this local network, they too are in the local intranet zone. The default is set for the worst case of an unsecured intranet. If your intranet is more secure you can modify security policy (with the CASPol tool) to grant more permissions to the local intranet, or to portions of it (such as specific machine share names). Q32-How do I make it so that code runs when the security system is stopping it? Security exceptions occur when code attempts to perform actions for which it has not been granted permission. Permissions are granted based on what is known about code; especially its location. For example, code run from the Internet is given fewer permissions than that run from the local machine because experience has proven that it is generally less reliable. So, to allow code to run that is failing due to security exceptions, you must increase the permissions granted to it. One simple way to do so is to move the code to a more trusted location (such as the local file system). But this won't work in all cases (web applications are a good example, and intranet applications on a corporate network are another). So, instead of changing the code's location, you can also change security policy to grant more permissions to that location. This is done using either the code access security policy utility (caspol.exe) or the graphical administration tool (available in Beta 2 and beyond). If you are the code's developer or publisher, you may also digitally sign it and then modify security policy to grant more permissions to code bearing that signature. When taking any of these actions, however, remember that code is given fewer permissions because it is not from an identifiably trustworthy source—before you move code to your local machine or change security policy, you should be sure that you trust the code to not perform malicious or damaging actions. Q33-How do I administer security for my machine? For an enterprise? Currently, the CASPol command line tool is the only way to administer security. Security policy consists of two levels: machine, and by-user. There are plans to provide a full-featured administration tool, as well as support for enterprise policy administration, as part of the first version of the .NET Framework. Q34-How does evidence-based security work with Windows 2000 security? Evidence-based security (which authorizes code) works together with Windows 2000 security (which is based on log on identity). For example, to access a file, managed code must have both the code access security file permission and must also be running under a log on identity that has NTFS file access rights. The managed libraries that are included with the .NET Framework also provide classes for rolebased security. These allow the application to work with Windows log on identities and user groups.

91

.NET Remoting Interview Questions
1. What’s a Windows process? It’s an application that’s running and had been allocated memory. 2. What’s typical about a Windows process in regards to memory allocation? Each process is allocated its own block of available RAM space, no process can access another process’ code or data. If the process crashes, it dies alone without taking the entire OS or a bunch of other applications down. 3. Why do you call it a process? What’s different between process and application in .NET, not common computer usage, terminology? A process is an instance of a running application. An application is an executable on the hard drive or network. There can be numerous processes launched of the same application (5 copies of Word running), but 1 process can run just 1 application. 4. What distributed process frameworks outside .NET do you know? Distributed Computing Environment/Remote Procedure Calls (DEC/RPC), Microsoft Distributed Component Object Model (DCOM), Common Object Request Broker Architecture (CORBA), and Java Remote Method Invocation (RMI). 5. What are possible implementations of distributed applications in .NET? .NET Remoting and ASP.NET Web Services. If we talk about the Framework Class Library, noteworthy classes are in System.Runtime.Remoting and System.Web.Services. 6. When would you use .NET Remoting and when Web services? Use remoting for more efficient exchange of information when you control both ends of the application. Use Web services for openprotocol-based information exchange when you are just a client or a server with the other end belonging to someone else. 7. What’s a proxy of the server object in .NET Remoting? It’s a fake copy of the server object that resides on the client side and behaves as if it was the server. It handles the communication between real server object and the client object. This process is also known as marshaling. 8. What are remotable objects in .NET Remoting? Remotable objects are the objects that can be marshaled across the application domains. You can marshal by value, where a deep copy of the object is created and then passed to the receiver. You can also marshal by reference, where just a reference to an existing object is passed. 9. What are channels in .NET Remoting? Channels represent the objects that transfer the other serialized objects from one application domain to another and from one computer to another, as well as one process to another on the same box. A channel must exist before an object can be transferred. 10. What security measures exist for .NET Remoting in System.Runtime.Remoting? None. Security should be taken care of at the application level. Cryptography and other security techniques can be applied at application or server level. 11. What is a formatter? A formatter is an object that is responsible for encoding and serializing data into messages on one end, and deserializing and decoding messages into data on the other end. 12. Choosing between HTTP and TCP for protocols and Binary and SOAP for formatters, what are the trade-offs? Binary over TCP is the most effiecient, SOAP over HTTP is the most interoperable. 13. What’s SingleCall activation mode used for? If the server object is instantiated for responding to just one single request, the request should be made in SingleCall mode. 14. What’s Singleton activation mode? A single object is instantiated regardless of the number of clients accessing it. Lifetime of this object is determined by lifetime lease. 15. How do you define the lease of the object? By implementing ILease interface when writing the class code. 16. Can you configure a .NET Remoting object via XML file? Yes, via machine.config and application level .config file (or web.config in ASP.NET). Application-level XML settings take precedence over machine.config. 17. How can you automatically generate interface for the remotable object in .NET with Microsoft tools? Use the Soapsuds tool.

92

ASP.NET DataGrid questions
1. What is datagrid? The DataGrid Web server control is a powerful tool for displaying information from a data source. It is easy to use; you can display editable data in a professional-looking grid by setting only a few properties. At the same time, the grid has a sophisticated object model that provides you with great flexibility in how you display the data. 2. What’s the difference between the System.Web.UI.WebControls.DataGrid and and System.Windows.Forms.DataGrid? The Web UI control does not inherently support master-detail data structures. As with other Web server controls, it does not support two-way data binding. If you want to update data, you must write code to do this yourself. You can only edit one row at a time. It does not inherently support sorting, although it raises events you can handle in order to sort the grid contents. You can bind the Web Forms DataGrid to any object that supports the IEnumerable interface. The Web Forms DataGrid control supports paging. It is easy to customize the appearance and layout of the Web Forms DataGrid control as compared to the Windows Forms one. 3. How do you customize the column content inside the datagrid? If you want to customize the content of a column, make the column a template column. Template columns work like item templates in the DataList or Repeater control, except that you are defining the layout of a column rather than a row. 4. How do you apply specific formatting to the data inside the cells? You cannot specify formatting for columns generated when the grid’s AutoGenerateColumns property is set to true, only for bound or template columns. To format, set the column’s DataFormatString property to a string-formatting expression suitable for the data type of the data you are formatting. 5. How do you hide the columns? One way to have columns appear dynamically is to create them at design time, and then to hide or show them as needed. You can do this by setting a column’s Visible property. 6. How do you display an editable drop-down list? Displaying a drop-down list requires a template column in the grid. Typically, the ItemTemplate contains a control such as a data-bound Label control to show the current value of a field in the record. You then add a drop-down list to the EditItemTemplate. In Visual Studio, you can add a template column in the Property builder for the grid, and then use standard template editing to remove the default TextBox control from the EditItemTemplate and drag a DropDownList control into it instead. Alternatively, you can add the template column in HTML view. After you have created the template column with the drop-down list in it, there are two tasks. The first is to populate the list. The second is to preselect the appropriate item in the list — for example, if a book’s genre is set to “fiction,” when the drop-down list displays, you often want “fiction” to be preselected. 7. How do you check whether the row data has been changed? The definitive way to determine whether a row has been dirtied is to handle the changed event for the controls in a row. For example, if your grid row contains a TextBox control, you can respond to the control’s TextChanged event. Similarly, for check boxes, you can respond to a CheckedChanged event. In the handler for these events, you maintain a list of the rows to be updated. Generally, the best strategy is to track the primary keys of the affected rows. For example, you can maintain an ArrayList object that contains the primary keys of the rows to update. This is just a brief on dealing with ASP.NET DataGrid control. The full version of the document and the sample code is available on MSDN.

93

ASP.NET questions, part 2
1. Whats an assembly? Assemblies are the building blocks of .NET Framework applications; they form the fundamental unit of deployment, version control, reuse, activation scoping, and security permissions. An assembly is a collection of types and resources that are built to work together and form a logical unit of functionality. An assembly provides the common language runtime with the information it needs to be aware of type implementations. To the runtime, a type does not exist outside the context of an assembly. 2. Describe the difference between inline and code behind - which is best in a loosely coupled solution? ASP.NET supports two modes of page development: Page logic code that is written inside <script runat=server> blocks within an .aspx file and dynamically compiled the first time the page is requested on the server. Page logic code that is written within an external class that is compiled prior to deployment on a server and linked "behind" the .aspx file at run time. 3. Explain what a diffgram is, and a good use for one? A DiffGram is an XML format that is used to identify current and original versions of data elements. The DataSet uses the DiffGram format to load and persist its contents, and to serialize its contents for transport across a network connection. When a DataSet is written as a DiffGram, it populates the DiffGram with all the necessary information to accurately recreate the contents, though not the schema, of the DataSet, including column values from both the Original and Current row versions, row error information, and row order. 4. Where would you use an iHTTPModule, and what are the limitations of anyapproach you might take in implementing one? One of ASP.NET’s most useful features is the extensibility of the HTTP pipeline, the path that data takes between client and server. You can use them to extend your ASP.NET applications by adding pre- and post-processing to each HTTP request coming into your application. For example, if you wanted custom authentication facilities for your application, the best technique would be to intercept the request when it comes in and process the request in a custom HTTP module. 9. In what order do the events of an ASPX page execute. As a developer is it important to undertsand these events? Every Page object (which your .aspx page is) has nine events, most of which you will not have to worry about in your day to day dealings with ASP.NET. The three that you will deal with the most are: Page_Init, Page_Load, Page_PreRender. 10.Which method do you invoke on the DataAdapter control to load your generated dataset with data? System.Data.Common.DataAdapter.Fill(System.Data.DataSet); If my DataAdapter is sqlDataAdapter and my DataSet is dsUsers then it is called this way: sqlDataAdapter.Fill(dsUsers); 11. Which template must you provide, in order to display data in a Repeater control? ItemTemplate 12. How can you provide an alternating color scheme in a Repeater control? AlternatingItemTemplate Like the ItemTemplate element, but rendered for every other row (alternating items) in the Repeater control. You can specify a different appearance for the AlternatingItemTemplate element by setting its style properties. 13. What property must you set, and what method must you call in your code, in order to bind the data from some data source to the Repeater control? You must set the DataMember property which Gets or sets the specific table in the DataSource to bind to the control and the DataBind method to bind data from a source to a server control. This method is commonly used after retrieving a data set through a database query. 14. What base class do all Web Forms inherit from? System.Web.UI.Page 15. What method do you use to explicitly kill a user’s session? The Abandon method destroys all the objects stored in a Session object and releases their resources. If you do not call the Abandon method explicitly, the server destroys these objects when the session times out. Syntax: Session.Abandon

94 16. How do you turn off cookies for one page in your site? Use the Cookie.Discard Property which Gets or sets the discard flag set by the server. When true, this property instructs the client application not to save the Cookie on the user’s hard disk when a session ends. 17. Which two properties are on every validation control? ControlToValidate & ErrorMessage properties 18. What tags do you need to add within the asp:datagrid tags to bind columns manually? 19. How do you create a permanent cookie? Setting the Expires property to MinValue means that the Cookie never expires. 22. Which method do you use to redirect the user to another page without performing a round trip to the client? Server.transfer() 23. What is the transport protocol you use to call a Web service? SOAP. Transport Protocols: It is essential for the acceptance of Web Services that they are based on established Internet infrastructure. This in fact imposes the usage of of the HTTP, SMTP and FTP protocols based on the TCP/IP family of transports. Messaging Protocol: The format of messages exchanged between Web Services clients and Web Services should be vendor neutral and should not carry details about the technology used to implement the service. Also, the message format should allow for extensions and different bindings to specific transport protocols. SOAP and ebXML Transport are specifications which fulfill these requirements. We expect that the W3C XML Protocol Working Group defines a successor standard. 24. True or False: A Web service can only be written in .NET. False. 25. What does WSDL stand for? Web Services Description Language 26. What property do you have to set to tell the grid which page to go to when using the Pager object? 27. Where on the Internet would you look for Web services? UDDI repositaries like uddi.microsoft.com, IBM UDDI node, UDDI Registries in Google Directory, enthusiast sites like XMethods.net. 28. What tags do you need to add within the asp:datagrid tags to bind columns manually? Column tag and an ASP:databound tag. 29. Which property on a Combo Box do you set with a column name, prior to setting the DataSource, to display data in the combo box? 30. How is a property designated as read-only? In VB.NET: Public ReadOnly Property PropertyName As ReturnType Get ‘Your Property Implementation goes in here End Get End Property in C# public returntype PropertyName { get{ //property implementation goes here } // Do not write the set implementation } 31. Which control would you use if you needed to make sure the values in two different controls matched? Use the CompareValidator control to compare the values of 2 different controls. 32. True or False: To test a Web service you must create a windows application or Web application to consume this service? False. 33. How many classes can a single .NET DLL contain? Unlimited.

95

.NET and COM interop questions
1. Describe the advantages of writing a managed code application instead of unmanaged one. What’s involved in certain piece of code being managed? The advantages include automatic garbage collection, memory management, support for versioning and security. These advantages are provided through .NET FCL and CLR, while with the unmanaged code similar capabilities had to be implemented through third-party libraries or as a part of the application itself. 2. Are COM objects managed or unmanaged? Since COM objects were written before .NET, apparently they are unmanaged. 3. So can a COM object talk to a .NET object? Yes, through Runtime Callable Wrapper (RCW) or PInvoke. 4. How do you generate an RCW from a COM object? Use the Type Library Import utility shipped with SDK. tlbimp COMobject.dll /out:.NETobject.dll or reference the COM library from Visual Studio in your project. 5. I can’t import the COM object that I have on my machine. Did you write that object? You can only import your own objects. If you need to use a COM component from another developer, you should obtain a Primary Interop Assembly (PIA) from whoever authored the original object. 6. How do you call unmanaged methods from your .NET code through PInvoke? Supply a DllImport attribute. Declare the methods in your .NET code as static extern. Do not implement the methods as they are implemented in your unmanaged code, you’re just providing declarations for method signatures. 7. Can you retrieve complex data types like structs from the PInvoke calls? Yes, just make sure you re-declare that struct, so that managed code knows what to do with it. 8. I want to expose my .NET objects to COM objects. Is that possible? Yes, but few things should be considered first. Classes should implement interfaces explicitly. Managed types must be public. Methods, properties, fields, and events that are exposed to COM must be public. Types must have a public default constructor with no arguments to be activated from COM. Types cannot be abstract. 9. Can you inherit a COM class in a .NET application? The .NET Framework extends the COM model for reusability by adding implementation inheritance. Managed types can derive directly or indirectly from a COM coclass; more specifically, they can derive from the runtime callable wrapper generated by the runtime. The derived type can expose all the method and properties of the COM object as well as methods and properties implemented in managed code. The resulting object is partly implemented in managed code and partly implemented in unmanaged code. 10. Suppose I call a COM object from a .NET applicaiton, but COM object throws an error. What happens on the .NET end? COM methods report errors by returning HRESULTs; .NET methods report them by throwing exceptions. The runtime handles the transition between the two. Each exception class in the .NET Framework maps to an HRESULT.

96

Garbage Collection
Implementing proper resource management for your applications can be a difficult, tedious task. It can distract your concentration from the real problems that you're trying to solve. Wouldn't it be wonderful if some mechanism existed that simplified the mind-numbing task of memory management for the developer? Fortunately, in .NET there is: garbage collection (GC). Let's back up a minute. Every program uses resources of one sort or another—memory buffers, screen space, network connections, database resources, and so on. In fact, in an object-oriented environment, every type identifies some resource available for your program's use. To use any of these resources requires that memory be allocated to represent the type. The steps required to access a resource are as follows: 1. 2. 3. 4. 5. Allocate memory for the type that represents the resource. Initialize the memory to set the initial state of the resource and to make the resource usable. Use the resource by accessing the instance members of the type (repeat as necessary). Tear down the state of the resource to clean up. Free the memory.

This seemingly simple paradigm has been one of the major sources of programming errors. After all, how many times have you forgotten to free memory when it is no longer needed or attempted to use memory after you've already freed it? These two bugs are worse than most other application bugs because what the consequences will be and when those consequences will occur are typically unpredictable. For other bugs, when you see your application misbehaving, you just fix it. But these two bugs cause resource leaks (memory consumption) and object corruption (destabilization), making your application perform in unpredictable ways at unpredictable times. In fact, there are many tools (such as the Task Manager, the System Monitor ActiveX® Control, CompuWare's BoundsChecker, and Rational's Purify) that are specifically designed to help developers locate these types of bugs. As I examine GC, you'll notice that it completely absolves the developer from tracking memory usage and knowing when to free memory. However, the garbage collector doesn't know anything about the resource represented by the type in memory. This means that a garbage collector can't know how to perform step four—tearing down the state of a resource. To get a resource to clean up properly, the developer must write code that knows how to properly clean up a resource. In the .NET Framework, the developer writes this code in a Close, Dispose, or Finalize method, which I'll describe later. However, as you'll see later, the garbage collector can determine when to call this method automatically. Also, many types represent resources that do not require any cleanup. For example, a Rectangle resource can be completely cleaned up simply by destroying the left, right, width, and height fields maintained in the type's memory. On the other hand, a type that represents a file resource or a network connection resource will require the execution of some explicit clean up code when the resource is to be destroyed. I will explain how to accomplish all of this properly. For now, let's examine how memory is allocated and how resources are initialized. Resource Allocation The Microsoft® .NET common language runtime requires that all resources be allocated from the managed heap. This is similar to a C-runtime heap except that you never free objects from the managed heap—objects are automatically freed when they are no longer needed by the application. This, of course, raises the question: how does the managed heap know when an object is no longer in use by the application? I will address this question shortly. There are several GC algorithms in use today. Each algorithm is fine-tuned for a particular environment in order to provide the best performance. This article concentrates on the GC algorithm that is used by the common language runtime. Let's start with the basic concepts. When a process is initialized, the runtime reserves a contiguous region of address space that initially has no storage allocated for it. This address space region is the managed heap. The heap also maintains a pointer, which I'll call the NextObjPtr. This pointer indicates where the next object is to be allocated within the heap. Initially, the NextObjPtr is set to the base address of the reserved

97 address space region. An application creates an object using the new operator. This operator first makes sure that the bytes required by the new object fit in the reserved region (committing storage if necessary). If the object fits, then NextObjPtr points to the object in the heap, this object's constructor is called, and the new operator returns the address of the object.

Figure 1 Managed Heap At this point, NextObjPtr is incremented past the object so that it points to where the next object will be placed in the heap. Figure 1 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). Now let's look at how the C-runtime heap allocates memory. In a C-runtime heap, allocating memory for an object requires walking though a linked list of data structures. Once a large enough block is found, that block has to be split, and pointers in the linked list nodes must be modified to keep everything intact. For the managed heap, allocating an object simply means adding a value to a pointer—this is blazingly fast by comparison. In fact, allocating an object from the managed heap is nearly as fast as allocating memory from a thread's stack! So far, it sounds like the managed heap is far superior to the C-runtime heap due to its speed and simplicity of implementation. Of course, the managed heap gains these advantages because it makes one really big assumption: address space and storage are infinite. This assumption is (without a doubt) ridiculous, and there must be a mechanism employed by the managed heap that allows the heap to make this assumption. This mechanism is called the garbage collector. Let's see how it works. When an application calls the new operator to create an object, there may not be enough address space left in the region to allocate to the object. The heap detects this by adding the size of the new object to NextObjPtr. If NextObjPtr is beyond the end of the address space region, then the heap is full and a collection must be performed. In reality, a collection occurs when generation 0 is completely full. Briefly, a generation is a mechanism implemented by the garbage collector in order to improve performance. The idea is that newly created objects are part of a young generation, and objects created early in the application's lifecycle are in an old generation. Separating objects into generations can allow the garbage collector to collect specific generations instead of collecting all objects in the managed heap. Generations will be discussed in more detail in Part 2 of this article. The Garbage Collection Algorithm The garbage collector checks to see if there are any objects in the heap that are no longer being used by the application. If such objects exist, then the memory used by these objects can be reclaimed. (If no more memory is available for the heap, then the new operator throws an OutOfMemoryException.) How does the garbage collector know if the application is using an object or not? As you might imagine, this isn't a simple question to answer. Every application has a set of roots. Roots identify storage locations, which refer to objects on the managed heap or to objects that are set to null. For example, all the global and static object pointers in an application are considered part of the application's roots. In addition, any local variable/parameter object pointers on a thread's stack are considered part of the application's roots. Finally, any CPU registers containing pointers to objects in the managed heap are also considered part of the application's roots. The list of active roots is maintained by the just-in-time (JIT) compiler and common language runtime, and is made accessible to the garbage collector's algorithm. When the garbage collector starts running, it makes the assumption that all objects in the heap are garbage. In other words, it assumes that none of the application's roots refer to any objects in the heap. Now, the garbage collector starts walking the roots and building a graph of all objects reachable from the roots. For example, the garbage collector may locate a global variable that points to an object in the heap.

98 Figure 2 shows a heap with several allocated objects where the application's roots refer directly to objects A, C, D, and F. All of these objects become part of the graph. When adding object D, the collector notices that this object refers to object H, and object H is also added to the graph. The collector continues to walk through all reachable objects recursively.

Figure 2 Allocated Objects in Heap Once this part of the graph is complete, the garbage collector checks the next root and walks the objects again. As the garbage collector walks from object to object, if it attempts to add an object to the graph that it previously added, then the garbage collector can stop walking down that path. This serves two purposes. First, it helps performance significantly since it doesn't walk through a set of objects more than once. Second, it prevents infinite loops should you have any circular linked lists of objects. Once all the roots have been checked, the garbage collector's graph contains the set of all objects that are somehow reachable from the application's roots; any objects that are not in the graph are not accessible by the application, and are therefore considered garbage. The garbage collector now walks through the heap linearly, looking for contiguous blocks of garbage objects (now considered free space). The garbage collector then shifts the non-garbage objects down in memory (using the standard memcpy function that you've known for years), removing all of the gaps in the heap. Of course, moving the objects in memory invalidates all pointers to the objects. So the garbage collector must modify the application's roots so that the pointers point to the objects' new locations. In addition, if any object contains a pointer to another object, the garbage collector is responsible for correcting these pointers as well. Figure 3 shows the managed heap after a collection.

Figure 3 Managed Heap after Collection After all the garbage has been identified, all the non-garbage has been compacted, and all the nongarbage pointers have been fixed-up, the NextObjPtr is positioned just after the last non-garbage object. At this point, the new operation is tried again and the resource requested by the application is successfully created. As you can see, a GC generates a significant performance hit, and this is the major downside of using a managed heap. However, keep in mind that GCs only occur when the heap is full and, until then, the managed heap is significantly faster than a C-runtime heap. The runtime's garbage collector also offers some optimizations that greatly improve the performance of garbage collection.

99 I'll discuss these optimizations in Part 2 of this article when I talk about generations. There are a few important things to note at this point. You no longer have to implement any code that manages the lifetime of any resources that your application uses. And notice how the two bugs I discussed at the beginning of this article no longer exist. First, it is not possible to leak resources, since any resource not accessible from your application's roots can be collected at some point. Second, it is not possible to access a resource that is freed, since the resource won't be freed if it is reachable. If it's not reachable, then your application has no way to access it. The code in Figure 4 demonstrates how resources are allocated and managed. If GC is so great, you might be wondering why it isn't in ANSI C++. The reason is that a garbage collector must be able to identify an application's roots and must also be able to find all object pointers. The problem with C++ is that it allows casting a pointer from one type to another, and there's no 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 the metadata information is used to determine which members of an object refer to other objects. Finalization The garbage collector offers an additional feature that you may want to take advantage of: finalization. Finalization allows a resource to gracefully clean up after itself when it is being collected. By using finalization, a resource representing a file or network connection is able to clean itself up properly when the garbage collector decides to free the resource's memory. Here is an oversimplification of what happens: when the garbage collector detects that an object is garbage, the garbage collector calls the object's Finalize method (if it exists) and then the object's memory is reclaimed. For example, let's say you have the following type (in C#): public class BaseObj { public BaseObj() { } protected override void Finalize() { // Perform resource cleanup code here... // Example: Close file/Close network connection Console.WriteLine("In Finalize."); } } 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 object is garbage. When that happens, the garbage collector will see that the type has a Finalize method and will call the method, causing "In Finalize" to appear in the console window and reclaiming the memory block used by this object. Many developers who are used to programming in C++ draw an immediate correlation between a destructor and the Finalize method. However, let me warn you right now: object finalization and destructors have very different semantics and it is best to forget everything you know about destructors when thinking about finalization. Managed objects never have destructors—period. When designing a type it is best to avoid using a Finalize method. There are several reasons for this:  Finalizable objects get promoted to older generations, which increases memory pressure and prevents the object's memory from being collected when the garbage collector determines the object is garbage. In addition, all objects referred to directly or indirectly by this object get promoted as well. Generations and promotions will be discussed in Part 2 of this article. Finalizable objects take longer to allocate. Forcing the garbage collector to execute a Finalize method can significantly hurt performance. Remember, each object is finalized. So if I have an array of 10,000 objects, each object must have its Finalize method called. Finalizable objects may refer to other (non-finalizable) objects, prolonging their lifetime unnecessarily. In fact, you might want to consider breaking a type into two different types: a lightweight type with a Finalize method that doesn't refer to any other objects, and a separate type without a Finalize method that does refer to other objects.

 

100   You have no control over when the Finalize method will execute. The object may hold on to resources until the next time the garbage collector runs. When an application terminates, some objects are still reachable and will not have their Finalize method called. This can happen if background threads are using the objects or if objects are created during application shutdown or AppDomain unloading. In addition, by default, Finalize methods are not called for unreachable objects when an application exits so that the application may terminate quickly. Of course, all operating system resources will be reclaimed, but any objects in the managed heap are not able to clean up gracefully. You can change this default behavior by calling the System.GC type's RequestFinalizeOnShutdown method. However, you should use this method with care since calling it means that your type is controlling a policy for the entire application. The runtime doesn't make any guarantees as to the order in which Finalize methods are called. For example, let's say there is an object that contains a pointer to an inner object. The garbage collector has detected that both objects are garbage. Furthermore, say that the inner object's Finalize method gets called first. Now, the outer object's Finalize method is allowed to access the inner object and call methods on it, but the inner object has been finalized and the results may be unpredictable. For this reason, it is strongly recommended that Finalize methods not access any inner, member objects.

If you determine that your type must implement a Finalize method, then make sure the code executes as quickly as possible. Avoid all actions that would block the Finalize method, including any thread synchronization operations. Also, if you let any exceptions escape the Finalize method, the system just assumes that the Finalize method returned and continues calling other objects' Finalize methods. When the compiler generates code for a constructor, the compiler automatically inserts a call to the base type's constructor. Likewise, when a C++ compiler generates code for a destructor, the compiler automatically inserts a call to the base type's destructor. However, as I've said before, Finalize methods are different from destructors. The compiler has no special knowledge about a Finalize method, so the compiler does not automatically generate code to call a base type's Finalize method. If you want this behavior—and frequently you do—then you must explicitly call the base type's Finalize method from your type's Finalize method: public class BaseObj { public BaseObj() { } protected override void Finalize() { Console.WriteLine("In Finalize."); base.Finalize(); // Call base type's Finalize } } Note that you'll usually call the base type's Finalize method as the last statement in the derived type's Finalize method. This keeps the base object alive as long as possible. Since calling a base type Finalize method is common, C# has a syntax that simplifies your work. In C#, the following code 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++ language's syntax for defining a destructor. But remember, C# doesn't support destructors. Don't let the identical syntax fool you. Finalization Internals

101 On the surface, finalization seems pretty straightforward: you create an object and when the object is collected, the object's Finalize method is called. But there is more to finalization than this. When an application creates a new object, the new operator allocates the memory from the heap. If the object's type contains a Finalize method, then a pointer to the object is placed on the finalization queue. The finalization queue is an internal data structure controlled by the garbage collector. Each entry in the queue points to an object that should have its Finalize method called before the object's memory can be reclaimed. Figure 5 shows a heap containing several objects. Some of these objects are reachable from the application's roots, and some are not. When objects C, E, F, I, and J were created, the system detected that these objects had Finalize methods and pointers to these objects were added to the finalization queue.

Figure 5 A Heap with Many Objects When a GC occurs, objects B, E, G, H, I, and J are determined to be garbage. The garbage collector scans the finalization queue looking for pointers to these objects. When a pointer is found, the pointer is removed from the finalization queue and appended to the freachable queue (pronounced "F-reachable"). The freachable queue is another internal data structure controlled by the garbage collector. Each pointer in the freachable queue identifies an object that is ready to have its Finalize method called. After the collection, the managed heap looks like Figure 6. Here, you see that the memory occupied by objects B, G, and H has been reclaimed because these objects did not have a Finalize method that needed to be called. However, the memory occupied by objects E, I, and J could not be reclaimed because their Finalize method has not been called yet.

Figure 6 Managed Heap after Garbage Collection There is a special runtime thread dedicated to calling Finalize methods. When the freachable queue is empty (which is usually the case), this thread sleeps. But when entries appear, this thread wakes, removes each entry from the queue, and calls each object's Finalize method. Because of this, you should not execute any code in a Finalize method that makes any assumption about the thread that's executing the code. For example, avoid accessing thread local storage in the Finalize method.

102 The interaction of the finalization queue and the freachable queue is quite fascinating. First, let me tell you how the freachable queue got its name. The f is obvious and stands for finalization; every entry in the freachable queue should have its Finalize method called. The "reachable" part of the name means that the objects are reachable. To put it another way, the freachable queue is considered to be a root just like global and static variables are roots. Therefore, if an object is on the freachable queue, then the object is reachable and is not garbage. In short, when an object is not reachable, the garbage collector considers the object garbage. Then, when the garbage collector moves an object's entry from the finalization queue to the freachable queue, the object is no longer considered garbage and its memory is not reclaimed. At this point, the garbage collector has finished identifying garbage. Some of the objects identified as garbage have been reclassified as not garbage. The garbage collector compacts the reclaimable memory and the special runtime thread empties the freachable queue, executing each object's Finalize method.

Figure 7 Managed Heap after Second Garbage Collection The next time the garbage collector is invoked, it sees that the finalized objects are truly garbage, since the application's roots don't point to it and the freachable queue no longer points to it. Now the memory for the object is simply reclaimed. The important thing to understand here is that two GCs are required to reclaim memory used by objects that require finalization. In reality, more than two collections may be necessary since the objects could get promoted to an older generation. Figure 7 shows what the managed heap looks like after the second GC. Resurrection The whole concept of finalization is fascinating. However, there is more to it than what I've described so far. You'll notice in the previous section that when an application is no longer accessing a live object, the garbage collector considers the object to be dead. However, if the object requires finalization, the object is considered live again until it is actually finalized, and then it is permanently dead. In other words, an object requiring finalization dies, lives, and then dies again. This is a very interesting phenomenon called resurrection. Resurrection, as its name implies, allows an object to come back from the dead. I've already described a form of resurrection. When the garbage collector places a reference to the object on the freachable queue, the object is reachable from a root and has come back to life. Eventually, the object's Finalize method is called, no roots point to the object, and the object is dead forever after. But what if an object's Finalize method executed code that placed a pointer to the object in a global or static variable? public class BaseObj { protected override void Finalize() { Application.ObjHolder = this; } } class Application { static public Object ObjHolder; ••• }

// Defaults to null

103 In this case, when the object's Finalize method executes, a pointer to the object is placed in a root and the object is reachable from the application's code. This object is now resurrected and the garbage collector will not consider the object to be garbage. The application is free to use the object, but it is very important to note that the object has been finalized and that using the object may cause unpredictable results. Also note: if BaseObj contained members that pointed to other objects (either directly or indirectly), all objects would be resurrected, since they are all reachable from the application's roots. However, be aware that some of these other objects may also have been finalized. In fact, when designing your own object types, objects of your type can get finalized and resurrected totally out of your control. Implement your code so that you handle this gracefully. For many types, this means keeping a Boolean flag indicating whether the object has been finalized or not. Then, if methods are called on your finalized object, you might consider throwing an exception. The exact technique to use depends on your type. Now, if some other piece of code sets Application.ObjHolder to null, the object is unreachable. Eventually the garbage collector will consider the object to be garbage and will reclaim the object's storage. Note that the object's Finalize method will not be called because no pointer to the object exists on the finalization queue. There are very few good uses of resurrection, and you really should avoid it if possible. However, when people do use resurrection, they usually want the object to clean itself up gracefully every time the object dies. To make this possible, the GC type offers a method called ReRegisterForFinalize, which takes a single parameter: the pointer to an object. public class BaseObj { protected override void Finalize() { Application.ObjHolder = this; GC.ReRegisterForFinalize(this); } } When this object's Finalize method is called, it resurrects itself by making a root point to the object. The Finalize method then calls ReRegisterForFinalize, which appends the address of the specified object (this) to the end of the finalization queue. When the garbage collector detects that this object is unreachable again, it will queue the object's pointer on the freachable queue and the Finalize method will get called again. This specific example shows how to create an object that constantly resurrects itself and never dies, which is usually not desirable. It is far more common to conditionally set a root to reference the object inside the Finalize method. Make sure that you call ReRegisterForFinalize no more than once per resurrection, or the object will have its Finalize method called multiple times. This happens because each call to ReRegisterForFinalize appends a new entry to the end of the finalization queue. When an object is determined to be garbage, all of these entries move from the finalization queue to the freachable queue, calling the object's Finalize method multiple times. Forcing an Object to Clean Up If you can, you should try to define objects that do not require any clean up. Unfortunately, for many objects, this is simply not possible. So for these objects, you must implement a Finalize method as part of the type's definition. However, it is also recommended that you add an additional method to the type that allows a user of the type to explicitly clean up the object when they want. By convention, this method should be called Close or Dispose. In general, you use Close if the object can be reopened or reused after it has been closed. You also use Close if the object is generally considered to be closed, such as a file. On the other hand, you would use Dispose if the object should no longer be used at all after it has been disposed. For example, to delete a System.Drawing.Brush object, you call its Dispose method. Once disposed, the Brush object cannot be used, and calling methods to manipulate the object may cause exceptions to be thrown. If you need to work with another Brush, you must construct a new Brush object. Now, let's look at what the Close/Dispose method is supposed to do. The System.IO.FileStream type allows the user to open a file for reading and writing. To improve performance, the type's implementation makes use of a memory buffer. Only when the buffer fills does the type flush the contents of the buffer to the file. Let's say that you create a new FileStream object and write just a few bytes of information to it. If these bytes don't fill the buffer, then the buffer is not written to disk. The FileStream type does implement a Finalize method, and when the FileStream object is collected the Finalize method flushes any remaining data from memory to disk and then closes the file. But this approach may not be good enough for the user of the FileStream type. Let's say that the

104 first FileStream object has not been collected yet, but the application wants to create a new FileStream object using the same disk file. In this scenario, the second FileStream object will fail to open the file if the first FileStream object had the file open for exclusive access. The user of the FileStream object must have some way to force the final memory flush to disk and to close the file. If you examine the FileStream type's documentation, you'll see that it has a method called Close. When called, this method flushes the remaining data in memory to the disk and closes the file. Now the user of a FileStream object has control of the object's behavior. But an interesting problem arises now: what should the FileStream's Finalize method do when the FileStream object is collected? Obviously, the answer is nothing. In fact, there is no reason for the FileStream's Finalize method to execute at all if the application has explicitly called the Close method. You know that Finalize methods are discouraged, and in this scenario you're going to have the system call a Finalize method that should do nothing. It seems like there ought to be a way to suppress the system's calling of the object's Finalize method. Fortunately, there is. The System.GC type contains a static method, SuppressFinalize, that takes a single parameter, the address of an object. Figure 8 shows FileStream's type implementation. When you call SuppressFinalize, it turns on a bit flag associated with the object. When this flag is on, the runtime knows not to move this object's pointer to the freachable queue, preventing the object's Finalize method from being called. Let's examine another related issue. It is very common to use a StreamWriter object with a FileStream object. FileStream fs = new FileStream("C:\\SomeFile.txt", FileMode.Open, FileAccess.Write, FileShare.Read); StreamWriter sw = new StreamWriter(fs); sw.Write ("Hi there"); // The call to Close below is what you should do sw.Close(); // NOTE: StreamWriter.Close closes the FileStream. The FileStream // should not be explicitly closed in this scenario Notice that the StreamWriter's constructor takes a FileStream object as a parameter. Internally, the StreamWriter object saves the FileStream's pointer. Both of these objects have internal data buffers that should be flushed to the file when you're finished accessing the file. Calling the StreamWriter's Close method writes the final data to the FileStream and internally calls the FileStream's Close method, which writes the final data to the disk file and closes the file. Since StreamWriter's Close method closes the FileStream object associated with it, you should not call fs.Close yourself. What do you think would happen if you removed the two calls to Close? Well, the garbage collector would correctly detect that the objects are garbage and the objects would get finalized. But, the garbage collector doesn't guarantee the order in which the Finalize methods are called. So if the FileStream gets finalized first, it closes the file. Then when the StreamWriter gets finalized, it would attempt to write data to the closed file, raising an exception. Of course, if the StreamWriter got finalized first, then the data would be safely written to the file. How did Microsoft solve this problem? Making the garbage collector finalize objects in a specific order is impossible because objects could contain pointers to each other and there is no way for the garbage collector to correctly guess the order to finalize these objects. So, here is Microsoft's solution: the StreamWriter type doesn't implement a Finalize method at all. Of course, this means that forgetting to explicitly close the StreamWriter object guarantees data loss. Microsoft expects that developers will see this consistent loss of data and will fix the code by inserting an explicit call to Close. As stated earlier, the SuppressFinalize method simply sets a bit flag indicating that the object's Finalize method should not be called. However, this flag is reset when the runtime determines that it's time to call a Finalize method. This means that calls to ReRegisterForFinalize cannot be balanced by calls to SuppressFinalize. The code in Figure 9 demonstrates exactly what I mean. ReRegisterForFinalize and SuppressFinalize are implemented the way they are for performance reasons. As long as each call to SuppressFinalize has an intervening call to ReRegisterForFinalize, everything works. It is up to you to ensure that you do not call ReRegisterForFinalize or SuppressFinalize multiple times consecutively, or multiple calls to an object's Finalize method can occur. Conclusion The motivation for garbage-collected environments is to simplify memory management for the

105 developer. The first part of this overview looked at some general GC concepts and internals. In Part 2, I will conclude this discussion. First, I will explore a feature called WeakReferences, which you can use to reduce the memory pressure placed on the managed heap by large objects. Then I'll examine a mechanism that allows you to artificially extend the lifetime of a managed object. Finally, I'll wrap up by discussing various aspects of the garbage collector's performance. I'll discuss generations, multithreaded collections, and the performance counters that the common language runtime exposes, which allow you to monitor the garbage collector's real-time behavior SUMMARY The first part of this two-part article explained how the garbage collection algorithm works, how resources can clean up properly when the garbage collector decides to free a resource's memory, and how to force an object to clean up when it is freed. The conclusion of this series explains strong and weak object references that help to manage memory for large objects, as well as object generations and how they improve performance. In addition, the use of methods and properties for controlling garbage collection, resources for monitoring collection performance, and garbage collection for multithreaded applications are covered. ast month, I described the motivation for garbage-collected environments: to simplify memory management for the developer. I also discussed the general algorithm used by the common language runtime (CLR) and some of the internal workings of this algorithm. In addition, I explained how the developer must still explicitly handle resource management and cleanup by implementing Finalize, Close, and/or Dispose methods. This month, I will conclude my discussion of the CLR garbage collector. I'll start by exploring a feature called weak references, which you can use to reduce the memory pressure placed on the managed heap by large objects. Then, I'll discuss how the garbage collector uses generations as a performance enhancement. Finally, I'll wrap up by discussing a few other performance enhancements offered by the garbage collector, such as multithreaded collections and performance counters exposed by the CLR that allow you to monitor the garbage collector's real-time behavior. Weak References When a root points to an object, the object cannot be collected because the application's code can reach the object. When a root points to an object, it's called a strong reference to the object. However, the garbage collector also supports weak references. Weak references allow the garbage collector to collect the object, but they also allow the application to access the object. How can this be? It all comes down to timing. If only weak references to an object exist and the garbage collector runs, the object is collected and when the application later attempts to access the object, the access will fail. On the other hand, to access a weakly referenced object, the application must obtain a strong reference to the object. If the application obtains this strong reference before the garbage collector collects the object, then the garbage collector can't collect the object because a strong reference to the object exists. I know this all sounds somewhat confusing, so let's clear it up by examining the code in Figure 1. Why might you use weak references? Well, there are some data structures that are created easily, but require a lot of memory. For example, you might have an application that needs to know all the directories and files on the user's hard drive. You can easily build a tree that reflects this information and as your application runs, you'll refer to the tree in memory instead of actually accessing the user's hard disk. This procedure greatly improves the performance of your application. The problem is that the tree could be extremely large, requiring quite a bit of memory. If the user starts accessing a different part of your application, the tree may no longer be necessary and is wasting valuable memory. You could delete the tree, but if the user switches back to the first part of your application, you'll need to reconstruct the tree again. Weak references allow you to handle this scenario quite easily and efficiently. When the user switches away from the first part of the application, you can create a weak reference to the tree and destroy all strong references. If the memory load is low for the other part of the application, then the garbage collector will not reclaim the tree's objects. When the user switches back to the first part of the application, the application attempts to obtain a strong reference for the tree. If successful, the application doesn't have to traverse the user's hard drive again. The WeakReference type offers two constructors: WeakReference(Object target); WeakReference(Object target, Boolean trackResurrection);

106 The target parameter identifies the object that the WeakReference object should track. The trackResurrection parameter indicates whether the WeakReference object should track the object after it has had its Finalize method called. Usually, false is passed for the trackResurrection parameter and the first constructor creates a WeakReference that does not track resurrection. (For an explanation of resurrection, see part 1 of this article at Garbage Collection: Automatic Memory Management in the Microsoft .NET Framework.) For convenience, a weak reference that does not track resurrection is called a short weak reference, while a weak reference that does track resurrection is called a long weak reference. If an object's type doesn't offer a Finalize method, then short and long weak references behave identically. It is strongly recommended that you avoid using long weak references. Long weak references allow you to resurrect an object after it has been finalized and the state of the object is unpredictable. Once you've created a weak reference to an object, you usually set the strong reference to the object to null. If any strong reference remains, the garbage collector will be unable to collect the object. To use the object again, you must turn the weak reference into a strong reference. You accomplish this simply by calling the WeakReference object's Target property and assigning the result to one of your application's roots. If the Target property returns null, then the object was collected. If the property does not return null, then the root is a strong reference to the object and the code may manipulate the object. As long as the strong reference exists, the object cannot be collected. Weak Reference Internals From the previous discussion, it should be obvious that WeakReference objects do not behave like other object types. Normally, if your application has a root that refers to an object and that object refers to another object, then both objects are reachable and the garbage collector cannot reclaim the memory in use by either object. However, if your application has a root that refers to a WeakReference object, then the object referred to by the WeakReference object is not considered reachable and may be collected. To fully understand how weak references work, let's look inside the managed heap again. The managed heap contains two internal data structures whose sole purpose is to manage weak references: the short weak reference table and the long weak reference table. These two tables simply contain pointers to objects allocated within the managed heap. Initially, both tables are empty. When you create a WeakReference object, an object is not allocated from the managed heap. Instead, an empty slot in one of the weak reference tables is located; short weak references use the short weak reference table and long weak references use the long weak reference table. Once an empty slot is found, the value in the slot is set to the address of the object you wish to track—the object's pointer is passed to the WeakReference's constructor. The value returned from the new operator is the address of the slot in the WeakReference table. Obviously, the two weak reference tables are not considered part of an application's roots or the garbage collector would not be able to reclaim the objects pointed to by the tables. Now, here's what happens when a garbage collection (GC) runs: 1. 2. The garbage collector builds a graph of all the reachable objects. Part 1 of this article discussed how this works. The garbage collector scans the short weak reference table. If a pointer in the table refers to an object that is not part of the graph, then the pointer identifies an unreachable object and the slot in the short weak reference table is set to null. The garbage collector scans the finalization queue. If a pointer in the queue refers to an object that is not part of the graph, then the pointer identifies an unreachable object and the pointer is moved from the finalization queue to the freachable queue. At this point, the object is added to the graph since the object is now considered reachable. The garbage collector scans the long weak reference table. If a pointer in the table refers to an object that is not part of the graph (which now contains the objects pointed to by entries in the freachable queue), then the pointer identifies an unreachable object and the slot is set to null. The garbage collector compacts the memory, squeezing out the holes left by the unreachable objects.

3.

4.

5.

107 Once you understand the logic of the garbage collection process, it's easy to understand how weak references work. Accessing the WeakReference's Target property causes the system to return the value in the appropriate weak reference table's slot. If null is in the slot, the object was collected. A short weak reference doesn't track resurrection. This means that the garbage collector sets the pointer to null in the short weak reference table as soon as it has determined that the object is unreachable. If the object has a Finalize method, the method has not been called yet so the object still exists. If the application accesses the WeakReference object's Target property, then null will be returned even though the object actually still exists. A long weak reference tracks resurrection. This means that the garbage collector sets the pointer to null in the long weak reference table when the object's storage is reclaimable. If the object has a Finalize method, the Finalize method has been called and the object was not resurrected. Generations When I first started working in a garbage-collected environment, I had many concerns about performance. After all, I've been a C/C++ programmer for more than 15 years and I understand the overhead of allocating and freeing memory blocks from a heap. Sure, each version of Windows® and each version of the C runtime has tweaked the internals of the heap algorithms in order to improve performance. Well, like the developers of Windows and the C runtime, the GC developers are tweaking the garbage collector to improve its performance. One feature of the garbage collector that exists purely to improve performance is called generations. A generational garbage collector (also known as an ephemeral garbage collector) makes the following assumptions:     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 are frequently accessed around the same time. Compacting a portion of the heap is faster than compacting the whole heap.

Of course, many studies have demonstrated that these assumptions are valid for a very large set of existing applications. So, let's discuss how these assumptions have influenced the implementation of the garbage collector. When initialized, the managed heap contains no objects. Objects added to the heap are said to be in generation 0, as you can see in Figure 2. Stated simply, objects in generation 0 are young objects that have never been examined by the garbage collector.

Figure 2 Generation 0 Now, if more objects are added to the heap, the heap fills and a garbage collection must occur. When the garbage collector analyzes the heap, it builds the graph of garbage (shown here in purple) and non-garbage objects. Any objects that survive the collection are compacted into the left-most

108 portion of the heap. These objects have survived a collection, are older, and are now considered to be in generation 1 (see Figure 3).

Figure 3 Generations 0 and 1 As even more objects are added to the heap, these new, young objects are placed in generation 0. If generation 0 fills again, a GC is performed. This time, all objects in generation 1 that survive are compacted and considered to be in generation 2 (see Figure 4). All survivors in generation 0 are now compacted and considered to be in generation 1. Generation 0 currently contains no objects, but all new objects will go into generation 0.

Figure 4 Generations 0, 1, and 2 Currently, generation 2 is the highest generation supported by the runtime's garbage collector. When future collections occur, any surviving objects currently in generation 2 simply stay in generation 2. Generational GC Performance Optimizations As I stated earlier, generational garbage collecting improves performance. When the heap fills and a collection occurs, the garbage collector can choose to examine only the objects in generation 0 and ignore the objects in any greater generations. After all, the newer an object is, the shorter its lifetime is expected to be. So, collecting and compacting generation 0 objects is likely to reclaim a significant amount of space from the heap and be faster than if the collector had examined the objects in all generations. This is the simplest optimization that can be obtained from generational GC. A generational collector can offer more optimizations by not traversing every object in the managed heap. If a root or object refers to an object in an old generation, the garbage collector can ignore any of the older

109 objects' inner references, decreasing the time required to build the graph of reachable objects. Of course, it is possible that an old object refers to a new object. So that these objects are examined, the collector can take advantage of the system's write-watch support (provided by the Win32® GetWriteWatch function in Kernel32.dll). This support lets the collector know which old objects (if any) have been written to since the last collection. These specific old objects can have their references checked to see if they refer to any new objects. If collecting generation 0 doesn't provide the necessary amount of storage, then the collector can attempt to collect the objects from generations 1 and 0. If all else fails, then the collector can collect the objects from all generations—2, 1, and 0. The exact algorithm used by the collector to determine which generations to collect is one of those areas that Microsoft will be tweaking forever. Most heaps (like the C runtime heap) allocate objects wherever they find free space. Therefore, if I create several objects consecutively, it is quite possible that these objects will be separated by megabytes of address space. However, in the managed heap, allocating several objects consecutively ensures that the objects are contiguous in memory. One of the assumptions stated earlier was that newer objects tend to have strong relationships to each other and are frequently accessed around the same time. Since new objects are allocated contiguously in memory, you gain performance from locality of reference. More specifically, it is highly likely that all the objects can reside in the CPU's cache. Your application will access these objects with phenomenal speed since the CPU will be able to perform most of its manipulations without having cache misses which forces RAM access. Microsoft's performance tests show that managed heap allocations are faster than standard allocations performed by the Win32 HeapAlloc function. These tests also show that it takes less than 1 millisecond on a 200Mhz Pentium to perform a full GC of generation 0. It is Microsoft's goal to make GCs take no more time than an ordinary page fault. Direct Control with System.GC The System.GC type allows your application some direct control over the garbage collector. For starters, you can query the maximum generation supported by the managed heap by reading the GC.MaxGeneration property. Currently, the GC.MaxGeneration property always returns 2. It is also possible to force the garbage collector to perform a collection by calling 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 may pass any integer from 0 to GC.MaxGeneration, inclusive. Passing 0 causes generation 0 to be collected; passing 1 causes generation 1 and 0 to be collected; and passing 2 causes generation 2, 1, and 0 to be collected. The version of the Collect method that takes no parameters forces a full collection of all generations and is equivalent to calling: GC.Collect(GC.MaxGeneration); Under most circumstances, you should avoid calling any of the Collect methods; it is best to just let the garbage collector run on its own accord. However, since your application knows more about its behavior than the runtime does, you could help matters by explicitly forcing some collections. For example, it might make sense for your application to force a full collection of all generations after the user saves his data file. I imagine Internet browsers performing a full collection when pages are unloaded. You might also want to force a collection when your application is performing other lengthy operations; this hides the fact that the collection is taking processing time and prevents a collection from occurring when the user is interacting with your application. The GC type also offers a WaitForPendingFinalizers method. This method simply suspends the calling thread until the thread processing the freachable queue has emptied the queue, calling each object's Finalize method. In most applications, it is unlikely that you will ever have to call this method. Lastly, the garbage collector offers two methods that allow you to determine which 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. Of course, the value returned will be somewhere between 0 and GC.MaxGeneration, inclusive. The code in Figure 5 will help you understand how generations work. It also demonstrates the use

110 of the garbage collection methods just discussed. Performance for Multithreaded Applications In the previous section, I explained the GC algorithm and optimizations. However, there was a big assumption made during that discussion: only one thread is running. In the real world, it is quite likely that multiple threads will be accessing the managed heap or at least manipulating objects allocated within the managed heap. When one thread sparks a collection, other threads must not access any objects (including object references on its own stack) since the collector is likely to move these objects, changing their memory locations. So, when the garbage collector wants to start a collection, all threads executing managed code must be suspended. The runtime has a few different mechanisms that it uses to safely suspend threads so that a collection may be done. The reason there are multiple mechanisms is to keep threads running as long as possible and to reduce overhead as much as possible. I don't want to go into all the details here, but suffice it to say that Microsoft has done a lot of work to reduce the overhead involved with performing a collection. Microsoft will continue to modify these mechanisms over time to help ensure efficient garbage collections. The following paragraphs describe a few of the mechanisms that the garbage collector employs when applications have multiple threads: Fully Interruptible Code When a collection starts, the collector suspends all application threads. The collector then determines where a thread got suspended and using tables produced by the justin-time (JIT) compiler, the collector can tell where in a method the thread stopped, what object references the code is currently accessing, and where those references are held (in a variable, CPU register, and so on). Hijacking The collector can modify a thread's stack so that the return address points to a special function. When the currently executing method returns, this special function will execute, suspending the thread. Stealing the thread's execution path this way is referred to as hijacking the thread. When the collection is complete, the thread will resume and return to the method that originally called it. Safe Points As the JIT compiler compiles a method, it can insert calls to a special function that checks if a GC is pending. If so, the thread is suspended, the GC runs to completion, and the thread is then resumed. The position where the compiler inserts these method calls is called a GC safe point. Note that thread hijacking allows threads that are executing unmanaged code to continue execution while a garbage collection is occurring. This is not a problem since unmanaged code is not accessing objects on the managed heap unless the objects are pinned and don't contain object references. A pinned object is one that the garbage collector is not allowed to move in memory. If a thread that is currently executing unmanaged code returns to managed code, the thread is hijacked and is suspended until the GC completes. In addition to the mechanisms I just mentioned, the garbage collector offers some additional improvements that enhance the performance of object allocations and collections when applications have multiple threads. Synchronization-free Allocations On a multiprocessor system, generation 0 of the managed heap is split into multiple memory arenas using one arena per thread. This allows multiple threads to make allocations simultaneously so that exclusive access to the heap is not required. Scalable Collections On a multiprocessor system running the server version of the execution engine (MSCorSvr.dll), the managed heap is split into several sections, one per CPU. When a collection is initiated, the collector has one thread per CPU; all threads collect their own sections simultaneously. The workstation version of the execution engine (MSCorWks.dll) doesn't support this feature. Garbage-collecting Large Objects There is one more performance improvement that you might want to be aware of. Large objects (those that are 20,000 bytes or larger) are allocated from a special large object heap. Objects in this heap are finalized and freed just like the small objects I've been talking about. However, large objects are never compacted because shifting 20,000-byte blocks of memory down in the heap would waste too much CPU time. Note that all of these mechanisms are transparent to your application code. To you, the developer, it looks like there is just one managed heap; these mechanisms exist simply to improve application performance.

111 Monitoring Garbage Collections The runtime team at Microsoft has created a set of performance counters that provide a lot of realtime statistics about the runtime's operations. You can view these statistics via the Windows 2000 System Monitor ActiveX® control. The easiest way to access the System Monitor control is to run PerfMon.exe and select the + toolbar button, causing the Add Counters dialog box to appear (see Figure 6).

Figure 6 Adding Performance Counters To monitor the runtime's garbage collector, select the COM+ Memory Performance object. Then, you can select a specific application from the instance list box. Finally, select the set of counters that you're interested in monitoring and press the Add button followed by the Close button. At this point, the System Monitor will graph the selected real-time statistics. Figure 7 describes the function of each counter. Conclusion So that's just about the full story on garbage collection. Last month I provided the background on how resources are allocated, how automatic garbage collection works, how to use the finalization feature to allow an object to clean up after itself, and how the resurrection feature can restore access to objects. This month I explained how weak and strong references to objects are implemented, how classifying objects in generations results in performance benefits, and how you can manually control garbage collection with System.GC. I also covered the mechanisms the garbage collector uses in multithreaded applications to improve performance, what happens with objects that are larger than 20,000 bytes, and finally, how you can use the Windows 2000 System Monitor to track garbage collection performance. With this information in hand, you should be able to simplify memory management and boost performance in your applications.

112

Memory Management
Resource Allocation The Microsoft .NET common language runtime requires that all resources be allocated from the managed heap. Objects are automatically freed when they are no longer needed by the application. When a process is initialized, the runtime reserves a contiguous region of address space that initially has no storage allocated for it. This address space region is the managed heap. The heap also maintains a pointer. This pointer indicates where the next object is to be allocated within the heap. Initially, the pointer is set to the base address of the reserved address space region. An application creates an object using the new operator. This operator first makes sure that the bytes required by the new object fit in the reserved region (committing storage if necessary). If the object fits, then pointer points to the object in the heap, this object's constructor is called, and the new 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 may not be enough address space left in the region to allocate to the object. The heap detects this by adding the size of the new object to NextObjPtr. If NextObjPtr is beyond the end of the address space region, then the heap is full and a collection must be performed. In reality, a collection occurs when generation 0 is completely full. Briefly, a generation is a mechanism implemented by the garbage collector in order to improve performance. The idea is that newly created objects are part of a young generation, and objects created early in the application's lifecycle are in an old generation. Separating objects into generations can allow the garbage collector to collect specific generations instead of collecting all objects in the managed heap. The Garbage Collection Algorithm The garbage collector checks to see if there are any objects in the heap that are no longer being used by the application. If such objects exist, then the memory used by these objects can be reclaimed. (If no more memory is available for the heap, then the new operator throws an OutOfMemoryException.) Every application has a set of roots. Roots identify storage locations, which refer to objects on the managed heap or to objects that are set to null. For example, all the global and static object pointers in an application are considered part of the application's roots. In addition, any local variable/parameter object pointers on a thread's stack are considered part of the application's roots. Finally, any CPU registers containing pointers to objects in the managed heap are also considered part of the application's roots. The list of active roots is maintained by the just-in-time (JIT) compiler and common language runtime, and is made accessible to the garbage collector's algorithm. When the garbage collector starts running, it makes the assumption that all objects in the heap are

113 garbage. In other words, it assumes that none of the application's roots refer to any objects in the heap. Now, the garbage collector starts walking the roots and building a graph of all objects reachable from the roots. For example, the garbage collector may locate a global variable that points to an object in the heap. Following fig shows a heap with several allocated objects where the application's roots refer directly to objects A, C, D, and F. All of these objects become part of the graph. When adding object D, the collector notices that this object refers to object H, and object H is also added to the graph. The collector continues to walk through all reachable objects recursively.

Once this part of the graph is complete, the garbage collector checks the next root and walks the objects again. As the garbage collector walks from object to object, if it attempts to add an object to the graph that it previously added, then the garbage collector can stop walking down that path. This serves two purposes. First, it helps performance significantly since it doesn't walk through a set of objects more than once. Second, it prevents infinite loops should you have any circular linked lists of objects. Once all the roots have been checked, the garbage collector's graph contains the set of all objects that are somehow reachable from the application's roots; any objects that are not in the graph are not accessible by the application, and are therefore considered garbage. The garbage collector now walks through the heap linearly, looking for contiguous blocks of garbage objects (now considered free space). The garbage 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 the objects. So the garbage collector must modify the application's roots so that the pointers point to the objects' new locations. In addition, if any object contains a pointer to another object, the garbage collector is responsible for correcting these pointers as well. Following fig shows the managed heap after a collection.

After all the garbage has been identified, all the non-garbage has been compacted, and all the nongarbage pointers have been fixed-up, the NextObjPtr is positioned just after the last non-garbage object. At this point, the new operation is tried again and the resource requested by the application is successfully created. GC generates a significant performance hit, and this is the major downside of using a managed heap. However, keep in mind that GCs only occur when the heap is full and, until then, the managed heap is significantly faster than a C-runtime heap. The runtime's garbage collector also

114 offers some optimizations using Generations that greatly improve the performance of garbage collection. You no longer have to implement any code that manages the lifetime of any resources that your application uses. Now it is not possible to leak resources, since any resource not accessible from your application's roots can be collected at some point. Also it is not possible to access a resource that is freed, since the resource won't be freed if it is reachable. If it's not reachable, 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 root ArrayList myArray = new ArrayList(); // Create 10000 objects in the heap for (int x = 0; x < 10000; x++) { myArray.Add(new Object()); // Object object created in heap } // Right now, myArray is a root (on the thread's 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 doesn't 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 isn't in ANSI C++. The reason is that a garbage collector must be able to identify an application's roots and must also be able to find all object pointers. The problem with C++ is that it allows casting a pointer from one type to another, and there's no 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 the metadata information is used to determine which members of an object refer to other objects. Generations One feature of the garbage collector that exists purely to improve performance is called generations. A generational garbage collector (also known as an ephemeral garbage collector) makes the following assumptions:     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 are frequently accessed around the same time. Compacting a portion of the heap is faster than compacting the whole heap.

When initialized, the managed heap contains no objects. Objects added to the 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 never been examined by the garbage collector.

115

Now, if more objects are added to the heap, the heap fills and a garbage collection must occur. When the garbage collector analyzes the heap, it builds the graph of garbage (shown here in Green) and non-garbage objects. Any objects that survive the collection are compacted into the left-most portion of the heap. These objects have survived a collection, are older, and are now considered to be in generation 1.

116

As even more objects are added to the heap, these new, young objects are placed in generation 0. If generation 0 fills again, a GC is performed. This time, all objects in generation 1 that survive are compacted and considered to be in generation 2 (see following fig). All survivors in generation 0 are now compacted and considered to be in generation 1. Generation 0 currently contains no objects, but all new objects will go into generation 0.

117 Currently, generation 2 is the highest generation supported by the runtime's garbage collector. When future collections occur, any surviving objects currently in generation 2 simply stay in generation 2. Generational GC Performance Optimizations Generational garbage collecting improves performance. When the heap fills and a collection occurs, the garbage collector can choose to examine only the objects in generation 0 and ignore the objects in any greater generations. After all, the newer an object is, the shorter its lifetime is expected to be. So, collecting and compacting generation 0 objects is likely to reclaim a significant amount of space from the heap and be faster than if the collector had examined the objects in all generations. A generational collector can offer more optimizations by not traversing every object in the managed heap. If a root or object refers to an object in an old generation, the garbage collector can ignore any of the older objects' inner references, decreasing the time required to build the graph of reachable objects. Of course, it is possible that an old object refers to a new object. So that these objects are examined, the collector can take advantage of the system's write-watch support (provided by the Win32® GetWriteWatch function in Kernel32.dll). This support lets the collector know which old objects (if any) have been written to since the last collection. These specific old objects can have their references checked to see if they refer to any new objects. If collecting generation 0 doesn't provide the necessary amount of storage, then the collector can attempt to collect the objects from generations 1 and 0. If all else fails, then the collector can collect the objects from all generations—2, 1, and 0. One of the assumptions stated earlier was that newer objects tend to have strong relationships to each other and are frequently accessed around the same time. Since new objects are allocated contiguously in memory, you gain performance from locality of reference. More specifically, it is highly likely that all the objects can reside in the CPU's cache. Your application will access these objects with phenomenal speed since the CPU will be able to perform most of its manipulations without having cache misses which forces RAM access. Microsoft's performance tests show that managed heap allocations are faster than standard allocations performed by the Win32 HeapAlloc function. These tests also show that it takes less than 1 millisecond on a 200 MHz Pentium to perform a full GC of generation 0. It is Microsoft's goal to make GCs take no more time than an ordinary page fault. Disadvantages of Win32 heap:  Most heaps (like the C runtime heap) allocate objects wherever they find free space. Therefore, if I create several objects consecutively, it is quite possible that these objects will be separated by megabytes of address space. However, in the managed heap, allocating several objects consecutively ensures that the objects are contiguous in memory. When memory is allocated from a Win32 heap, the heap must be examined to find a block of memory that can satisfy the request. This is not required in managed heap, since here objects are contiguous in memory. In Win32 heap, data structures that the heap maintains must be updated. The managed heap, on the other hand, only needs to increment the heap pointer.

Finalization The garbage collector offers an additional feature that you may want to take advantage of: finalization. Finalization allows a resource to gracefully clean up after itself when it is being collected. By using finalization, a resource representing a file or network connection is able to clean itself up properly when the garbage collector decides to free the resource's memory. When the garbage collector detects that an object is garbage, the garbage collector calls the object's Finalize method (if it exists) and then the object's memory is reclaimed. For example, let's say you have the following type (in C#): public class BaseObj { public BaseObj()

118 { } protected override void Finalize() { // Perform resource cleanup code here... // Example: Close file/Close network connection Console.WriteLine("In Finalize."); } } 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 object is garbage. When that happens, the garbage collector will see that the type has a Finalize method and will call the method, causing "In Finalize" to appear in the console window and reclaiming the memory block used by this object. Many developers who are used to programming in C++ draw an immediate correlation between a destructor and the Finalize method. However, object finalization and destructors have very different semantics and it is best to forget everything you know about destructors when thinking about finalization. Managed objects never have destructors. When designing a type it is best to avoid using a Finalize method. There are several reasons for this:  Finalizable objects get promoted to older generations, which increases memory pressure and prevents the object's memory from being collected when the garbage collector determines the object is garbage. In addition, all objects referred to directly or indirectly by this object get promoted as well. Finalizable objects take longer to allocate. Forcing the garbage collector to execute a Finalize method can significantly hurt performance. Remember, each object is finalized. So if I have an array of 10,000 objects, each object must have its Finalize method called. Finalizable objects may refer to other (non-finalizable) objects, prolonging their lifetime unnecessarily. In fact, you might want to consider breaking a type into two different types: a lightweight type with a Finalize method that doesn't refer to any other objects, and a separate type without a Finalize method that does refer to other objects. You have no control over when the Finalize method will execute. The object may hold on to resources until the next time the garbage collector runs. When an application terminates, some objects are still reachable and will not have their Finalize method called. This can happen if background threads are using the objects or if objects are created during application shutdown or AppDomain unloading. In addition, by default, Finalize methods are not called for unreachable objects when an application exits so that the application may terminate quickly. Of course, all operating system resources will be reclaimed, but any objects in the managed heap are not able to clean up gracefully. You can change this default behavior by calling the System.GC type's RequestFinalizeOnShutdown method. However, you should use this method with care since calling it means that your type is controlling a policy for the entire application. The runtime doesn't make any guarantees as to the order in which Finalize methods are called. For example, let's say there is an object that contains a pointer to an inner object. The garbage collector has detected that both objects are garbage. Furthermore, say that the inner object's Finalize method gets called first. Now, the outer object's Finalize method is allowed to access the inner object and call methods on it, but the inner object has been finalized and the results may be unpredictable. For this reason, it is strongly recommended that Finalize methods not access any inner, member objects.

 

 

If you determine that your type must implement a Finalize method, then make sure the code executes as quickly as possible. Avoid all actions that would block the Finalize method, including

119 any thread synchronization operations. Also, if you let any exceptions escape the Finalize method, the system just assumes that the Finalize method returned and continues calling other objects' Finalize methods. When the compiler generates code for a constructor, the compiler automatically inserts a call to the base type's constructor. Likewise, when a C++ compiler generates code for a destructor, the compiler automatically inserts a call to the base type's destructor. Finalize methods are different from destructors. The compiler has no special knowledge about a Finalize method, so the compiler does not automatically generate code to call a base type's Finalize method. If you want this behavior—and frequently you do—then you must explicitly call the base type's Finalize method from your type's Finalize method: public class BaseObj { public BaseObj() { } protected override void Finalize() { Console.WriteLine("In Finalize."); base.Finalize(); // Call base type's Finalize } } Note that you'll usually call the base type's Finalize method as the last statement in the derived type's Finalize method. This keeps the base object alive as long as possible. Since calling a base type Finalize method is common, C# has a syntax that simplifies your work. In C#, the following code: 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++ language's syntax for defining a destructor. But remember, C# doesn't support destructors. Don't let the identical syntax fool you. Finalization Internals When an application creates a new object, the new operator allocates the memory from the heap. If the object's type contains a Finalize method, then a pointer to the object is placed on the finalization queue. The finalization queue is an internal data structure controlled by the garbage collector. Each entry in the queue points to an object that should have its Finalize method called before the object's memory can be reclaimed. Following fig shows a heap containing several objects. Some of these objects are reachable from the application's roots, and some are not. When objects C, E, F, I, and J were created, the system detected that these objects had Finalize methods and pointers to these objects were added to the finalization queue.

120

When a GC occurs, objects B, E, G, H, I, and J are determined to be garbage. The garbage collector scans the finalization queue looking for pointers to these objects. When a pointer is found, the pointer is removed from the finalization queue and appended to the freachable queue (pronounced "F-reachable"). The freachable queue is another internal data structure controlled by the garbage collector. Each pointer in the freachable queue identifies an object that is ready to have its Finalize method called. After the collection, the managed heap looks like following fig. Here, you see that the memory occupied by objects B, G, and H has been reclaimed because these objects did not have a Finalize method that needed to be called. However, the memory occupied by objects E, I, and J could not be reclaimed because their Finalize method has not been called yet.

121

There is a special runtime thread dedicated to calling Finalize methods. When the freachable queue is empty (which is usually the case), this thread sleeps. But when entries appear, this thread wakes, removes each entry from the queue, and calls each object's Finalize method. Because of this, you should not execute any code in a Finalize method that makes any assumption about the thread that's executing the code. For example, avoid accessing thread local storage in the Finalize method. The interaction of the finalization queue and the freachable queue is quite fascinating. First, let me tell you how the freachable queue got its name. The f is obvious and stands for finalization; every entry in the freachable queue should have its Finalize method called. The "reachable" part of the name means that the objects are reachable. To put it another way, the freachable queue is considered to be a root just like global and static variables are roots. Therefore, if an object is on the freachable queue, then the object is reachable and is not garbage. In short, when an object is not reachable, the garbage collector considers the object garbage. Then, when the garbage collector moves an object's entry from the finalization queue to the freachable queue, the object is no longer considered garbage and its memory is not reclaimed. At this point, the garbage collector has finished identifying garbage. Some of the objects identified as garbage have been reclassified as not garbage. The garbage collector compacts the reclaimable memory and the special runtime thread empties the freachable queue, executing each object's Finalize method.

122

The next time the garbage collector is invoked, it sees that the finalized objects are truly garbage, since the application's roots don't point to it and the freachable queue no longer points to it. Now the memory for the object is simply reclaimed. The important thing to understand here is that two GCs are required to reclaim memory used by objects that require finalization. In reality, more than two collections may be necessary since the objects could get promoted to an older generation. Above fig shows what the managed heap looks like after the second GC. Dispose Method Use this method to close or release unmanaged resources such as files, streams, and handles held by an instance of the class that implements this interface. This method is, by convention, used for all tasks associated with freeing resources held by an object, or preparing an object for reuse. When implementing this method, objects must seek to ensure that all held resources are freed by propagating the call through the containment hierarchy. For example, if an object A allocates an object B, and object B allocates an object C, then A's Dispose implementation must call Dispose on B, which must in turn call Dispose on C. Objects must also call the Dispose method of their base class if the base class implements IDisposable. If an object's Dispose method is called more than once, the object must ignore all calls after the first one. The object must not throw an exception if its Dispose method is called multiple times. Dispose can throw an exception if an error occurs because a resource has already been freed and Dispose had not been called previously. Because the Dispose method must be called explicitly, objects that implement IDisposable must also implement a finalizer to handle freeing resources when Dispose is not called. By default, the garbage collector will automatically call an object's finalizer prior to reclaiming its memory. However, once the Dispose method has been called, it is typically unnecessary for the garbage collector to call the disposed object's finalizer. To prevent automatic finalization, Dispose implementations can call the GC.SuppressFinalize method. Direct Control with System.GC The System.GC type allows your application some direct control over the garbage collector. You can query the maximum generation supported by the managed heap by reading the GC.MaxGeneration property. Currently, the GC.MaxGeneration property always returns 2. It is also possible to force the garbage collector to perform a collection by calling one of the two methods shown here:

123 void GC.Collect(Int32 Generation) void GC.Collect() The first method allows you to specify which generation to collect. You may pass any integer from 0 to GC.MaxGeneration, inclusive. Passing 0 causes generation 0 to be collected; passing 1 cause generation 1 and 0 to be collected; and passing 2 causes generation 2, 1, and 0 to be collected. The version of the Collect method that takes no parameters forces a full collection of all generations and is equivalent to calling: GC.Collect(GC.MaxGeneration); Under most circumstances, you should avoid calling any of the Collect methods; it is best to just let the garbage collector run on its own accord. However, since your application knows more about its behavior than the runtime does, you could help matters by explicitly forcing some collections. For example, it might make sense for your application to force a full collection of all generations after the user saves his data file. I imagine Internet browsers performing a full collection when pages are unloaded. You might also want to force a collection when your application is performing other lengthy operations; this hides the fact that the collection is taking processing time and prevents a collection from occurring when the user is interacting with your application. The GC type also offers a WaitForPendingFinalizers method. This method simply suspends the calling thread until the thread processing the freachable queue has emptied the queue, calling each object's Finalize method. In most applications, it is unlikely that you will ever have to call this method. Lastly, the garbage collector offers two methods that allow you to determine which 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. Of course, the value returned will be somewhere between 0 and GC.MaxGeneration, inclusive.

Multi File Assembly
This section provides a complete example that illustrates the steps required to create a multifile assembly. Step 1 — Compiling Files with Namespaces Referenced by Other Files This example starts with some simple code for the Stringer file. Stringer has a namespace called myStringer with a class called Stringer. The Stringer class contains a method called StringerMethod that writes a single line to the console. [C#] // Assembly building example in the .NET Framework SDK. using System; namespace myStringer { public class Stringer { public void StringerMethod() { System.Console.WriteLine("This is a line from StringerMethod."); }

124 } } Use the following command to compile this code: [C#] csc /t:module Stringer.cs Specifying the module parameter with the /t: compiler option indicates that the file should be compiled as a module rather than as an assembly. The compiler produces a module called Stringer.netmodule, which can be added to an assembly. Step 2 — Compiling Modules with References to Other Modules This step uses the /addmodule compiler option. In this example, a code module called Client has an entry point Main method that references a method in the Stringer.dll module created in Step 1. The following example shows the code for Client. [C#] using System; using myStringer; //The namespace created in Stringer.netmodule. class MainClientApp { // Static method Main is the entry point method. public static void Main() { Stringer myStringInstance = new Stringer(); Console.WriteLine("Client code executes"); //myStringComp.Stringer(); myStringInstance.StringerMethod(); } } Use the following command to compile this code: [C#] csc /addmodule:Stringer.netmodule /t:module Client.cs Specify the /t:module option because this module will be added to an assembly in a future step. Specify the /addmodule option because the code in Client references a namespace created by the code in Stringer.netmodule. The compiler produces a module called Client.netmodule that contains a reference to another module, Stringer.netmodule. Note The C# and Visual Basic compilers support directly creating multifile assemblies using the following two different syntaxes.       Two compilations create a two-file assembly: [Visual Basic] vbc /t:module Stringer.vb vbc Client.vb /addmodule:Stringer.netmodule [C#] csc /t:module Stringer.cs csc Client.cs /addmodule:Stringer.netmodule    One compilation creates a two-file assembly: [Visual Basic] vbc /out:Stringer.netmodule Stringer.vb /out:Client.exe Client.vb

125  [C#] csc /out:Client.exe Client.cs /out:Stringer.netmodule Stringer.cs Step 3 — Creating a Multifile Assembly Using the Assembly Linker You can use the Assembly Linker (Al.exe) to create an assembly from a collection of compiled code modules. To create a multifile assembly using the Assembly Linker  At the command prompt, type the following command: al <module name> <module name> ... /main:<method name> /out:<file name> /target:<assembly file type> In this command, the module name arguments specify the name of each module to include in the assembly. The /main: option specifies the method name that is the assembly's entry point. The /out: option specifies the name of the output file, which contains assembly metadata. The /target: option specifies that the assembly is a console application executable (.exe) file, a Windows executable (.win) file, or a library (.lib) file. In the following example, Al.exe creates an assembly that is a console application executable called myAssembly.exe. The application consists of two modules called Client.netmodule and Stringer.netmodule, and the executable file called myAssembly.exe, which contains only assembly metadata . The entry point of the assembly is the Main method in the class MainClientApp, which is located in Client.dll. al Client.netmodule Stringer.netmodule /main:MainClientApp.Main /out:myAssembly.exe /target:exe You can use the MSIL Disassembler (Ildasm.exe) to examine the contents of an assembly, or determine whether a file is an assembly or a module.

NET Remoting Versus Web Services
With the advent of .NET and the .NET Framework, Microsoft introduced a set of new technologies in the form of Web services and .NET remoting. .NET remoting and ASP.NET Web services are powerful technologies that provide a suitable framework for developing distributed applications. It is important to understand how both technologies work and then choose the one that is right for your application. The Web services technology enables cross-platform integration by using HTTP, XML and SOAP for communication thereby enabling true business-to-business application integrations across firewalls. Because Web services rely on industry standards to expose application functionality on the Internet, they are independent of programming language, platform and device. Remoting is .a technology that allows programs and software components to interact across application domains, processes, and machine boundaries. This enables your applications to take advantage of remote resources in a networked environment. Both Web services and remoting support developing distributed applications and application integration, but you need to consider how they differ before choosing one implementation over the other. In this article, I will show the differences between these two technologies. I will present samples for each type of implementation and identify when to use which technology.

126 DCOM If you are a real Microsoft platform developer then you have done some work on COM and interface based components. When it comes to distributing your program logic, you are almost tied to Distributed COM (DCOM). DCOM is a very proprietary RPC-based communication protocol for COMbased distributed component architectures. Even though DCOM allows us to create scalable and reliable architectures in the Intranet environment, there are a lot of problems with DCOM when you try to integrate with different platforms and technologies in an Internet environment.

A Look at .NET Remoting .NET Remoting uses a flexible and extremely extensible architecture. Remoting uses the .NET concept of an Application Domain (AppDomain) to determine its activity. An AppDomain is an abstract construct for ensuring isolation of data and code, but not having to rely on operating system specific concepts such as processes or threads. A process can contain multiple AppDomains but one AppDomain can only exist in exactly one process. If a call from program logic crosses an AppDomain boundary then .NET Remoting will come into place. An object is considered local if it resides in the same AppDomain as the caller. If the object is not in the same appdomain as the caller, then it is considered remote. In .NET remoting, the remote object is implemented in a class that derives from System.MarshalByRefObject. The MarshalByRefObject class provides the core foundation for enabling remote access of objects across application domains. A remote object is confined to the application domain where it is created. In .NET remoting, a client doesn't call the methods directly; instead a proxy object is used to invoke methods on the remote object. Every public method that we define in the remote object class is available to be called from clients.

When a client calls the remote method, the proxy receives the call, encodes the message using an appropriate formatter, then sends the call over the channel to the server process. A listening channel on the server appdomain picks up the request and forwards it to the server remoting system, which locates and invokes the methods on the requested object. Once the execution is completed, the process is reversed and the results are returned back to the client.

127 Out of the box, the remoting framework comes with two formatters: the binary and SOAP formatters. The binary formatter is extremely fast, and encodes method calls in a proprietary, binary format. The SOAP formatter is slower, but it allows developers to encode the remote messages in a SOAP format. If neither formatter fits your needs, developers are free to write their own and plug it in as a replacement. Different Types of Remote Objects The remoting infrastructure allows you to create two distinct types of remote objects. 1. Client-activated objects - A client-activated object is a server-side object whose creation and destruction is controlled by the client application. An instance of the remote object is created when the client calls the new operator on the server object. This instance lives as long as the client needs it, and lives across one to many method calls. The object will be subject to garbage collection once it's determined that no other clients need it. 2. Server-activated objects - A server-activated object's lifetime is managed by the remote server, not the client that instantiates the object. This differs from the client-activated object, where the client governs when the object will be marked for finalization. It is important to understand that the server-activated objects are not created when a client calls New or Activator.GetObject. They are rather created when the client actually invokes a method on the proxy. There are two types of server activated objects. They are: o Single call . Single-call objects handle one, and only one, request coming from a client. When the client calls a method on a single call object, the object constructs itself, performs whatever action the method calls for, and the object is then subject to garbage collection. No state is held between calls, and each call (no matter what client it came from) is called on a new object instance. o Singleton - The difference in a singleton and single call lies in lifetime management. While single-call objects are stateless in nature, singletons are stateful objects, meaning that they can be used to retain state across multiple method calls. A singleton
object instance serves multiple clients, allowing those clients to share data among themselves.

A Look At ASP.NET Web Services With the arrival of .NET, creating an ASP.NET Web service is a breezy experience with the .NET framework taking away all the complexities in creating and consuming Web services. To create a Web service, all you need to do is create a Web service class that derives from the System.Web.Services.WebService class and decorate the methods (that you want to expose as Web services) with the WebMethod attribute. Once this is done, these methods can be invoked by sending HTTP requests using SOAP. Consuming a Web service is very straightforward too. You can very easily create a proxy class for your Web service using either wsdl.exe utility or the Add Web Reference option in VS.NET. The Web service proxy hides all the network and marshaling plumbing from the application code, so using the Web service looks just like using any other local object.

128

As you can see from the above diagram, the client proxy receives the request from the client, serializes the request into a SOAP request which is then forwarded to the remote Web service. The remote Web service receives the SOAP request, executes the method, and sends the results in the form of a SOAP response to the client proxy, which deserializes the message and forwards the actual results to the client. ASP.NET Web Services Vs .NET Remoting Now that we have understood the basic concepts of .NET remoting and Web services, let us identify the differences between these two technologies. For this, I present different factors such as performance, state management, etc and then identify which technology to use in what situations. Performance In terms of performance, the .NET remoting plumbing provides the fastest communication when you use the TCP channel and the binary formatter. In the case of Web services, the primary issue is performance. The verbosity of XML can cause SOAP serialization to be many times slower than a binary formatter. Additionally, string manipulation is very slow when compared to processing the individual bits of a binary stream. All data transported across the wire is formatted into a SOAP packet. However if your Web service performs computation intensive operations, you might want to consider using caching to increase the performance of your Web service on the server side. This will increase the scalability of the Web service, which in turn can contribute to the increase in performance of the Web service consumers. A remoting component, using the TCP channel and the binary formatter, provides the greatest performance of any remoting scenario, primarily because the binary formatter is able to serialize and deserialize data much faster. If you use .NET remoting with a SOAP formatter, you will find that the performance provided by ASP.NET Web services is better than the performance provided by NET remoting endpoints that used the SOAP formatter with either the HTTP or the TCP channel. However the .NET remoting provides clear performance advantages over ASP.NET Web services only when you use TCP channels with binary communication. State Management Web services are a stateless programming model, which means each incoming request is handled independently. In addition, each time a client invokes an ASP.NET Web service, a new object is created to service the request. The object is destroyed after the method call completes. To maintain

129 state between requests, you can either use the same techniques used by ASP.NET pages, i.e., the Session and Application objects, or you can implement your own custom solution. However it is important to remember that maintaining state can be costly with Web services as they use extensive memory resources. .NET remoting supports a range of state management options that you can choose from. As mentioned before, SingleCall objects are stateless, Singleton objects can share state for all clients, and client-activated objects maintain state on a per-client basis. Having three types of remote objects (as opposed to one with Web services) during the design phase helps us create more efficient, scalable applications. If you don't need to maintain state, use single-call objects; if you need to maintain state in a small section of code, use single call and singletons together. The ability to mix and match the various object types facilitates creation of solid architectural designs. Security .NET remoting plumbing does not provide out of the box support for securing cross-process invocations. However a .NET remoting object hosted in IIS, can leverage all the same security features provided by IIS. If you are using the TCP channel or the HTTP channel hosted in a container other than IIS, you have to implement authentication, authorization and privacy mechanisms yourself. Since ASP.NET Web services are hosted, by default, in IIS, they benefit from all the security features of IIS such as support for secure communication over the wire using SSL, authentication and authorization services. Reliability .NET remoting gives you the flexibility to host remote objects in any type of application including a Windows Form, a managed Windows Service, a console application or the ASP.NET worker process. If you host your remote objects in a windows service, or a console application, you need to make sure that you provide features such as fault tolerance within your hosting application so that the reliability of the remote object is not compromised. However if you do host remote objects in IIS, then you can take advantage of the fact that the ASP.NET worker process is both auto-starting and thread-safe. In the case of ASP.NET Web services, reliability is not a consideration as they are always hosted in IIS, making it easy for them to take advantage of the capabilities provided by IIS. Extensibility Both the ASP.NET Web services and the .NET remoting infrastructures are extensible. You can filter inbound and outbound messages, control aspects of type marshaling and metadata generation. .NET remoting takes extensibility to the next level allowing you to implement your own formatters and channels. Since ASP.NET Web services rely on the System.Xml.Serialization.XmlSerializer class to marshal data to and from SOAP messages at runtime, we can very easily customize the marshaling by adding a set of custom attributes that can be used to control the serialization process. As a result, you have very fine-grained control over the shape of the XML being generated when an object is serialized. Ease of programming and deployment In this section, we will consider a simple remoting object and an ASP.NET Web service to understand the complexities involved in creating and consuming them. We will start off by creating a simple remote object. Creating a remote object Creating a remoting object is a simple process. To create a remote object, you need to inherit from MarshalByRefObject class. The following code shows a remotable class. using System; namespace RemoteClassLib { public class MyRemoteObject : System.MarshalByRefObject

130 { public MyRemoteObject() { Console.WriteLine("Constructor called"); } public string Hello(string name) { Console.WriteLine("Hello Called"); return "Hello " + name; } } } The above code is very simple and straightforward. We start off by defining a class that inherits from MarshalByRefObject. After that we add code to the constructor of the class to write out a message to the console. Then we have a method named Hello that basically takes a string argument and appends that with the string and returns the concatenated value back to the caller. Once the remote object is created, the next step is to create a host application that hosts the remote object. For the purposes of this article, we will create a console application that reads the details of the remote object from its configuration file. using System; using System.Runtime.Remoting; namespace RemoteClassLibServer { class RemoteServer { [STAThread] static void Main(string[] args) { RemotingConfiguration.Configure( "RemoteClassLibServer.exe.config"); Console.WriteLine("Press return to Exit"); Console.ReadLine(); } } } In the main method, we just read the configuration settings from the configuration file using the RemotingConfiguration.Configure method and wait for the client applications to connect to it. The configuration file used by the above hosting application looks like the following. In the configuration file, we specify that we want to expose the remote object using the TCP channel by using the channel element. <?xml version="1.0" encoding="utf-8" ?> <configuration> <system.runtime.remoting> <application name="RemoteClassLibServer"> <service> <wellknown mode="SingleCall" type="RemoteClassLib.MyRemoteObject,RemoteClassLib" objectUri="MyRemoteObject"> </wellknown> </service> <channels> <channel ref="tcp server" port="9000"/> </channels> </application> </system.runtime.remoting>

131 </configuration> Once the hosting application is started, then client applications can start creating instances of the remote object and invoke its methods. In the next section, we will understand the processes involved in creating an ASP.NET Web service. Creating an ASP.NET Web Service As mentioned before, creating an ASP.NET Web service is pretty easy in VS.NET. Select the ASP.NET Web Service template using Visual Studio.NET New Project dialog box. Enter the name of the project and click OK to create the project. Once the project is created, modify the default service1.asmx file to look like the following. using using using using using using using System; System.Collections; System.ComponentModel; System.Data; System.Diagnostics; System.Web; System.Web.Services;

namespace XmlWebServicesExample { public class Service1 : System.Web.Services.WebService { public Service1() { } [WebMethod (EnableSession=true)] public string HelloWorld() { return "Hello World"; } } } As you can see from the above, the Web service class named Service1 is derived from System.Web.Services.WebService. Inheriting from the WebService class is optional and it is used to gain access to common ASP.NET objects like Application, Session, User, and Context. Then we also add a method named HelloWorld that basically returns a simple string back to the callers of the Web service. In the WebMethod attribute of the HelloWorld method, we also specify that we want to enable session state for our ASP.NET Web service by setting the EnableSession attribute to true. Creating the consumer for the ASP.NET Web Service You can consume the Web service by using the Add Web Reference option in VS.NET to create a proxy for the Web service. When you create a Web reference, the VS.NET IDE creates a proxy for you based on the WSDL file published by the Web service. Once the proxy is generated, you can treat the proxy class methods as if they are the actual Web service methods. At runtime, when the proxy class methods are invoked, they will connect to the actual Web service, invoke the Web service method, retrieve the results returned by the Web service and hand it back to the consumers. The following screenshot shows how to use the Add Web Reference option to create a proxy for the Web service.

132

So far, we have seen the steps involved in creating a .NET remoting object and an ASP.NET Web service. As can be seen from the above code, ASP.NET Web services are very easy-to-create. Consuming ASP.NET Web service is also a very simple process due to the excellent Web service support provided by Visual Studio.NET. With .NET remoting, you need to create the remote object first and then write a hosting application (assuming that you are not using IIS) to expose that remote object. You also need to make sure that the information about the remote object is retrieved from the configuration file to allow for extensibility in the future. If you all these factors into consideration, you will agree that .NET remoting objects are complex to develop and deploy. Type Fidelity ASP.NET Web services favor the XML schema type system, and provide a simple programming model with broad cross-platform reach. .NET remoting favors the runtime type system, and provides a more complex programming model with much more limited reach. This essential difference is the primary factor in determining which technology to use. Putting it all together So far, we have looked at the differences between these two technologies. Let us summarize the difference in a table. ASP.NET Web Services Protocol State Management Can be accessed only over HTTP Web services work in a stateless environment .NET Remoting Can be accessed over any protocol (including TCP, HTTP, SMTP and so on) Provide support for both stateful and stateless environments through Singleton and SingleCall objects Using binary communication, .NET Remoting can provide support for rich type system .NET remoting requires the client be built using .NET, enforcing homogenous environment.

Web services support only the datatypes defined in the XSD type Type System system, limiting the number of objects that can be serialized. Web services support interoperability Interoperability across platforms, and are ideal for heterogeneous environments.

Reliability

Extensibility Ease-ofProgramming

133 Can also take advantage of IIS for fault Highly reliable due to the fact that isolation. If IIS is not used, application Web services are always hosted in IIS needs to provide plumbing for ensuring the reliability of the application. Provides extensibility by allowing us to Very extensible by allowing us to customize intercept the SOAP messages during the different components of the .NET the serialization and deserialization remoting framework. stages. Easy-to-create and deploy. Complex to program.

Though both the .NET Remoting infrastructure and ASP.NET Web services can enable cross-process communication, each is designed to benefit a different target audience. ASP.NET Web services provide a simple programming model and a wide reach. .NET Remoting provides a more complex programming model and has a much narrower reach. As explained before, the clear performance advantage provided by TCPChannel-remoting should make you think about using this channel whenever you can afford to do so. If you can create direct TCP connections from your clients to your server and if you need to support only the .NET platform, you should go for this channel. If you are going to go cross-platform or you have the requirement of supporting SOAP via HTTP, you should definitely go for ASP.NET Web services. Combination of .NET Remoting and ASP.NET Web Services in Action

So far, we have understood how the .NET remoting and ASP.NET Web services technologies differ in implementation. We have also had a detailed look at different factors to understand what technology to choose in what situation. Even though these two technologies are meant for different purposes, there are times where you will be able to use the combination of these technologies in your application. For example, in an application scenario where you are trying to address the needs of both internet and intranet clients, you might consider using both .NET remoting and Web services as shown in the above diagram. For the intranet .NET clients, you can use .NET remoting to enable cross appdomain communication. For the internet clients, you can expose the same functionality as Web services, allowing client applications running in different platforms to take advantage of the Web service.

134 Conclusion Both the .NET remoting and ASP.NET Web services are powerful technologies that provide a suitable framework for developing distributed applications. It is important to understand how both technologies work and then choose the one that is right for your application. For applications that require interoperability and must function over public networks, Web services are probably the best bet. For those that require communications with other .NET components and where performance is a key priority, .NET Remoting is the best choice. In short, use Web services when you need to send and receive data from different computing platforms, use .NET Remoting when sending and receiving data between .NET applications. In some architectural scenarios, you might also be able to use.NET Remoting in conjunction with ASP.NET Web services and take advantage of the best of both worlds.

OOPS Concept

1) Access Modifiers: C# Access Modifier Public Private (default) Protected Meaning Marks a member as accessible from an object variable as well as any derived classes. Marks a method as accessible only by the class that has defined the method. In C#, all members are private by default. Marks a method as usable by the defining class, as well as any derived classes. Protected methods, however, are not accessible from an object variable. Defines a method that is accessible by any type in the same assembly, but not outside the assembly. Defines a method whose access is limited to the current assembly or types derived from the defining class in the current assembly. Unmarked members are private by default in C#.

Internal protected internal

class SomeClass { // Accessible anywhere. public void PublicMethod(){} // Accessible only from SomeClass types. private void PrivateMethod(){} // Accessible from SomeClass and any descendent. protected void ProtectedMethod(){} // Accessible from within the same assembly. internal void InternalMethod(){} // Assembly-protected access. protected internal void ProtectedInternalMethod(){} // Unmarked members are private by default in C#. void SomeMethod(){} }

2) What is default modifier of class, function and variables? Prepare list for same. Class Methods Variables Constructor Interface Static Method Internal Private Private Private Public Private

135 3) Can we create static internal method? Method can be declared as static internal and can be used with Class name. 4) Can Non Static class contain static functions? Static Methods can be declared in a non static class. Q1 In C# How do you call a member of a base class from within a derived class? 1. There is no way to call like thar 2. using the key word 'MyBase' 3. using the key word 'base' 4. using the key word 'this' Ans: base Q2 Which of the following operations can you NOT perform on an ADO.NET DataSet? 1. A DataSet can be synchronised with the database. 2. A DataSet can be converted to XML. 3. A DataSet can be synchronised with a RecordSet. 4. You can infer the schema from a DataSet. Ans: A DataSet can be synchronised with a RecordSet Q3 Which of these statements correctly declares a two-dimensional array in C#? 1. int[,] myArray; 2. int[][] myArray; 3. int[2] myArray; 4. System.Array[2] myArray; Ans: int[,] myArray; Q4 What is a delegate? 1. A strongly typed function pointer. 2. A light weight thread or process that can call a single method. 3. A reference to an object in a different process.

136 4. An inter-process message channel. Ans: A strongly typed function pointer Q5 In C#, a technique used to stream data is known as... 1. wading. 2. serialization. 3. crunching. 4. marshalling. Ans: serialization Q6 What is the output of following C# code? public interface Inter { void MyFun(); int MyProp { get; set; } } public class AClass:Inter { int aField; public AClass( ){ } public static void Main() { AClass aClass = new AClass(); Console.Write(aClass.MyProp); aClass.MyFun(); } void Inter.MyFun( ) { } public int MyProp { get { return aField; } set { aField = value; }}} 1. Exception 2. Syntax Error( aField is not intialised ). 3. MyFun() Console.WriteLine(" MyFun()");

137 4. Syntax Error( 'AClass' does not contain a definition for 'MyFun' ). 5. 0 MyFun() Ans: Syntax Error( 'AClass' does not contain a definition for 'MyFun' ). Q6. A static constructor can have parameters.True or False. 1. True 2. False Ans: False Q7. Does C# support multiple-inheritance? 1. No, use interfaces instead 2. yes, use interfaces instead 3. both one and two 4. none of the above Ans: No, use interfaces instead Q8. What happens when you include a Throw statement in the catch block? 1. Compilation Error 2. Current Exception is re-thrown 3. Runtime Error 4. Execution is abandoned Ans: Current Exception is re-thrown Q9. We can't use Indexers with structures. 1. True 2. False 3. Don't Know Ans: False Q10. classes can implement interfaces where as the structures can't. 1. True 2. False 3. Don't Know Ans: False Q11. What Should be done to avoid a class Inheritence in C#?

138 1. use "NonInhertable" keyword before class/method name 2. use "sealed" keyword before class/method name 3. use "abstract" keyword before class/method name 4. There is no provision in c# 5. None of the above Ans: use "sealed" keyword before class/method name Q12. Can Static Methods can be overridable? 1. Yes 2. No 3. It Depends on how we declare them 4. It depends on sccessspecifiers Ans: No Q13. When Static Constructors invokes 1. When we create the object of the class 2. When we create a Class 3. It is called before the first instance is created 4. All the above Ans: It is called before the first instance is created. Q14. What is the accessibility modifier for methods inside the interface? 1. Private by default 2. Public by default 3. protected 4. Friend Ans: Public by default Q15. Can you override private virtual methods? 1. Yes 2. No 3. Either 1 0r 2 4. None Ans: No

139 Q16. Is it possible to have different access modifiers on the get/set methods of a property? Yes No Ans: No. The access modifier on a property applies to both its get and set accessors. What you need to do if you want them to be different is make the property read- only (by only providing a get accessor) and create a private/internal set method that is separate from the property Q17. What is diffrence between Interface and abstract class. 1. Both are same. 2. unlike abstracts class interface class have no implementation. 3. interface require inheritance Ans: unlike abstracts class interface class have no implementation. Q19. What is the printout of the following? What is the printout of the following? byte b1=1; byte b2=255; byte total=b1+b2; Console.WriteLine (total);

1. We will get a runtime error 2. We will get a compilation error 3. 256 4. 1 Ans: We will get a compilation error. Q20 What is the error in the following code Public Interface ITest1() { } Public Interface ITest2() { void MySub(){} } void MySub(){ }

140 Public Class MyTest: ITest1, ITest2 { Public void MySub() :ITest1.MySub { } Public Sub MySub1() :ITest2.MySub { } } }Public Class Test:MyTest, ITest2 { } 1. Compile Time Error - Itest2.MySub is not implemented in Class Test 2. Compile Time Error - ITest2 is already implemented by base class 3. Compile Time Error - MySub cannot be implemented as both ITest1 and ITest2 have the same method name 4. Runtime Error

Ans : Compile Time Error - ITest2 is already implemented by base class Plain Text Attachment [ Download File | Save to Yahoo! Briefcase ] Q1. How to implement Multiple Inheritance in C# ? 1. Using Interface 2. Using Abstract Class 3. Using Delegates 4. Using Events 5. Using All 6. Using Interface & Delegates only Ans: Using Interface Q2. What is the size of Session ID? 1. 32-bit long string 2. 32-bit long double 3. 32-bit long char 4. 32-bit long integers Ans: 32-bit long integers Q3. Which of the following forms of caching involves the storing of Arbitrary objects across multiple requests?

141 1. Page output caching 2. Fragment caching 3. Page data caching 4. None of the above Ans: Page data caching Q4. If browsers do not support client-side cookies, what state Maintenance approach can be used? 1. Client-side 2. Server-side 3. Cookieless 4. None of the above Ans: 3 Cookieless Q5 Which language can support SOAP? 1. VB 2. JAVA 3. COBOL 4. ALL OF ABOVE aNS: 4 ALL OF ABOVE Q6. How many ways are there in asp.net for managing persistent user state ? 1. Nine 2. four 3. five 4. seven Ans: Nine Q7 What is finalise method and what are the role of it? 1. Release object memory 2. Release memory 3. it calls when page is closed 4. All of the above Ans: Release object memory Q8 it is NOT possible for any class method in the System namespace to be used directly without first creating an object from the class. Is it true? 1. True 2. False Ans: False Q9 If Date is interpreted as 0 (numeric) Sql server Inter Prets as 1. 1754 dec31 2. 1854Mar 17 3. 1900 jan1 4. 1854 dec31 5. 1857 dec31 Ans: 1900 jan1

142 Q10 Which property is used to specify whether a tree node label is displayed in the form of a hyperlink when the mouse pointer moves over it? 1. TopNode 2. SelectedNode 3. HotTracking 4. Nodes Ans: HotTracking Q11 The only control(s)s that are avialble in HTML and not in WebControl(s) is 1. FileField 2. Input Hidden 3. Group controls like Flow Layout, Grid Layout 4. None Ans: FileField & Input Hidden Q13 What is the total no. of events in Global.asax file in Asp.NET? 1. 20 2. 25 3. 19 4. 32 Ans: 19 Q14 which of the following OleDbConnection properties is used to obtain the database to which an OleDbConnection object is connected? 1. Provider 2. DataSource 3. Database 4. UserID 5. Database Provider Ans: Database Q15 What data type does the RangeValidator control support? 1. Integer 2. Date 3. Boolean 4. String 5. all of the above 6. 1 and 2 7. 1,2 and 4 Ans: 1,2 and 4 Q16 Which of the following in not a session stste mode? 1. Inproc 2. Outproc 3. StateServer 4. SqlServer 5. OracleServer Ans OutProc

143 Q17 What is the default executionTimeout of an aspx page? 1. 30s 2. 60s 3. 90s 4. 120s Ans: 90s Q18 Which of the following are authentication methods? 1. Web, windows, passport 2. Web, forms, none 3. Windows, Passport, Forms, None 4. None of the above Ans: Windows, Passport, Forms, None Q19 What is the default authendication mode in aps.net web application? 1. Windows 2. Passport 3. Form 4. Client Certificate 5. Cookies ANs: Windows Q20 what is the difference between Server.Transfer and response.Redirect? 1. No difference 2. Server.Transfer needs a Round Trip, Response.Rediect not 3. Response.Rediect needs Rountrip to bowser Server.Transfer does not need a Round Trip, 4. Server.Transfer can transfer user between two applications Ans: Response.Rediect needs Rountrip to bowser Server.Transfer does not need a Round Trip,

Remoting
What is .NET Remoting? .NET Remoting is an enabler for application communication. It is a generic system for different applications to use to communicate with one another. .NET objects are exposed to remote processes, thus allowing interprocess communication. The applications can be located on the same computer, different computers on the same network, or even computers across separate networks. .NET Remoting versus Distributed COM In the past interprocess communication between applications was handled through Distributed COM, or DCOM. DCOM works well and the performance is adequate when applications exist on computers of similar type on the same network. However, DCOM has its drawbacks in the Internet connected world. DCOM relies on a proprietary binary protocol that not all object models support, which hinders interoperability across platforms. In addition, have you tried to get DCOM to work through a firewall? DCOM wants to communicate over a range of ports that are typically blocked by firewalls. There are a ways to get it to work, but they either decrease the effectiveness of the firewall (why bother to even have the firewall if you open up a ton of ports on it), or require you to get a firewall that allows support for binary traffic over port 80. .NET Remoting eliminates the difficulties of DCOM by supporting different transport protocol formats and communication protocols. This allows .NET Remoting to be adaptable to the network environment in which it is being used.

144 .NET Remoting versus Web Services Unless you have been living in a cave, or are way behind in your reading, you have probably read something about Web services. When you read the description of .NET Remoting it may remind you a lot of what you're read about Web services. That is because Web services fall under the umbrella of .NET Remoting, but have a simplified programming model and are intended for a wide target audience. Web services involve allowing applications to exchange messages in a way that is platform, object model, and programming language independent. Web services are stateless and know nothing about the client that is making the request. The clients communicate by transferring messages back and forth in a specific format known as the Simple Object Access Protocol, or SOAP. (Want to get some funny looks in the hallway? Stand around in the hallway near the marketing department with your colleagues and discuss the benefits of using SOAP). The following list outlines some of the major differences between .NET Remoting and Web services that will help you to decide when to use one or the other:   ASP.NET based Web services can only be accessed over HTTP. .NET Remoting can be used across any protocol. Web services work in a stateless environment where each request results in a new object created to service the request. .NET Remoting supports state management options and can correlate multiple calls from the same client and support callbacks. Web services serialize objects through XML contained in the SOAP messages and can thus only handle items that can be fully expressed in XML. .NET Remoting relies on the existence of the common language runtime assemblies that contain information about data types. This limits the information that must be passed about an object and allows objects to be passed by value or by reference. Web services support interoperability across platforms and are good for heterogeneous environments. .NET Remoting requires the clients be built using .NET, or another framework that supports .NET Remoting, which means a homogeneous environment.

Channels Remote objects are accessed through Channels. Channels physically transport the messages to and from remote objects. There are two existing channels TcpChannel and HttpChannel. Their names give away the protocols that they use. In addition, the TcpChannel or HttpChannel can be extended, or a new channel created if you determine the existing channels do not meet your needs. Create a Remotable Object A remotable object is nothing more than an object that inherits from MarshalByRefObject. The following sample demonstrates a simple class to expose the omnipresent hello world. This object exposes a single method HelloWorld that will return a string. The only values that can be returned from methods are the classes in the .NET Framework that are serializable such as string and DataSet. In addition, if you need to return a user-defined object then the object needs to be marked as serializable. Create a new C# class library project. Add a class called SampleObject and put in the following code. Add a reference to System.Runtime.Remoting in the project, otherwise the TcpChannel will not be found. Compile the class to make sure you have everything correct. using System; using System.Runtime.Remoting; using System.Runtime.Remoting.Channels; using System.Runtime.Remoting.Channels.Tcp; namespace CodeGuru.Remoting { /// <remarks> /// Sample object to demonstrate the use of .NET Remoting. /// </remarks> public class SampleObject : MarshalByRefObject { /// <summary>

145 /// Constructor /// </summary> public SampleObject() { } /// <summary> /// Return a hello message /// </summary> /// <returns>Hello world message</returns> public string HelloWorld() { return "Hello World!"; } } } Create a Server To Expose the Remotable Object We need to create a server object that will act as a listener to accept remote object requests. For this example we will use the TCP/IP channel. We first create an instance of the channel and then register it for use by clients at a specific port. The service can be registered as WellKnownObjectMode.SingleCall, which results in a new instance of the object for each client, or as WellKnownObjectMode.Singleton, which results in one instance of the object used for all clients. It is not necessary to create the server listener if you are planning to use IIS. For obvious reasons, IIS only supports the use of the HttpChannel. Create a virtual directory for your application and then put code to register your service in the Application_Start event. For our example, we'll go ahead and create a server listener in case you don't have IIS. Since the service needs to be bound to an available port, for our example I chose 8080, which is a port that I know to be unused on my computer. You may need to choose a different port depending upon what ports you have available. To see a list of the used ports on your computer open a command prompt and issue the command "netstat --a". It may produce a long listing so make sure the command prompt buffer sizes are set to allow scrolling. Compile the class to make sure you have everything correct. Create a new C# console application project. Add a class called SampleServer and paste in the following code. Add a reference to System.Runtime.Remoting in the project, otherwise the TcpChannel will not be found. In addition, add a reference to the project containing the SampleObject, otherwise the code will not compile because it won't know how to find a reference to SampleObject. using System; using System.Runtime.Remoting; using System.Runtime.Remoting.Channels; using System.Runtime.Remoting.Channels.Tcp; namespace CodeGuru.Remoting { /// <remarks> /// Sample server to demonstrate the use of .NET Remoting. /// </remarks> public class SampleServer { public static int Main(string [] args) { // Create an instance of a channel TcpChannel channel = new TcpChannel(8080); ChannelServices.RegisterChannel(channel); // Register as an available service with the name HelloWorld RemotingConfiguration.RegisterWellKnownServiceType( typeof(SampleObject), "HelloWorld",

146 WellKnownObjectMode.SingleCall ); System.Console.WriteLine("Press the enter key to exit..."); System.Console.ReadLine(); return 0; } } } Create a Client To Use the Remotable Object Now that we have our remotable object and a server object to listen for requests, let's create a client to use it. Our client will be very simple. It will connect to the server, create an instance of the object using the server, and then execute the HelloWorld method. Create a new C# console application project. Add a class called SampleClient and paste in the following code. Add a reference to System.Runtime.Remoting in the project, otherwise the TcpChannel will not be found. In addition, add a reference to the project containing the SampleObject, otherwise the code will not compile because it won't know how to find a reference to SampleObject. Compile the class to make sure you have everything correct. using System; using System.Runtime.Remoting; using System.Runtime.Remoting.Channels; using System.Runtime.Remoting.Channels.Tcp; namespace CodeGuru.Remoting { /// <remarks> /// Sample client to demonstrate the use of .NET Remoting. /// </remarks> public class SampleClient { public static int Main(string [] args) { // Create a channel for communicating w/ the remote object // Notice no port is specified on the client TcpChannel chan = new TcpChannel(); ChannelServices.RegisterChannel(chan); // Create an instance of the remote object SampleObject obj = (SampleObject) Activator.GetObject( typeof(CodeGuru.Remoting.SampleObject), "tcp://localhost:8080/HelloWorld" ); // Use the object if( obj.Equals(null) ) { System.Console.WriteLine("Error: unable to locate server"); } else { Console.WriteLine(obj.HelloWorld()); } return 0; } } }

147 Test the Remoting Sample Once you have created the projects and successfully compiled each of them you are ready to try it out. Assuming you chose a free TCP/IP port for the service, start the server executable. After the server successfully starts it will result in a console window being displayed with the message "Press the enter key to exit". The server is listening so you are now ready to run the client. Executing the client should result in "Hello World!" being displayed in a separate console window. The client window will then close while the server remains open and available. If you have multiple computers available to you on a network you could execute the server on one machine and the client on another just to prove to yourself that it really is remoting. In order to run on separate machines you would need to change the reference to localhost in the sample client to point to the appropriate location. Summary .NET Remoting is a powerful way to enable interprocess communication. It is more complicated to program against than Web services. You need to decide for yourself whether your standard architecture is to use .NET Remoting or Web services. The following list provides an overview of the key elements of the architecture:

  

A remote object is an object that’s running on the server. The client doesn’t call methods on this object directly, but uses a proxy instead. With .NET it’s easy to distinguish remote objects from local objects; every class that derived from MarshalByRefObject never leaves its application domain. The client can call methods of the remote object via a proxy. A channel is used for communication between the client and the server. There are client and server parts of the channel .NET Framework 1.1 offers two channel type that communicate via TCP or HTTP. You can also create a custom channel that communicates by using a different protocol. Messages are sent into a channel. Messages are created for communication between the client and the server. These messages hold the information about the remote object, the method name called, and all of the arguments. The formatter defines how messages are transferred into the channel. With .NET Framework 1.1, we have SOAP binary formatters. The SOAP formatter can be used to communicate with Web services that are not based on .NET Framework. Binary formatters are much faster and can be used efficiently in an intranet environment of course; you also have the possibility to create a custom formatter. A formatter provider is used to associate a formatter with a channel. By creating a channel, you can specify what formatter provider to use, and this in turn defines the formatter that is used to transfer the data into the channel. The client calls method on a proxy instead of the remote object. There are two types of proxies: the transparent proxy and real proxy. To the client, the transparent proxy looks likes the remote object. On the transparent proxy, the client can call the methods implemented by the remote objects. In a turn, the transparent proxy calls the Invoke() method on the real proxy. The Invoke() method uses the message sink to pass to the channel. Messages sink, or sink for short, is an interceptor object. Interceptors are used on both the client and server. A sink is associated with the channel. The real proxy uses the message sink to pass the message into the channel. Depending on where the sink is used, is known as envoy sink, a server context sink, an object context sink, and so on. The client can use an activator to create a remote object on the server or to get a proxy of a server-activated object. Remotingcongiguration is a utility class to configure remote servers and clients. This class can be used either to read configuration files, or to configure remote objects dynamically. Channelservices is a utility class to register channels and then to dispatch messages to them.

148

State Management in ASP.NET
Web form pages are HTTP-Based, they are stateless, which means they don’t know whether the requests are all from the same client, and pages are destroyed and recreated with each round trip to the server, therefore information will be lost, therefore state management is really an issue in developing web applications Mainly there are two different ways to manage web page’s state: Client-side and Server-side. 1. Client-side state management: There is no information maintained on the server between round trips. Information will be stored in the page or on the client’s computer. A. Cookies. A cookie is a small amount of data stored either in a text file on the client's file system or in-memory in the client browser session. Cookies are mainly used for tracking data settings. Let’s take an example: say we want to customize a welcome web page, when the user request the default web page, the application first to detect if the user has login before, we can retrieve the user information from cookies: if (Request.Cookies[“username”]!=null) lbMessage.text=”Dear “+Request.Cookies[“username”].Value+”, Welcome shopping here!”; else lbMessage.text=”Welcome shopping here!”; If you want to store client’s information, you can use the following code: Response.Cookies[“username’].Value=username; So next time when the user request the web page, you can easily recognize the user again. B. Hidden Field A hidden field does not render visibly in the browser, but you can set its properties just as you can with a standard control. When a page is submitted to the server, the content of a hidden field is sent in the HTTP Form collection along with the values of other controls. A hidden field acts as a repository for any page-specific information that you would like to store directly in the page. Hidden field stores a single variable in its value property and must be explicitly added it to the page. ASP.NET provides the HtmlInputHidden control that offers hidden field functionality. protected System.Web.UI.HtmlControls.HtmlInputHidden Hidden1; //to assign a value to Hidden field Hidden1.Value=”this is a test”; //to retrieve a value string str=Hidden1.Value; Note: Keep in mind, in order to use hidden field, you have to use HTTP-Post method to post web page. Although its name is ‘Hidden’, its value is not hidden; you can see its value through ‘view source’ function. C. View State Each control on a Web Forms page, including the page itself, has a ViewState property; it is a builtin struture for automatic retention of page and control state, which means you don’t need to do anything about getting back the data of controls after posting page to the server. Here, which is useful to us is the ViewState property; we can use it to save information between round trips to the server. //to save information ViewState.Add(“shape”,”circle”); //to retrieve information string shapes=ViewState[“shape”]; D. Query Strings Query strings provide a simple but limited way of maintaining some state information. You can easily pass information from one page to another, But most browsers and client devices impose a

149 255-character limit on the length of the URL. In addition, the query values are exposed to the Internet via the URL so in some cases security may be an issue. A URL with query strings may look like this: http://www.examples.com/list.aspx?categoryid=1&productid=101 When list.aspx is being requested, the category and product information can be obtained by using the following codes: string categoryid, productid; categoryid=Request.Params[“categoryid”]; productid=Request.Params[“productid”]; Note: you can only use HTTP-Get method to post the web page, or you will never get the value from query strings. 2. Server-side state management: Information will be stored on the server, it has higher security but it can use more web server resources. A. Application object The Application object provides a mechanism for storing data that is accessible to all code running within the Web application, the ideal data to insert into application state variables is data that is shared by multiple sessions and does not change often. And just because it is visible to the entire application, you need to used Lock and UnLock pair to avoid having conflit value. Application.Lock(); Application[“mydata”] =”mydata”; Application.UnLock(); B. Session object Session object can be used for storing session-specific information that needs to be maintained between server round trips and between requests for pages. Session object is per-client basis, which means different clients generate different session object.The ideal data to store in session-state variables is short-lived, sensitive data that is specific to an individual session. Each active ASP.NET session is identified and tracked using a 120-bit SessionID string containing URL-legal ASCII characters. SessionID values are generated using an algorithm that guarantees uniqueness so that sessions do not collide, and SessionID’s randomness makes it harder to guess the session ID of an existing session.SessionIDs are communicated across client-server requests either by an HTTP cookie or a modified URL, depending on how you set the application's configuration settings. Every web application must have a configuration file named web.config, it is a XML-Based file, there is a section name ‘sessionState’, and the following is an example: ‘cookieless’ option can be ‘true’ or ‘false’. When it is ‘false’(default value), ASP.NET will use HTTP cookie to identify users. When it is ‘true’, ASP.NET will randomly generate a unique number and put it just right ahead of the requested file, this number is used to identify users, you can see it on the address bar of IE: http://localhost/Management/(2yzakzez3eqxut45ukyzq3qp)/Default.aspx //to store information Session[“myname”]=”Mike”; //to retrieve information myname=Session[“myname”]; C. Database Database enables you to store large amount of information pertaining to state in your Web application. Sometimes users continually query the database by using the unique ID, you can save it in the database for use across multiple request for the pages in your site.

150 Summary Choosing among the options will depand upon your application, you have to think about the following before making any choose:

1. How much information do you need to store? 2. Does the client accept persistent or in-memory cookies? 3. Do you want to store the information on the client or server? 4. Is the information sensitive? 5. What kind of performance experience are you expecting from your pages?

Cookies- You need to store small amounts of information on the client and security is not an issue. Viewstate- You needs to store small amounts of information for a page that will post back to itself. Use of the ViewState property does supply semi-secure functionality. Hidden fields- You need to store small amounts of information for a page that will post back to itself or another page, and security is not an issue. Note You can use a hidden field only on pages that are submitted to the server. Querystring- You are transferring small amounts of information from one page to another and security is not an issue. Note You can use query strings only if you are requesting the same page, or another page via a link. Application state object- You are storing infrequently changed, application-scope information that is used by many users and security is not an issue. Do not store large quantities of information in an application state object. Session state object - You are storing short-lived information that is specific to an individual session, and security is an issue. Do not store large quantities of information in a session state object. Be aware that a session state object will be created and maintained for the lifetime of every session in your application. In applications hosting many users, this can occupy significant server resources and affect scalability. Database support- You are storing large amounts of information, managing transactions, or the information must survive application and session restarts. Data mining is a concern, and security is an issue.

Static Constructor
Notes for Static Constructors: 1. 2. 3. 4. 5. 6. There can be only one static constructor in the class. The static constructor should be without parameters. It can only access the static members of the class. There should be no access modifier in static constructor definition. A static constructor does not take access modifiers or have parameters. A static constructor is called automatically to initialize the class before the first instance is created or any static members are referenced. 7. A static constructor cannot be called directly. 8. The user has no control on when the static constructor is executed in the program. 9. A typical use of static constructors is when the class is using a log file and the constructor is used to write entries to this file. 10. Static constructors are also useful when creating wrapper classes for unmanaged code, when the constructor can call the LoadLibrary method Ok fine, all the above points are fine, but why is it like that? Let us go step by step here. Firstly, the call to the static method is made by the CLR and not by the object, so we do not need to have the access modifier to it. Secondly, it is going to be called by CLR, who can pass the parameters to it, if required. So we cannot have parameterized static constructor.

151 Thirdly, non-static members in the class are specific to the object instance. So static constructor, if allowed to work on non-static members, will reflect the changes in all the object instances, which is impractical. So static constructor can access only static members of the class. Fourthly, overloading needs the two methods to be different in terms of methods definition, which you cannot do with Static Constructors, so you can have at the most one static constructor in the class. Example public class Bus { // Static constructor: static Bus() { System.Console.WriteLine("The static constructor invoked."); } public static void Drive() { System.Console.WriteLine("The Drive method invoked."); } } class TestBus { static void Main() { Bus.Drive(); } } Copy Constructor class Person { private string name; private int age; // Copy constructor. public Person(Person previousPerson) { name = previousPerson.name; age = previousPerson.age; } // Instance constructor. public Person(string name, int age) { this.name = name; this.age = age; } // Get accessor. public string Details { get { return name + " is " + age.ToString();

152 } } } class TestPerson { static void Main() { // Create a new person object. Person person1 = new Person("George", 40); // Create another new object, copying person1. Person person2 = new Person(person1); System.Console.WriteLine(person2.Details); } } using System; using System.Collections.Generic; namespace Model { /// <summary> /// /// /// </summary> [Serializable] public class SearchType { // The available search types private const string SEARCH_BY_ID = null; private const string SEARCH_BY_CODE = null; private readonly string _id; /// <summary> /// The id used to represent this search type /// </summary> public string Id { get { return _id; } } private readonly string _description; /// <summary> /// A description of the Search Type /// </summary> public string Description { get { return _description; } } /// <summary> /// An instance of a Search type representing SearchType only with No /// </summary> public static readonly SearchType SearchById = new SearchType (SEARCH_BY_ID, " Reference"); /// <summary> /// An instance of a Search type representing SearchType only with Agency Code /// </summary> public static readonly SearchType SearchByCode = new SearchType(SEARCH_BY_ CODE, " Code");

153 /// <summary> /// overriding toString() method /// </summary> /// <returns>A description of the Search Type</returns> public override string ToString() { return Description; } /// <summary> /// Private parameterize constructor to initialized object /// </summary> /// <param name="id">string</param> /// <param name="description">string</param> private SearchType(string id, string description) { _id = id; _description = description; } } }

Static Constructor in C# and their Usages
Static constructor is used to initialize static data members as soon as the class is referenced first time, whereas an instance constructor is used to create an instance of that class with keyword.

C# supports two types of constructor, a class constructor (static constructor) and an instance constructor (non-static constructor). Static constructor is used to initialize static data members as soon as the class is referenced first time, whereas an instance constructor is used to create an instance of that class with <new> keyword. A static constructor does not take access modifiers or have parameters and can't access any non-static data member of a class. Since static constructor is a class constructor, they are guaranteed to be called as soon as we refer to that class or by creating an instance of that class. You may say, why not initialize static data members where we declare them in the code. Like this: private static int id = 10; private static string name = "jack"; Usages: Static data members can certainly be initialized at the time of their declaration but there are times when value of one static member may depend upon the value of another static member. In such cases we definitely need some mechanism to handle conditional initialization of static members. To handle such situation, C# provides static constructor. Examples: //File Name : Test.cs using System; namespace Constructor { class Test { //Declaration and initialization of static data member private static int id = 5; public static int Id

154 { get { return id; } } public static void print() { Console.WriteLine("Test.id = " + id); } static void Main(string[] args) { //Print the value of id Test.print(); } } } In the above example, static data member <id> is declared and initialized in same line. So if you compile and run this program your output would look similar to this : Test.id = 5 Lets create one more class similar to class Test but this time the value of its static data member would depend on the value of static data member <id> of class Test.id. //File Name: Test1.cs using System; namespace Constructor { class Test1 { private static int id ; //Static constructor, value of data member id is set conditionally here. //This type of initialization is not possible at the time of declaration. static Test1() { if( Test.Id < 10 ) { id = 20; } else { id = 100; } Console.WriteLine("Static<Class> Constructor for Class Test1 Called.."); } public static void print() { Console.WriteLine("Test1.id = " + id); } static void Main(string[] args) { //Print the value of id Test1.print(); } } } As you can see in the above static constructor, static data member <id> is initialized conditionally.

155 This type of initialization is not possible at the time of declaration. This is where static constructor comes in picture. So if you compile and run this program your output would look similar to this: Static<Class> Constructor for Class Test1 Called.. id = 20 Since <id> in class Test was initialized with a value of 5, therefore <id> in class Test1 got initialized to a value of 20. Some important point regarding static constructor from C# Language Specification and C# Programmer's Reference: 1) The static constructor for a class executes before any instance of the class is created. 2) The static constructor for a class executes before any of the static members for the class are referenced. 3) The static constructor for a class executes after the static field initializers (if any) for the class. 4) The static constructor for a class executes at most one time during a single program instantiation 5) A static constructor does not take access modifiers or have parameters. 6) A static constructor is called automatically to initialize the class before the first instance is created or any static members are referenced. 7) A static constructor cannot be called directly. 8) The user has no control on when the static constructor is executed in the program. 9) A typical use of static constructors is when the class is using a log file and the constructor is used to write entries to this file.

Structs in C#
This article introduces you to the differences between classes and structs in C#, and explains how to use structs correctly.

Why we need Structs? The basic reason is the ability to create types with value semantics, which, if properly used, leads to better performance in a managed environment. .NET supports the notion of value types and reference types. Instances of reference types get allocated in the managed heap and are garbage collected when there are no outstanding references to them. Instances of value types, on the other hand, are allocated in the stack, and hence allocated memory is reclaimed as soon as their scope ends. All C# primitive data types, except for System.String, are value types. In C#, structs are value types, classes are reference types. There are two ways you can create value types, in C#, using the enum keyword and the struct keyword. Using a value type instead of a reference type will result in fewer objects on the managed heap, which results in lesser load on the garbage collector (GC), less frequent GC cycles, and consequently better performance. However, value types have their downsides too. Passing around a big struct is definitely costlier than passing a reference, that's one obvious problem. The other problem is the overhead associated with boxing/unboxing. Apart from performance, there are times when you simply need types to have value semantics, which would be very difficult to implement if reference types are all you have. Differences between Class & Struct: 1. Struct and Inheritance structs derive from System.ValueType whereas classes derive from System.Object or one of its descendants. Of course, System.ValueType again derives from System.Object, but that's beside the point. structs cannot derive from any other class/struct, nor can they be derived from. However, a struct can implement any number of interfaces. Although, that when you

156 treat the struct as an interface, it gets implicitly boxed, as interfaces operate only on reference types. E.g. struct Foo : IFoo { int x; } and then: IFoo iFoo = new Foo(); an instance of Foo is created and boxed. All interface method calls then execute only on the boxed instance. 2. Constructors: Although the CLR allows it, C# does not allow structs to have a default parameterless constructor. The reason is that, for a value type, compilers by default neither generate a default constructor, nor do they generate a call to the default constructor. So, even if you happened to define a default constructor, it will not be called and that will only confuse you. To avoid such problems, the C# compiler disallows definition of a default constructor by the user. And because it doesn't generate a default constructor, you can't initialize fields when defining them, like: struct MyWrongFoo { int x = 1; } The compiler puts all this initialization code into the constructor (every constructor), and because there's no default constructor, you can't do the initialization. 3. Destructors: You cannot define destructors for structs. The compiler straightaway flags it as an error. Of course, structs can implement IDisposable (it being an interface), so you can always use the dispose pattern (with the extra boxing overhead). When to use Structs?  You want your type to look and feel like a primitive type.  You create a lot of instances, use them briefly, and then drop them. For e.g., within a loop.  The instances you create are not passed around a lot.  You don't want to derive from other types or let others derive from your type.  You want others to operate on a copy of your data (basically pass by value semantics). When not to use Structs?  The size of the struct (the sum of the sizes of its members) gets large. The reason is that beyond a particular size, the overhead involved in passing it around gets prohibitive. Microsoft recommends that the size of a struct should ideally be below 16 bytes, but it really is up to you. In case your struct has reference types as members, make sure you don't include the size of instances of reference types, just the size of the references.  You create instances, put them in a collection, iterate and modify elements in the collection. This will result in a lot of boxing/unboxing as FCL Collections operate on System.Object. Every addition will involve a boxing operation, and every modification will involve an unboxing followed by a boxing operation.

157

Typed DataSet:
Along with late bound access to values through weakly typed variables, the DataSet provides access to data through a strongly typed metaphor. Tables and columns that are part of the DataSet can be accessed using user-friendly names and strongly typed variables. A typed DataSet is a class that derives from a DataSet. As such, it inherits all the methods, events, and properties of a DataSet. Additionally, a typed DataSet provides strongly typed methods, events, and properties. This means you can access tables and columns by name, instead of using collectionbased methods. Aside from the improved readability of the code, a typed DataSet also allows the Visual Studio .NET code editor to automatically complete lines as you type. Additionally, the strongly typed DataSet provides access to values as the correct type at compile time. With a strongly typed DataSet, type mismatch errors are caught when the code is compiled rather than at run time.

Strongly Typed DataSet Given an XML Schema that complies with the XML Schema definition language (XSD) standard, you can generate a strongly typed DataSet using the XSD.exe tool provided with the .NET Framework SDK.
The following code shows the syntax for generating a DataSet using this tool. xsd.exe /d /l:CS XSDSchemaFileName.xsd /n:XSDSchema.Namespace In this syntax, the /d directive tells the tool to generate a DataSet, and the /l: tells the tool what language to use (for example, C# or Visual Basic .NET). The optional /n: directive tells the tool to also generate a namespace for the DataSet called XSDSchema.Namespace. The output of the command is XSDSchemaFileName.cs, which can be compiled and used in an ADO.NET application. The generated code can be compiled as a library or a module. The following code shows the syntax for compiling the generated code as a library using the C# compiler (csc.exe). csc.exe /t:library XSDSchemaFileName.cs /r:System.dll /r:System.Data.dll The /t: directive tells the tool to compile to a library, and the /r: directives specify dependent libraries required to compile. The output of the command is XSDSchemaFileName.dll, which can be passed to the compiler when compiling an ADO.NET application with the /r: directive. The following code shows the syntax for accessing the namespace passed to XSD.exe in an ADO.NET application. [Visual Basic] Imports XSDSchema.Namespace [C#] using XSDSchema.Namespace; The following code example uses a typed DataSet named CustomerDataSet to load a list of customers from the Northwind database. Once the data is loaded using the Fill method, the example loops through each customer in the Customers table using the typed CustomersRow (DataRow) object. This provides direct access to the CustomerID column, as opposed to accessing it through the DataColumnCollection. [Visual Basic] Dim custDS As CustomerDataSet= New CustomerDataSet() Dim custCMD As SqlDataAdapter New SqlDataAdapter("SELECT * FROM Customers", _ "Data Source=localhost;Integrated Security=SSPI;Initial Catalog=northwind")

158 custCMD.Fill(custDS, "Customers") Dim custRow As CustomerDataSet.CustomersRow For Each custRow In custDS.Customers Console.WriteLine(custRow.CustomerID) Next [C#] CustomerDataSet custDS = new CustomerDataSet(); SqlDataAdapter custCMD = new SqlDataAdapter("SELECT * FROM Customers", "Data Source=localhost;Integrated Security=SSPI;Initial Catalog=northwind"); custCMD.Fill(custDS, "Customers"); foreach(CustomerDataSet.CustomersRow custRow in custDS.Customers) Console.WriteLine(custRow.CustomerID); Following is the XML Schema used for the example. <?xml version="1.0" encoding="utf-8"?> <xs:schema id="CustomerDataSet" xmlns="" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata"> <xs:element name="CustomerDataSet" msdata:IsDataSet="true"> <xs:complexType> <xs:choice maxOccurs="unbounded"> <xs:element name="Customers"> <xs:complexType> <xs:sequence> <xs:element name="CustomerID" type="xs:string" minOccurs="0" /> </xs:sequence> </xs:complexType> </xs:element> </xs:choice> </xs:complexType> </xs:element> </xs:schema>

159

Webservises
ASP.NET AJAX provides the power of asynchronous JavaScript and XML to your web sites. AJAX makes web pages more responsive and interactive by reducing page refreshes or postbacks. It harnesses the power of client-side JavaScript and the XML HTTP object to provide these features. Although AJAX is essentially a client-side technique, most of its real-world deployments call for server-side processing. Most commonly, the data manipulated by your web site will reside in some RDBMS on the server. To make AJAX really useful, you need an easy and robust way to deal with this server-side data. Fortunately, ASP.NET AJAX provides a sound infrastructure for doing just that. AJAX communication happens between your browser and the server over the Internet. Naturally, web services can play a significant role in data transport and overall communication between the client and the server. This article shows how ASP.NET AJAX can consume ASP.NET web services. Software Requirements All the examples in this article are developed using the RC build of ASP.NET AJAX that you can download from ajax.asp.net. Moreover, you need to have SQL Server 2005 (Express Edition will do) with the Northwind database installed. The examples use Visual Studio 2005 as the IDE. Example Scenario The example develops a web form that acts as a data entry page for an Employees table of the Northwind database. Using ASP.NET AJAX features, this data entry page will consume a web service that allows you to SELECT, INSERT, UPDATE, and DELETE employees. Creating the Web Service To begin with, create a new web site using Visual Studio 2005. Notice that installing ASP.NET AJAX adds project templates to the New Web Site dialog, including the "ASP.NET AJAX Enabled Web Site" template (see Figure 1).

Click here for a larger image. Figure 1: The New Web Site Dialog with Added Templates A web site created using the "ASP.NET AJAX Enabled Web Site" template is different from a normal web site in the following ways:   It has a web.config file with a lot of ASP.NET AJAX-specific configuration information. It refers System.Web.Extensions assembly.

160 Of course, you can modify a normal web site to make it AJAX enabled, but this template simplifies your job. Now that you have created a new web site, add a new web service to it and name it EmployeeService.asmx. The EmployeeService will contain five web methods (see Table 1). Method Name Description

GetEmployees() Returns a list of employees from the Employees table. The list is returned in the form of an array of Employee objects. GetEmployee() Insert() Update() Delete() Accepts an EmployeeID and returns its details as an Employee object. Adds a new employee to the Employees table. Updates an existing employee from the Employees table. Deletes an existing employee from the Employees table.

Table 1. Web Methods in EmployeeService The GetEmployees() and GetEmployee() methods return data in the form of Employee object(s). Therefore, you first need to create a class called Employee. Right-click the App_Code folder of your web site and choose "Add New Item...". Add a new class called Employee. The following is the complete code that makes the Employee class: public class Employee { private int intEmployeeID; private string strFirstName; private string strLastName; public int EmployeeID { get { return intEmployeeID; } set { intEmployeeID = value; } } public string FirstName { get { return strFirstName; } set { strFirstName = value; } } public string LastName { get { return strLastName; } set { strLastName = value; }

161 } } The Employee class declares three provate variables for storing employee ID, first name, and last name, respectively. The three variables are wrapped inside three public properties: EmployeeID, FirstName, and LastName. Open the web.config file and add a <connectionStrings> section as follows: <connectionStrings> <add name="connstr" connectionString= "data source=.\sqlexpress; initial catalog=northwind; integrated security=true"/> </connectionStrings> This stores a database connection string that points to the Northwind database. Make sure to change SQL Server name/IP and authentication details to match your environment. Now, open EmployeeService.cs and add the following code: private string strConn = ""; public EmployeeService() { strConn = ConfigurationManager.ConnectionStrings["connstr"]. ConnectionString; } The code uses the ConfigurationManager class to read the connection string from the config file and stores it in a class-level variable called strConn. This variable is used further by all the other web methods. Now, add the GetEmployees web method as follows: [WebMethod] public Employee[] GetEmployees() { SqlConnection cnn = new SqlConnection(strConn); cnn.Open(); SqlCommand cmd = new SqlCommand(); cmd.Connection = cnn; cmd.CommandText = "select employeeid,firstname, lastname from employees"; SqlDataReader reader = cmd.ExecuteReader(); List<Employee> list = new List<Employee>(); while (reader.Read()) { Employee emp = new Employee(); emp.EmployeeID = reader.GetInt32(0); emp.FirstName = reader.GetString(1); emp.LastName = reader.GetString(2); list.Add(emp); } reader.Close(); cnn.Close(); return list.ToArray(); } The code creates new SqlConnection and SqlCommand objects. It then executes a SELECT query and fetches EmployeeID, FirstName, and LastName columns from the Employees table. The results are retrieved as SqlDataReader instances. Then, a generic-based List of Employee objects is created. A while loop iterates through the SqlDataReader. With each iteration, a new Employee object is

162 created and its EmployeeID, FirstName, and LastName properties are set. The Employee object then is added to the List. After the while loop completes, SqlDataReader and SqlConnection are closed. The return type of the GetEmployees() web method is an array of Employee objects. Hence, the generic List is converted into Employee array using the ToArray() method of the List class. Next, add a web method called GetEmployee() as follows: [WebMethod] public Employee GetEmployee(int pEmployeeId) { SqlConnection cnn = new SqlConnection(strConn); cnn.Open(); SqlCommand cmd = new SqlCommand(); cmd.Connection = cnn; cmd.CommandText = "select employeeid,firstname,lastname from employees where employeeid=@id"; SqlParameter id = new SqlParameter("@id", pEmployeeId); cmd.Parameters.Add(id); SqlDataReader reader = cmd.ExecuteReader(); Employee emp = new Employee(); while (reader.Read()) { emp.EmployeeID = reader.GetInt32(0); emp.FirstName = reader.GetString(1); emp.LastName = reader.GetString(2); } reader.Close(); cnn.Close(); return emp; } The GetEmployee() web method accepts an employee ID that is to be returned. The code is very similar to the previous code but this time it fetches only one employee. Note that you used SqlParameter to represent the passed EmployeeID. Now you can add the Insert(), Update(), and Delete() web methods as follows: [WebMethod] public int Insert(string pFirstName, string pLastName) { SqlConnection cnn = new SqlConnection(strConn); cnn.Open(); SqlCommand cmd = new SqlCommand(); cmd.Connection = cnn; cmd.CommandText = "insert into employees(firstname,lastname) values (@fname,@lname)"; SqlParameter fname = new SqlParameter("@fname", pFirstName); SqlParameter lname = new SqlParameter("@lname", pLastName); cmd.Parameters.Add(fname); cmd.Parameters.Add(lname); int i = cmd.ExecuteNonQuery(); cnn.Close(); return i; } [WebMethod] public int Update(int pEmployeeId,string pFirstName, string pLastName) { SqlConnection cnn = new SqlConnection(strConn); cnn.Open(); SqlCommand cmd = new SqlCommand(); cmd.Connection = cnn; cmd.CommandText = "update employees set firstname=@fname,

163 lastname=@lname where employeeid=@id"; SqlParameter fname = new SqlParameter("@fname", pFirstName); SqlParameter lname = new SqlParameter("@lname", pLastName); SqlParameter id = new SqlParameter("@id", pEmployeeId); cmd.Parameters.Add(fname); cmd.Parameters.Add(lname); cmd.Parameters.Add(id); int i = cmd.ExecuteNonQuery(); cnn.Close(); return i; } [WebMethod] public int Delete(int pEmployeeId) { SqlConnection cnn = new SqlConnection(strConn); cnn.Open(); SqlCommand cmd = new SqlCommand(); cmd.Connection = cnn; cmd.CommandText = "delete from employees where employeeid=@id"; SqlParameter id = new SqlParameter("@id", pEmployeeId); cmd.Parameters.Add(id); int i = cmd.ExecuteNonQuery(); cnn.Close(); return i; } The Insert() web method accepts the first name and last name of the employee to be added. It then creates an instance each of SqlConnection and SqlCommand and executes the INSERT statement using the ExecuteNonQuery() method of the SqlCommand object. Similarly, the Update() web method accepts the employee ID to be updated, along with new values for first name and last name, and fires an UPDATE statement. Finally, the Delete() web method accepts an employee ID that is to be deleted and fires a DELETE statement. This completes your web service. To this point, you have not done anything specific to AJAX functionality. Now, it's time to do just that. Modify your web service class definition as follows: using System.Web.Script.Services; ... ... [WebService(Namespace = "http://tempuri.org/")] [WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)] [ScriptService] public class EmployeeService : System.Web.Services.WebService { ... ... Notice the lines marked in bold. You have imported a namespace System.Web.Script.Services, which comes from the System.Web.Extensions assembly. The [ScriptService] attribute you'll use later is supplied by this namespace. The [ScriptService] attribute enables the web service to be called from the client-side JavaScript (i.e., ASP.NET AJAX). That's it! You are now ready to consume your web service from ASP.NET AJAX. How to Consume the Web Service In this section, you will create a web form that acts as a data entry page for the Employees table by consuming the web service you just created. To begin, add a new web form called EmployeeServiceClient.aspx to the web site. Open the toolbox by selecting the View > Toolbox menu option. On the toolbox, locate a node titled AJAX Extensions (see Figure 2).

164

Figure 2: The New Web Site Dialog with Added Templates The AJAX Extensions node displays all the ASP.NET AJAX components that you can use on a web form. Drag and drop a ScriptManager component on the web form. Every web form making use of ASP.NET AJAX needs one ScriptManager component. Open the properties window for the ScriptManager. Locate its Services property and open the Service Reference collection editor as shown in Figure 3.

Click here for a larger image. Figure 3: The Service Reference Collection Editor Click the Add button at the bottom of the dialog and set the Path property to the virtual path of the web service (in other words, EmployeeService.asmx). This will generate the following markup in the web form file: <asp:ScriptManager ID="ScriptManager1" runat="server" > <Services> <asp:ServiceReference Path="EmployeeService.asmx" /> </Services> </asp:ScriptManager> For each web service that you want to consume, you need one <asp:ServiceReference> element inside the <asp:ScriptManager> section. The <asp:ServiceReference> tag registers a web service to use in the current web form. Now, design the web form as shown in Figure 4.

165

Figure 4: Design the Web Form The web form consists of a dropdown (<SELECT>) that lists all the existing employee IDs. Once you select a specific ID, details of that employee are displayed in the two textboxes. You then can update them. To add an employee, you simply need to enter the first name and last name and click the Insert button. Similarly, you can delete an employee by selecting employee ID in the dropdown and clicking the Delete button. A success or failure message is displayed once the INSERT, UPDATE, or DELETE operation is over. The following is the complete markup of the web form: <table> <tr> <td colspan="2"> <asp:Label ID="Label4" runat="server" Font-Size="X-Large" Text="Employee Management"> </asp:Label></td> </tr> <tr> <td style="width: 100px"> <asp:Label ID="Label1" runat="server" Text="Employee ID :"></asp:Label></td> <td style="width: 100px"> <select id="Select1" > </select> </td> </tr> <tr> <td style="width: 100px"> <asp:Label ID="Label2" runat="server" Text="First Name :"></asp:Label></td> <td style="width: 100px"> <input id="Text1" type="text" /></td> </tr> <tr> <td style="width: 100px"> <asp:Label ID="Label3" runat="server" Text="Last Name :"></asp:Label></td> <td style="width: 100px"> <input id="Text2" type="text" /></td> </tr> <tr> <td align="center" colspan="2"> <input id="Button3" type="button" value="Insert" /> <input id="Button4" type="button" value="Update" /> <input id="Button5" type="button" value="Delete" /> </td> </tr>

166 <tr> <td align="center" colspan="2"> <span id="lblMsg" style="font-weight: bold; color: red;"></span> </td> </tr> </table> Notice one important thing: You did not use ASP.NET server controls such as DropDownList, TextBox, and Button. Instead, you used traditional HTML controls such as <SELECT> and <INPUT>. This is because you want to call your web service from client-side JavaScript and not from serverside code. Also, notice the <SPAN> tag at the bottom. It will be used for displaying success or failure messages. Next, add a <script> section inside the <head> HTML element. Add a function called CallWebMethod() as shown below: function CallWebMethod(methodType) { switch(methodType) { case "select": EmployeeService.GetEmployees(FillEmployeeList,ErrorHandler, TimeOutHandler); break; case "selectone": var select=document.getElementById("Select1"); var empid=select.options[select.selectedIndex].value; EmployeeService.GetEmployee(empid,DisplayEmployeeDetails, ErrorHandler,TimeOutHandler); break; case "insert": var text1=document.getElementById("Text1"); var text2=document.getElementById("Text2"); EmployeeService.Insert(text1.value,text2.value, InsertEmployee,ErrorHandler, TimeOutHandler); break; case "update": var select=document.getElementById("Select1"); var empid=select.options[select.selectedIndex].value; var text1=document.getElementById("Text1"); var text2=document.getElementById("Text2"); var emp=new Employee(); emp.EmployeeID=empid; emp.FirstName=text1.value; emp.LastName=text2.value; EmployeeService.Update(empid,text1.value,text2.value, UpdateEmployee,ErrorHandler, TimeOutHandler); break; case "delete": var select=document.getElementById("Select1"); var empid=select.options[select.selectedIndex].value; EmployeeService.Delete(empid,DeleteEmployee,ErrorHandler, TimeOutHandler); break; } }

167 The CallWebMethod() function is a central function that makes calls to the web service. The function accepts a string parameter indicating the method to be called and then calls that method. It contains a switch statement that checks off the method to be called. Each case block calls one web method. Notice how the web method has been called. The ASP.NET AJAX framework automatically creates a JavaScript proxy class for the web service. The proxy class has the same name as the web service. So, the EmployeeService in the above code is not the actual web service class but a JavaScript proxy class. The proxy contains all the web methods of the original web service. In addition to the original web method parameters, each method can have three extra parameters. The first extra parameter is a JavaScript function that should be called when the web method call is successfully completed. Remember that any AJAX communication between client and server is asynchronous. Hence, this function is necessary to capture the return value of the web method. The second parameter is a JavaScript function that is called in the event of error. Finally, the third extra parameter is a JavaScript function that is called if a timeout occurs during the web method call. In the first case ("select"), you simply call the GetEmployees() method. In the second case ("selectone"), you call the GetEmployee() method. The employee ID is picked up from the dropdown using traditional JavaScript code. Similarly, the third, fourth, and fifth case blocks call the Insert(), Update(), and Delete() methods, respectively. The above code uses five JavaScript functions that are called when the respective web method calls are successful: FillEmployeeList(), DisplayEmployeeDetails(), InsertEmployee(), UpdateEmployee(), and DeleteEmployee(). Each of these functions accepts a single parameter that represents the return value of the corresponding web method: function FillEmployeeList(result) { var select=document.getElementById("Select1"); for(var i=0;i<result.length;i++) { var option=new Option(result[i].EmployeeID, result[i].EmployeeID); select.options.add(option); } } function DisplayEmployeeDetails(result) { var text1=document.getElementById("Text1"); var text2=document.getElementById("Text2"); text1.innerText=result.FirstName; text2.innerText=result.LastName; var lblMsg=document.getElementById("lblMsg"); lblMsg.innerText=""; } function InsertEmployee(result) { if(result>0) { var lblMsg=document.getElementById("lblMsg"); lblMsg.innerText="Employee added successfully!"; } else { var lblMsg=document.getElementById("lblMsg"); lblMsg.innerText="Error occurred while adding new employee!"; } } function UpdateEmployee(result) { if(result>0) {

168 var lblMsg=document.getElementById("lblMsg"); lblMsg.innerText="Employee updated successfully!"; } else { var lblMsg=document.getElementById("lblMsg"); lblMsg.innerText="Error occurred while updating the employee!"; } } function DeleteEmployee(result) { if(result>0) { var lblMsg=document.getElementById("lblMsg"); lblMsg.innerText="Employee deleted successfully!"; } else { var lblMsg=document.getElementById("lblMsg"); lblMsg.innerText="Error occurred while deleting employee!"; } } The FillEmployeeList() function receives an array of Employee objects as a parameter. Recollect that your GetEmployees() web method returns an array of Employee objects. It then iterates through the array. With each iteration, a new OPTION element is created and added to the dropdown (in other words, <SELECT>). The DisplayEmployeeDetails() function receives an Employee object containing details about an employee. It simply displays those details in the two textboxes. The InsertEmployee(), UpdateEmployee(), and DeleteEmployee() functions receive an integer indicating the number of records affected by the INSERT, UPDATE, and DELETE operations, respectively. A result greater than zero indicates success and they display a success message in the <SPAN> tag. Otherwise, they display an error message. When your page is displayed for the first time, you need to populate the dropdown list with the existing employee IDs. This is done by calling the CallWebMethod() method in a special function named pageLoad(): function pageLoad() { CallWebMethod("select"); } The pageLoad() function gets called automatically when the web page is loaded in the client browser. Finally, the error handler and timeout handler functions look like this: function ErrorHandler(result) { var msg=result.get_exceptionType() + "\r\n"; msg += result.get_message() + "\r\n"; msg += result.get_stackTrace(); alert(msg); } function TimeOutHandler(result) { alert("Timeout :" + result); } The TimeOutHandler() function is called whenever a web method times out. It simply shows an alert to the user. The ErrorHandler() function is called whenever there is any error. The result parameter received by this method provides three methods: get_exceptionType(), get_message(), and get_stackTrace(). These three methods return the type of exception, detailed error message, and stack trace, respectively. The ErrorHandler() function simply displays an alert to the end user.

169 Testing the Web Page Now that you have developed the web service and the client application, it's time to test them. Run the web form and try inserting, updating, or deleting employees. Figure 5 shows the web form after updating an employee.

Figure 5: Web Form After Updating an Employee To test the error handler function, deliberately initialize the connection string to an empty string and run the web page again. This time, you should see an alert as shown in Figure 6.

Click here for a larger image. Figure 6: ConnectionString Property Alert Calling External Web Services In this example, the EmployeeService was part of your web site. Sometimes, you may need to call web services that are not hosted by your domain at all. ASP.NET AJAX internally relies on the XML HTTP object, which for security reasons cannot communicate outside the originating web site. That means the above technique won't work for external web services. Unfortunately, ASP.NET AJAX does not have a direct solution to this issue (at least in the RC version). However, Microsoft has released a "bridge" technology that is still in CTP stages. You can use the bridge to call a wrapper class residing in your web site, which in turn calls the actual web service. In the current RC version, you can create a wrapper web service in your web site, which in turn calls the original web service. From the

170 client application, you then can call your wrapper web service and achieve the communication. The following is an outline of the necessary steps: 1. Add a web reference to the external web service in your web site. 2. Create a new web service in your web site. 3. In the newly created web service, provide wrapper web methods that call the external web methods via web reference. 4. Call this newly added web service from the client application as described in this article. Infrastructure for Calling ASP.NET Web Services ASP.NET AJAX provides a complete infrastructure for calling ASP.NET web services from client-side JavaScript. You can easily integrate server data with the user-responsive web pages using AJAX. All you need to do is mark your web service with the [ScriptService] attribute. The ASP.NET AJAX framework generates a JavaScript proxy for your web service. The proxy then is used to call the web methods.

Generics
What Are Generics? When we look at the term "generic", unrelated to the programming world, it simply means something that is not tied to any sort of brand name. For example, if we purchase some generic dish soap, soap that has no brand name on it, we know that we are buying dish soap and expect it to help us clean our dishes, but we really don't know what exact brand (if any) will be inside the bottle itself. We can treat it as dish soap even though we don't really have any idea of its exact contents. Think of Generics in this manner. We can refer to a class, where we don't force it to be related to any specific Type, but we can still perform work with it in a Type-Safe manner. A perfect example of where we would need Generics is in dealing with collections of items (integers, strings, Orders etc.). We can create a generic collection than can handle any Type in a generic and Type-Safe manner. For example, we can have a single array class that we can use to store a list of Users or even a list of Products, and when we actually use it, we will be able to access the items in the collection directly as a list of Users or Products, and not as objects (with boxing/unboxing, casting). "Generic" Collections as we see them today Currently, if we want to handle our Types in a generic manner, we always need to cast them to a System.Object, and we lose any benefit of a rich-typed development experience. For example, I'm sure most of us are familiar with the System.Collection.ArrayList class in Framework v1 and v1.1. If you have used it at all, you will notice a few things about it: 1. It requires that you store everything in it as an object public virtual int Add(object value); public virtual object this[int index] {get; set;} 2. You need to cast up in order to get your object back to its actual Type 3. Performance is really lacking, especially when iterating with foreach() 4. It performs no type safety for you (no exceptions are thrown even if you add objects of different types to a single list) System.Collections.ArrayList list = new System.Collections.ArrayList(); list.Add("a string"); list.Add(45); //no exception thrown

171 list.Add(new System.Collections.ArrayList()); //no exception foreach(string s in list) { //exception will be thrown! System.Console.WriteLine(s); } For some situations we may feel the need to implement IEnumerable and IEnumerator in order to create a custom collection of our given Type, that is, a Type-safe collection for our needs. If you had a User object, you could create another class (which implements IEnumerable and IEnumerator, or just IList) that allows you to only add and access User objects, even though most implementations will still store them as objects. It is a lot of work implementing these two interfaces, and you can imagine the work needed to create this additional collection class every time you wanted a Type-safe collection. The third and final way of creating a collection of items is by simply creating an array of that type, for example: string[] mystrings = new string[]{"a", "b", "c"}; This will guarantee Type safety, but is not very reusable nor very friendly to work with. Adding a new item to this collection would mean needing to create a temporary array and copy the elements into this new temporary array, resizing the old array, copying the data back into it, and then adding the new item to the end of that collection. In my humble opinion, this is too much work that tends to be very error prone. What we need is a way to create a Type-safe collection of items that we can use for any type imaginable. This template, or generic class, should be able to perform all of the existing duties that we need for our collections: adding, removing, inserting, etc. The ideal situation is for us to be able to create this generic collection functionality once and never have to do it again. You must also consider other types of collections that we commonly work with and their functionality, such as a Stack (First in, Last out) or a Queue (First In, First out), etc. It would be nice to be able to create different types of generic collections that behave in standard ways. In the next I will show you how to create your first Generic Type. Creating Our First Generic Type In this section we will create a very simple generic class and demonstrate how it can be used as a container for a variety of other Types. Below is a simple example of what a generic class could look like: public class Col<T> { T t; public T Val{get{return t;}set{t=value;}} } There are a few things to notice. The class name "Col<T>" is our first indication that this Type is generic, specifically the brackets containing the Type placeholder. This Type placeholder "T" is used to show that if we need to refer to the actual Type that is going to be used when we write this class, we will represent it as "T". Notice on the next line the variable declaration "T t;" creates a member variable with the type of T, or the generic Type which we will specify later during construction of the class (it will actually get inserted by the Common Language Runtime (CLR) automatically for us). The final item in the class is the public property. Again, notice that we are using the Type placeholder "T" to represent that generic type for the type of that property. Also notice that we can freely use the private variable "t" within the class.

172 In order to use this class to hold any Type, we simply need to create a new instance of our new Type, providing the name of the Type within the "<>" brackets and then use that class in a Type-safe manner. For example: public class ColMain { public static void Main() { //create a string version of our generic class Col<string> mystring = new Col<string>(); //set the value mystring.Val = "hello"; //output that value System.Console.WriteLine(mystring.Val); //output the value's type System.Console.WriteLine(mystring.Val.GetType()); //create another instance of our generic class, using a different type Col<int> myint = new Col<int>(); //load the value myint.Val = 5; //output the value System.Console.WriteLine(myint.Val); //output the value's type System.Console.WriteLine(myint.Val.GetType()); } } When we compile the two classes above and then run them, we will see the following output: hello System.String 5 System.Int32 Even though we used the same class to actually hold our string and int, it keeps their original type intact. That is, we are not going to and from a System.Object type just to hold them. Generic Collections The .NET team has provided us with a number of generic collections to work with in the the latest version of the .NET Framework. List, Stack, and Queue are all going to be implemented for us. Let's see an example on how to use the provided Generic List class. For this example we want to be able to hold a collection of a Type that we create, which we used to represent a User in our system. Here is the definition for that class: namespace Rob { public class User { protected string name; protected int age; public string Name{get{return name;}set{name=value;}} public int Age{get{return age;}set{age=value;}} } } Now that we have our User defined, let's create an instance of the .NET Framework Generic version of a simple List:

173 System.Collections.Generic.List<Rob.User> users = new System.Collections.Generic.List<Rob.User>(); Notice the new "Generic" namespace within the System.Collections namespace. This is where we will find all the new classes for our use. The "List" class within that namespace is synonymous with the typical System.Collections.ArrayList class, which I'm sure most of us are very familiar with by now. Please note that although they are similar there are several important differences. So now that we have a Type-safe list of our User class, let's see how we can use this class. What we will do is simply loop 5 times and create a new User and add that User to our users collection above:

for(int x=0;x<5;x++) { Rob.User user = new Rob.User(); user.Name="Rob" + x; user.Age=x; users.Add(user); } This should seem straight forward to you by now. In the next step we will iterate over that same collection and output each item to the console: foreach(Rob.User user in users) { System.Console.WriteLine( System.String.Format("{0}:{1}", user.Name, user.Age) ); } This is slightly different that what we are used to. What you should notice right off the bat is that we do not have to worry about the Type being "Rob.User". This is because our generic collection is working in a Type-safe manner; it will always be what we expect. Another way to output the same list would be to use a simple for() loop instead, and in this case we do not have to cast the object out of the collection in order to use it properly: for(int x=0;x<users.Count;x++) { System.Console.WriteLine( System.String.Format("{0}:{1}", users[x].Name, users[x].Age) ); } No more silly casting or boxing involved. Here is the complete listing of the source plus the output of the result of executing the console application: User.cs namespace Rob { public class User { protected string name; protected int age; public string Name{get{return name;}set{name=value;}} public int Age{get{return age;}set{age=value;}} } } Main.cs public class M { public static void Main(string[] args) {

174 System.Collections.Generic.List<Rob.User> users = new System.Collections.Generic.List<Rob.User>(); for(int x=0;x<5;x++) { Rob.User user = new Rob.User(); user.Name="Rob" + x; user.Age=x; users.Add(user); } foreach(Rob.User user in users) { System.Console.WriteLine(System.String.Format("{0}:{1}", user.Name, user.Age)); } System.Console.WriteLine("press enter"); System.Console.ReadLine(); for(int x=0;x<users.Count;x++) { System.Console.WriteLine(System.String.Format("{0}:{1}", users[x].Name, users[x].Age)); } } } Output Rob0:0 Rob1:1 Rob2:2 Rob3:3 Rob4:4 press enter Rob0:0 Rob1:1 Rob2:2 Rob3:3 Rob4:4

More on Generics More Generics features in the latest release of the .NET Framework include Generic Methods and Constraints. A generic method is very straight forward. Consider this example:

public static T[] CreateArray<T>(int size) { return new T[size]; } This static method simply creates a method of the given Type "T" and of the given "size" and returns it to the caller. An example of calling this method would be: string[] myString = CreateArray<string>(5); This will new up an instance of our string array, with an initial size of 5. You should take time to investigate the new version of the framework. You will be surprised at all the little helpful features like this. Lastly, we should take a quick look at constraints. A constraint is setup to limit the Types which the Generic can accept. Let's say for example we had a generic type:

175 public class Dictionary<K, V> where K : IComparable {} Notice the "where" clause on this class definition. It is forcing the K Type to be of Type IComparable. If K does NOT implement IComparable, you will get a Compiler error. Another type of constraint is a constructor constraint: public class Something<V> where V: new() {} In this example V must have at least the default constructor available, if not the Compiler will throw an error. Conclusion This article has introduced you to the new and exciting world of Generics. I hope you learned something with this article, and are beginning to prepare yourself for the latest release of the .NET Framework.

----------------------------------------------------------------------------------------------

When and How to Use Dispose and Finalize in C# Although the .NET framework frees managed memory and resources transparently, it's not as adept at freeing unmanaged resources; you have to help it out by implementing the Dispose and Finalize patterns in your code. hen the .NET framework instantiates an object, it allocates memory for that object on the managed heap. The object remains on the heap until it's no longer referenced by any active code, at which point the memory it's using is "garbage," ready for memory deallocation by the .NET Garbage Collector (GC). Before the GC deallocates the memory, the framework calls the object's Finalize() method, but developers are responsible for calling the Dispose() method. The two methods are not equivalent. Even though both methods perform object cleanup, there are distinct differences between them. To design efficient .NET applications, it's essential that you have a proper understanding of both how the .NET framework cleans up objects and when and how to use the Finalize and Dispose methods. This article discusses both methods and provides code examples and tips on how and when to use them. System Requirements To implement the techniques discussed in the article, the minimum requirements are:   .NET framework version 1.1 or higher Operating System: Windows XP/2000 or higher

An Insight into the Dispose and Finalize Methods The .NET garbage collector manages the memory of managed objects (native .NET objects) but it does not manage, nor is it directly able to clean up unmanaged resources. Managed resources are those that are cleaned up implicitly by the garbage collector. You do not have to write code to release such resources explicitly. In contrast, you must clean up unmanaged resources (file handles, database collections, etc.) explicitly in your code. There are situations when you might need to allocate memory for unmanaged resources from managed code. As an example, suppose you have to open a database connection from within a class. The database connection instance is an unmanaged resource encapsulated within this class and should be released as soon as you are done with it. In such cases, you'll need to free the memory occupied by the

176 unmanaged resources explicitly, because the GC doesn't free them implicitly. Briefly, the GC works as shown below:    It searches for managed objects that are referenced in managed code. It then attempts to finalize those objects that are not referenced in the code. Lastly, it frees the unreferenced objects and reclaims the memory occupied by them.

The GC maintains lists of managed objects arranged in "generations." A generation is a measure of the relative lifetime of the objects in memory. The generation number indicates to which generation an object belongs. Recently created objects are stored in lower generations compared to those created earlier in the application's life cycle. Longer-lived objects get promoted to higher generations. Because applications tend to create many short-lived objects compared to relatively few long-lived objects, the GC runs much more frequently to clean up objects in the lower generations than in the higher ones. Keep this information about the .NET garbage collector in mind as you read the remainder of the article. I'll walk you through the Finalize method first, and then discuss the Dispose method.

Finalizers—Implicit Resource Cleanup Finalization is the process by which the GC allows objects to clean up any unmanaged resources that they're holding, before the actually destroying the instance. An implementation of the Finalize method is called a "finalizer." Finalizers should free only external resources held directly by the object itself. The GC attempts to call finalizers on objects when it finds that the object is no longer in use—when no other object is holding a valid reference to it. In other words, finalizers are methods that the GC calls on "seemingly dead objects" before it reclaims memory for that object. The GC calls an object's finalizer automatically, typically once per instance—although that's not always the case (see the Author's Note below for more information). The framework calls finalizers on a secondary thread handled by the GC. You should never rely on finalizers to clean up managed resources. A class that has no finalizer implemented but is holding references to unmanaged objects can cause memory leaks, because the resources might become orphaned if a class instance is destroyed before releasing the unmanaged objects. Author's Note: Although the GC usually calls an object's finalizer only once, you can change that by writing code to re-register the instance using the ReRegisterForFinalize method and not subsequently calling the GC.SuppressFinalize method on the instance. You must implement finalizers very carefully; it's a complex operation that can carry considerable performance overhead. The performance overhead stems from the fact that finalizable objects are enlisted and removed from the finalization queues, which are internal data structures containing pointers to instances of classes that implement a finalizer method. When pointers to these objects are placed in this data structure, the object is said to be enlisted in the Finalization Queue. Note that the GC periodically scans this data structure to locate these pointers. When it finds one, it removes the pointer from the queue and appends the pointer at the end of another queue called the freachable queue. Further, finalizable objects tend to get promoted to the higher generations and hence stay in memory for a relatively longer period of time. Note that the GC works more frequently in the lower generations than in the higher ones. The time and order of execution of finalizers cannot be predicted or pre-determined. This is why you'll hear that the nature of finalization is "non-deterministic." Further, due to the non-deterministic nature of finalization the framework does not and cannot guarantee that the Finalize method will ever be called on an instance. Hence, you cannot rely upon this method to free up any un-managed resources (such as a file handle or a database connection instance) that would otherwise not be garbage collected by the

177 GC. Note that you cannot call or override the Finalize method. It is generated implicitly if you have a destructor for the class. This is shown in the following piece of C# code:— class Test { // Some Code ~Test { //Necessary cleanup code } } In the preceding code, the ~Test syntax declares an explicit destructor in C#, letting you write explicit cleanup code that will run during the finalize operation. The framework implicitly translates the explicit destructor to create a call to Finalize: protected override void Finalize() { try { //Necessary cleanup code } finally { base.Finalize(); } } Note that the generated code above calls the base.Finalize method. You should note the following points should when implementing finalizers:  Finalizers should always be protected, not public or private so that the method cannot be called from the application's code directly and at the same time, it can make a call to the base.Finalize method Finalizers should release unmanaged resources only. The framework does not guarantee that a finalizer will execute at all on any given instance. Never allocate memory in finalizers or call virtual methods from finalizers. Avoid synchronization and raising unhandled exceptions in the finalizers. The execution order of finalizers is non-deterministic—in other words, you can't rely on another object still being available within your finalizer. Do not define finalizers on value types. Don't create empty destructors. In other words, you should never explicitly define a destructor unless your class needs to clean up unmanaged resources—and if you do define one, it should do some work. If, later, you no longer need to clean up unmanaged resources in the destructor, remove it altogether.

      

To close out this section, Finalize() is a non-explicit way to clean up resources. Because you can't control when (or even if) the GC calls Finalize, you should treat destructors only as a fallback mechanism for releasing unmanaged resources. Instead, the approved way to release unmanaged resources is to make your class inherit from the IDisposable interface and implement the Dispose() method.

The Dispose Method—Explicit Resource Cleanup

178 Unlike Finalize, developers should call Dispose explicitly to free unmanaged resources. In fact, you should call the Dispose method explicitly on any object that implements it to free any unmanaged resources for which the object may be holding references. The Dispose method generally doesn't free managed memory—typically, it's used for early reclamation of only the unmanaged resources to which a class is holding references. In other words, this method can release the unmanaged resources in a deterministic fashion. However, Dispose doesn't remove the object itself from memory. The object will be removed when the garbage collector finds it convenient. It should be noted that the developer implementing the Dispose method must call GC.SuppressFinalize(this) to prevent the finalizer from running. Note that an object should implement IDisposable and the Dispose method not only when it must explicitly free unmanaged resources, but also when it instantiates managed classes which in turn use such unmanaged resources. Implementing IDisposable is a good choice when you want your code, not the GC, to decide when to clean up resources. Further, note that the Dispose method should not be called concurrently from two or more different threads as it might lead to unpredictable results if other threads still have access to unmanaged resources belonging to the instance. The IDisposable interface consists of only one Dispose method with no arguments. public interface IDisposable { void Dispose(); } The following code illustrates how to implement the Dispose method on a class that implements the IDisposable interface: class Test : IDisposable { private bool isDisposed = false; ~Test() { Dispose(false); } protected void Dispose(bool disposing) { if (disposing) { // Code to dispose the managed resources of the class } // Code to dispose the un-managed resources of the class isDisposed = true; } public void Dispose() { Dispose(true); GC.SuppressFinalize(this); } } In the preceding code, when the Boolean variable disposed equals true, the object can free both managed and unmanaged resources; but if the value equals false, the call has been initiated from within the finalizer (~Test) in which case the object should release only the unmanaged resources that the instance has reference to.

179 The Dispose/Finalize Pattern Microsoft recommends that you implement both Dispose and Finalize when working with unmanaged resources. The correct sequence then would be for a developer to call Dispose. The Finalize implementation would run and the resources would still be released when the object is garbage collected even if a developer neglected to call the Dispose method explicitly. Francesco Balena writes in his blog "the Dispose/Finalize pattern should be used only when your type invokes unmanaged code that allocates unmanaged resources (including unmanaged memory) and returns a handle that you must use eventually to release the resource. Both dispose and finalize must chain up to their parent objects by calling their parent's respective methods after they have disposed or finalized their own members". Simply put, cleanup the unmanaged resources in the Finalize method and the managed ones in the Dispose method, when the Dispose/Finalize pattern has been used in your code. As an example, consider a class that holds a database connection instance. A developer can call Dispose on an instance of this class to release the memory resource held by the database connection object. After it is freed, the Finalize method can be called when the class instance needs to be released from the memory. According to MSDN, "Finalize provides a backup to prevent resources from permanently leaking if the programmer fails to call Dispose". Please refer to the following link: Suppressing Finalization After the Dispose method has been called on an object, you should suppress calls to the Finalize method by invoking the GC.SuppressFinalize method as a measure of performance optimization. Note that you should never change the order of calls in the finalization context (first Dispose(true) and then GC.SupressFinalize) to ensure that the latter gets called if and only if the Dispose method has completed its operation successfully. The following code illustrates how to implement both the Dispose and Finalize pattern for a class. public class Base: IDisposable { private bool isDisposed = false; public void Dispose() { Dispose(true); GC.SuppressFinalize(this); } protected virtual void Dispose(bool disposing) { if(!isDisposed) { if (disposing) { // Code to dispose the managed resources // held by the class } } // Code to dispose the unmanaged resources // held by the class isDisposed = true; base.Dispose(disposing); } ~Base() { Dispose (false); } } You should not reimplement IDisposable for a class that inherits from a base class in which IDispose has already been implemented. The following code snippet may help you understand this concept:

180 public class Base: IDisposable { private bool isDisposed = false; public void Dispose() { Dispose(true); GC.SuppressFinalize(this); } protected virtual void Dispose(bool disposing) { if(!isDisposed) { if (disposing) { // Code to dispose managed resources // held by the class } } // Code to dispose unmanaged resources // held by the class isDisposed = true; base.Dispose(disposing); } ~Base() { Dispose (false); } } public class Derived: Base { protected override void Dispose(bool disposing) { if (disposing) { // Code to cleanup managed resources held by the class. } // Code to cleanup unmanaged resources held by the class. base.Dispose(disposing); } // Note that the derived class does not // re-implement IDisposable } In the preceding code, what if the Dispose method were to throw an exception? In that case, the Finalize method would exit prematurely, and the memory would never be reclaimed. Hence, in such situations, it is advisable to wrap the Dispose method in a try-catch block. This will prevent finalization exceptions from orphaning the object. Note the following points when implementing disposable types:      Implement IDisposable on every type that has a finalizer Ensure that an object is made unusable after making a call to the Dispose method. In other words, avoid using an object after the Dispose method has been called on it. Call Dispose on all IDisposable types once you are done with them Allow Dispose to be called multiple times without raising errors. Suppress later calls to the finalizer from within the Dispose method using the GC.SuppressFinalize method

181   Avoid creating disposable value types Avoid throwing exceptions from within Dispose methods

In a managed environment, the GC takes care of freeing unused objects. In contrast, in unmanaged languages such as C, developers had to release unused objects explicitly that were created dynamically in the heap. However, a proper understanding of both the Dispose and Finalize methods goes a long way toward designing efficient applications.

Delegates and Events
1) What does mean Type safe in .Net and is delegate type safe, if yes then explain it? a. Type-safe code accesses only the memory locations it is authorized to access. b. Type-safe code cannot directly read values from another object's private fields or code areas. c. It accesses types only in well-defined, allowable ways, thereby preventing overrun security breaches. d. Type safety helps isolate objects from each other and therefore helps protect them from malicious corruption. e. It also provides assurance that security restrictions on code can be reliably enforced. A delegate is essentially a type-safe pointer to a method. The .NET runtime enforces a check against the method signature and only the method with the proper signature will execute. 2) Delegate always needs to declare as public or can we declare as private or protected? Delegate can declare as private and protected but scope of that delegate will inside the class in case of private.

3) Can we declare delegate as static, if no then explain it?

Can somebody answer this question with example?

4) What is "call back". When and how to use it scenarios? Callback is method which can use by delegate. Let’s try to understand delegate with Example : Consider a multi-tier application for loan processing that has a business logic component containing loan-processing rules. During processing, a decision tree determines the applicant's overall credit rating score. This calculation is complex, often involving a number of variables and taking varying lengths of time to complete. Suppose that while the application is processing an applicant, a loan officer learns something that requires another applicant's credit score to be updated. Rather than have the UI wait until the processing finishes, which prevents the officer from updating the other applicant's score, the application makes a request and will notify the UI when processing is complete. In order for this notification to occur, the business logic component needs the address of the method to call in the UI when processing is complete. This is the essence of a callback method. It is a pointer to a method in the client to call when processing is complete

Sign up to vote on this title
UsefulNot useful