Top Banner
Module: .Net 3.5
618
Welcome message from author
This document is posted to help you gain knowledge. Please leave a comment to let me know what you think about it! Share it to your friends and learn new things together.
Transcript

Module: .Net 3.5

CHAPTER 1: GETTING

ACQUAINTED WITH

.NET FRAMEWORK 3.0

Introduction Developers must realize there is more to programming than simple code. This two-part series addresses the important issue of application architecture using an N-tier approach. The first part is a brief introduction to the theoretical aspects, including the understanding of certain basic concepts. The second part shows how to create a flexible and reusable application for distribution to any number of client interfaces. Technologies used consist of .NET Beta 2 (including C#, .NET Web Services, symmetric encryption), Visual Basic 6, the Microsoft SOAP Toolkit V2 SP2, and basic interoperability [ability to communicate with each other] between Web Services in .NET and the Microsoft SOAP Toolkit. None of these discussions (unless otherwise indicated) specify anything to do with the physical location of each layer. They often are on separate physical machines, but can be isolated to a single machine. For starters, this article uses the terms "tier" and "layer" synonymously. In the term "N-tier," "N" implies any number, like 2tier, or 4-tier, basically any number of distinct tiers used in your architecture. Description of 1-Tier and 2-Tier Web Applications Client-Server environments. Perhaps the most influential ClientServer environment is the Internet and its global users. With the increasing use of web applications, an examination of the best architecture to support web applications is timely. The architectural component of this discussion will focus on the underlying structures and schematics that best build web applications. Specifically, we will be discussing tier architecture, which is the breaking down of an application into logical chunks that are called Tiers. Tiers can exist on the same computer and be connected virtually or logically or on different machines. The simplest examples of tier architecture are enumerated as 1-Tier, 2-Tier, and 3-Tier. 1-Tier Architecture is the simplest, single tier on single user, and is the equivalent of running an application on a personal computer. All the required component to run the application are located within it. User interface, business logic, and data storage are all located on the same machine. They are the easiest to design, but the least scalable. Because they are not part of a network, they are useless for designing web applications. 2-Tier Architectures supply a basic network between a client and a server. For example, the basic web model is a 2-Tier Architecture. A web browser makes a request from a web server, which then processes the request and returns the desired response, in this case, web pages. This approach improves scalability and divides the user interface from the data layers. However, it does not divide application layers so they can be utilized separately. This makes them difficult to update and not specialized.

The entire application must be updated because layers arent separated. 3-Tier Architecture is most commonly used to build web applications. In this model, the browser acts like a client, middleware or an application server contains the business logic, and database servers handle data functions. This approach separates business logic from display and data. But, it does not specialize functional layers. Its fine for prototypical or very simple web applications, but it doesnt measure up to the complexity demanded of web applications. The application server is still too broad, with too many functions grouped together. This reduces flexibility and scalability. N-Tier Architectures provide finer granularity, which provides more modules to choose from as the application is separated into smaller functions. "Tier" can be defined as "one of two or more rows, levels, or ranks arranged one above another". So from this, we get an adapted definition of the understanding of what N-tier means and how it relates to our application architecture: "Any number of levels arranged above another, each serving distinct and separate tasks." To gain a better understanding of what is meant, let's take a look at a typical N-tier model (see Figure 1.1).

Figure 1.1 A Typical N-Tier Model

The Data Tier Since this has been deemed the Age of Information, and since all information needs to be stored, the Data Tier described above is usually an essential part. Developing a system without a data tier is possible, but I think for most applications the data tier should exist. So what is this layer? Basically, it is your Database Management System (DBMS) -- SQL Server, Access, Oracle, MySql, plain text (or binary) files, whatever you like. This tier can be as complex and comprehensive as high-end products such as SQL Server and Oracle, which do include the things like query optimization, indexing, etc., all the way down to the simplistic plain text files (and the engine to read and search these files). Some more well-known formats of structured, plain text files include CSV, XML, etc.. Notice how this layer is only intended to deal with the storage and retrieval of information. It doesn't care about how you plan on manipulating or delivering this data. This also should include your stored procedures. Do not place business logic in here, no matter how tempting. The Presentation Logic Tier Let's jump to the Presentation Logic Layer in Figure 1.1. You probably are familiar with this layer; it consists of our standard ASP documents, Windows forms, etc. This is the layer that provides an interface for the end user into your application. That is, it works with the results/output of the Business Tier to handle the transformation into something usable and readable by the end user. It has come to my attention that most applications have been developed for the Web with this layer talking directly to the Data Access Layer and not even implementing the Business Tier. Sometimes the Business Layer is not kept separated from the other two layers. Some applications are not consistent with the separation of these layers, and it's important that they are kept separate. A lot of developers will simply throw some SQL in their ASP (using ADO), connect to their database, get the recordset, and loop in their ASP to output the result. This is usually a very bad idea. I will discuss why later. The Proxy Tier and the Distributed Logic There's also that little, obscure Proxy Tier. "Proxy" by definition is "a person [object] authorized to act for another". This "object," in our context, is referring to any sort of code that is performing the actions for something else (the client). The key part of this definition is "act for another." The Proxy Layer is "acting" on behalf of the Distributed Logic layer (or end-user's requests) to provide access to the next tier, the Business Tier. Why would anyone ever need this? This facilitates our need for distributed computing. Basically it comes down to you choosing some standard method of communication between these two entities. That is, "how can the client talk to the remote server?" This is where we find the need for the Simple Object Access Protocol (SOAP). SOAP is a very simple method for doing this. Without too many details, SOAP could be considered a standard (protocol) for

accessing remote objects. It provides a way in which to have two machines "talking" or "communicating" with each other The Client Interface In this section of Figure 1.1 we notice that the end-user presentation (Windows forms, etc.) is connected directly to the Business Tier. A good example of this would be your applications over the Local Area Network (LAN). This is your typical, nondistributed, client-server application. Also notice that it extends over and on top of the Distributed Logic layer. This is intended to demonstrate how you could use SOAP (or some other type of distributed-computing messaging protocol) on the client to communicate with the server and have those requests be transformed into something readable and usable for the end user. The Business Tier This is basically where the brains of your application reside; it contains things like the business rules, data manipulation, etc. For example, if you're creating a search engine and you want to rate/weight each matching item based on some custom criteria (say a quality rating and number of times a keyword was found in the result), place this logic at this layer. This layer does NOT know anything about HTML, nor does it output it. It does NOT care about ADO or SQL, and it shouldn't have any code to access the database or the like. Those tasks are assigned to each corresponding layer above or below it. We must gain a very basic understanding of Object-Oriented Programming (OOP) at this time and make sure you understand the important benefits of OOP. To clarify, let's look at another example, such as a shopping cart application. Think in terms of basic objects. We create an object to represent each product for sale. This Product object has the standard property getters and setters: getSize, getColor, setSize, setColor, etc. It is a super simple implementation of any generic product. Internally, it ONLY knows how to return information (getters) and understands how it can validate the data you pump into it (ONLY for its limited use). It is self-contained (encapsulation). The key here is to encapsulate all the logic related to the generic product within this object. If you ask it to "getPrice," it will return the price of the single item it represents. Also if you instruct it to "validate" or "save," it has the brains to be able to handle this, return any errors, etc. We can plug this Product object into another object, a "Cart" object. This cart can contain and handle many Product objects. It also has getters and setters, but obviously on a more global scale. You can do something like "for each product in myCart", and enumerate (loop through) each product within. (For more information on enumeration, Now, when you call "getPrice" for the Cart object, it knows that it must enumerate each product that it has, add up the price for each, and return that single total. When we fire the "saveCart" method, it

will loop for each "product" and call its "saveProduct" method, which will then hit the Data Access Tier objects and methods to persist itself over to the Data Tier. We could also take our simple Product object, and plug it into our "Sale" object. This Sale object contains all of the items that are available for a particular sale. And the Sale object can be used for things like representing all the items on sale at a given outlet or the like. I'm sure you are beginning to understand the advantage of using an OOP environment. Data Access Tier This layer is where you will write some generic methods to interface with your data. For example, we will write a method for creating and opening a Connection object (internal), and another for creating and using a Command object, along with a stored procedure (with or without a return value), etc. It will also have some specific methods, such as "saveProduct," so that when the Product object calls it with the appropriate data, it can persist it to the Data Tier. This Data Layer, obviously, contains no data business rules or data manipulation/transformation logic. It is merely a reusable interface to the database. Applying N-Tier Architecture and Example Lets now apply N-Tier Architecture to our shopping cart example. In this example, we will demonstrate how sales tax is calculated and displayed. The presentation tier calls the business logic tier to perform computations on the data in the shopping cart to calculate total price. The business logic tier communicates with a database (data tier) to extract the sales tax amount based on the total price. he business logic tier is able to communicate with the data tier through the integration tier. Through encapsulation, the integration tier is able to conceal the complexities of communication. It also retrieves the right tax rate and returns it to the business logic tier. The business logic tier completes its calculations. The presentation tier formats the response through HTML and forwards it to the client or web browser, where it is displayed to the user. Benefits of N-Tier Architecture There are many business benefits to N-Tier Architecture. For example, a small business can begin running all tiers on a single machine. As traffic and business increases, each tier can be expanded and moved to its own machine and then clustered. This is just one example of how N-Tier Architecture improves scalability and supports costefficient application building. N-Tier model also make applications more readable and reusable. It reduces the amount of spaghetti code. Custom tag libraries and EJBs are easier to port to readable applications in well-maintained templates. Reusability multiplies developer productivity and improves

application maintainability. It is an important feature in web applications. N-Tier Architectures make application more robust because there is no single point of failure. Tiers function with relative independence. For example, if a business changes database vendors, they just have to replace the data tier and adjust the integration tier to any changes that affect it. The business logic tier and the presentation tier remain unchanged. Likewise, if the presentation layer changes, this will not affect the integration or data layer. In 3-Tier Architecture all the layers exist in one and affect each other. A developer would have to pick through the entire application code to implement any changes. Again, well-designed modules allow for applications or pieces of applications to be customized and used across modules or even projects. Reusability is particularly important in web applications. As demonstrated N-Tier Architecture offers innovations in the standard Client-Server technology that spawned the Internet itself. It is but one of many web application frameworks. These are used to develop dynamic web sites, web applications or web services. They provide database access libraries, templates, and, as previously stated code re-use. Most web application frameworks follow the Model View Controller (MVC) which separate the user interface, the business rules and the data model. They provide authentication and authorization to provide security. This allows the web server to restrict user access based on pre-determined criteria. Web application frameworks also provide a unified API (Application programming Interface). This allows web application to work with various databases without requiring any code change. These frameworks also maintain a web template system. Finally, N-Tier Architecture helps developers build web applications because it allows developers to apply their specific skill to that part of the program that best suits their skill set. Graphic artists can focus on the presentation tier, while administrators can focus on the database tier An Overview of .NET Technology The Microsoft .NET Framework is a software technology that is available with several Microsoft Windows operating systems. It includes a large library of pre-coded solutions to common programming problems and a virtual machine that manages the execution of programs written specifically for the framework. The .NET Framework is a key Microsoft offering and is intended to be used by most new applications created for the Windows platform. The pre-coded solutions that form the framework's Base Class Library cover a large range of programming needs in a number of areas, including user interface, data access, database connectivity, cryptography, web application development, numeric algorithms, and

network communications. The class library is used by programmers, who combine it with their own code to produce applications. Programs written for the .NET Framework execute in a software environment that manages the program's runtime requirements. Also part of the .NET Framework, this runtime environment is known as the Common Language Runtime (CLR). The CLR provides the appearance of an application virtual machine so that programmers need not consider the capabilities of the specific CPU that will execute the program. The CLR also provides other important services such as security, memory management, and exception handling. The class library and the CLR together compose the .NET Framework. Version 3.0 of the .NET Framework is included with Windows Server 2008 and Windows Vista. The current version of the framework can also be installed on Windows XP and the Windows Server 2003 family of operating systems A reduced "Compact" version of the .NET Framework is also available on Windows Mobile platforms, including smartphones. Interoperability Because interaction between new and older applications is commonly required, the .NET Framework provides means to access functionality that is implemented in programs that execute outside the .NET environment. Access to COM components is provided in the System.Runtime.InteropServices and System.EnterpriseServices namespaces of the framework; access to other functionality is provided using the P/Invoke feature. Common Runtime Engine The Common Language Runtime (CLR) is the virtual machine component of the .NET framework. All .NET programs execute under the supervision of the CLR, guaranteeing certain properties and behaviors in the areas of memory management, security, and exception handling. Base Class Library The Base Class Library (BCL), part of the Framework Class Library (FCL), is a library of functionality available to all languages using the .NET Framework. The BCL provides classes which encapsulate a number of common functions, including file reading and writing, graphic rendering, database interaction and XML document manipulation. Simplified Deployment Installation of computer software must be carefully managed to ensure that it does not interfere with previously installed software,

and that it conforms to security requirements. The .NET framework includes design features and tools that help address these requirements. Security The design is meant to address some of the vulnerabilities, such as buffer overflows, that have been exploited by malicious software. Additionally, .NET provides a common security model for all applications. Portability The design of the .NET Framework allows it to theoretically be platform agnostic, and thus cross-platform compatible. That is, a program written to use the framework should run without change on any type of system for which the framework is implemented. Microsoft's commercial implementations of the framework cover Windows, Windows CE, and the Xbox 360. In addition, Microsoft submits the specifications for the Common Language Infrastructure (which includes the core class libraries, Common Type System, and the Common Intermediate Language), the C# language, and the C+ +/CLI language to both ECMA and the ISO, making them available as open standards. This makes it possible for third parties to create compatible implementations of the framework and its languages on other platforms. Architecture Visual overview of the Common Language Infrastructure (CLI) Common Language Infrastructure The core aspects of the .NET framework lie within the Common Language Infrastructure, or CLI. The purpose of the CLI is to provide a language-neutral platform for application development and execution, including functions for exception handling, garbage collection, security, and interoperability. Microsoft's implementation of the CLI is called the Common Language Runtime or CLR. Assemblies The intermediate CIL code is housed in .NET assemblies. As mandated by specification, assemblies are stored in the Portable Executable (PE) format, common on the Windows platform for all DLL and EXE files. The assembly consists of one or more files, one of which must contain the manifest, which has the metadata for the assembly. The complete name of an assembly (not to be confused with the filename on disk) contains its simple text name, version number, culture, and public key token. The public key token is a unique hash generated when the assembly is compiled, thus two assemblies with the same public key token are guaranteed to be identical from the point of view of the framework. A private key can also be specified known only to the creator of the

assembly and can be used for strong naming and to guarantee that the assembly is from the same author when a new version of the assembly is compiled Metadata All CLI is self-describing through .NET metadata. The CLR checks the metadata to ensure that the correct method is called. Metadata is usually generated by language compilers but developers can create their own metadata through custom attributes. Metadata contains information about the assembly, and is also used to implement the reflective programming capabilities of .NET Framework. Security .NET has its own security mechanism with two general features: Code Access Security (CAS), and validation and verification. Code Access Security is based on evidence that is associated with a specific assembly. Typically the evidence is the source of the assembly (whether it is installed on the local machine or has been downloaded from the intranet or Internet). Code Access Security uses evidence to determine the permissions granted to the code. Other code can demand that calling code is granted a specified permission. The demand causes the CLR to perform a call stack walk: every assembly of each method in the call stack is checked for the required permission; if any assembly is not granted the permission a security exception is thrown. When an assembly is loaded the CLR performs various tests. Two such tests are validation and verification. During validation the CLR checks that the assembly contains valid metadata and CIL, and whether the internal tables are correct. Verification is not so exact. The verification mechanism checks to see if the code does anything that is 'unsafe'. The algorithm used is quite conservative; hence occasionally code that is 'safe' does not pass. Unsafe code will only be executed if the assembly has the 'skip verification' permission, which generally means code that is installed on the local machine. .NET Framework uses appdomains as a mechanism for isolating code running in a process. Appdomains can be created and code loaded into or unloaded from them independent of other appdomains. This helps increase the fault tolerance of the application, as faults or crashes in one appdomain do not affect rest of the application. Appdomains can also be configured independently with different security privileges. This can help increase the security of the application by isolating potentially unsafe code. The developer, however, has to split the application into subdomains; it is not done by the CLR. Class library Namespaces in the BCL System System. CodeDom

System. Collections System. Diagnostics System. Globalization System. IO System. Resources System. Text System. Text.RegularExpressions Microsoft .NET Framework includes a set of standard class libraries. The class library is organized in a hierarchy of namespaces. Most of the built in APIs are part of either System.* or Microsoft.* namespaces. It encapsulates a large number of common functions, such as file reading and writing, graphic rendering, database interaction, and XML document manipulation, among others. The .NET class libraries are available to all .NET languages. The .NET Framework class library is divided into two parts: the Base Class Library and the Framework Class Library. The Base Class Library (BCL) includes a small subset of the entire class library and is the core set of classes that serve as the basic API of the Common Language Runtime The classes in mscorlib.dll and some of the classes in System.dll and System.core.dll are considered to be a part of the BCL. The BCL classes are available in both .NET Framework as well as its alternative implementations including .NET Compact Framework, Microsoft Silverlight and Mono. The Framework Class Library (FCL) is a superset of the BCL classes and refers to the entire class library that ships with .NET Framework. It includes an expanded set of libraries, including WinForms, ADO.NET, ASP.NET, Language Integrated Query, Windows Presentation Foundation, Windows Communication Foundation among others. The FCL is much larger in scope than standard libraries for languages like C++, and comparable in scope to the standard libraries of Java. Memory management The .NET Framework CLR frees the developer from the burden of managing memory (allocating and freeing up when done); instead it does the memory management itself. To this end, the memory allocated to instantiations of .NET types (objects) is done contiguously[ from the managed heap, a pool of memory managed by the CLR. As long as there exists a reference to an object, which might be either a direct reference to an object or via a graph of objects, the object is considered to be in use by the CLR. When there is no reference to an object, and it cannot be reached or used, it becomes garbage. However, it still holds on to the memory allocated to it. .NET Framework includes a garbage collector which runs periodically, on a

separate thread from the application's thread, that enumerates all the unusable objects and reclaims the memory allocated to them. The .NET Garbage Collector (GC) is a non-deterministic, compacting, mark-and-sweep garbage collector. The GC runs only when a certain amount of memory has been used or there is enough pressure for memory on the system. Since it is not guaranteed when the conditions to reclaim memory are reached, the GC runs are nondeterministic. Each .NET application has a set of roots, which are pointers to objects on the managed heap (managed objects). These include references to static objects and objects defined as local variables or method parameters currently in scope, as well as objects referred to by CPU registers. When the GC runs, it pauses the application, and for each object referred to in the root, it recursively enumerates all the objects reachable from the root objects and marks them as reachable. It uses .NET metadata and reflection to discover the objects encapsulated by an object, and then recursively walk them. It then enumerates all the objects on the heap (which were initially allocated contiguously) using reflection. All objects not marked as reachable are garbage. This is the mark phase. Since the memory held by garbage is not of any consequence, it is considered free space. However, this leaves chunks of free space between objects which were initially contiguous. The objects are then compacted together, by using memcpy to copy them over to the free space to make them contiguous again. Any reference to an object invalidated by moving the object is updated to reflect the new location by the GC. The application is resumed after the garbage collection is over. The GC used by .NET Framework is actually generational. Objects are assigned a generation; newly created objects belong to Generation 0. The objects that survive a garbage collection are tagged as Generation 1, and the Generation 1 objects that survive another collection are Generation 2 objects. The .NET Framework uses up to Generation 2 objects Higher generation objects are garbage collected less frequently than lower generation objects. This helps increase the efficiency of garbage collection, as older objects tend to have a larger lifetime than newer objects. Thus, by removing older (and thus more likely to survive a collection) objects from the scope of a collection run, fewer objects need to be checked and compacted. Standardization and licensing While Microsoft and their partners hold patents for the CLI and C#, ECMA and ISO require that all patents essential to implementation be made available under "reasonable and non-discriminatory terms." In addition to meeting these terms, the companies have agreed to make the patents available royalty-free. However, this does not apply for the part of the .NET Framework which is not covered by the ECMA/ISO standard, which includes Windows Forms, ADO.NET, and ASP.NET. Patents that Microsoft holds

in these areas may deter non-Microsoft implementations of the full framework. On 3 October 2007, Microsoft announced that much of the source code for the .NET Framework will be made available with the final release of Visual Studio 2008 towards the end of 2007 under the shared source Microsoft Reference License. The source code for other libraries including Windows Communication Foundation (WCF), Windows Workflow Foundation (WF) and Language Integrated Query (LINQ) will be added in future releases. Being released under the Microsoft Reference License means this source code is made available for debugging purpose only, primarily to support integrated debugging of the BCL in Visual Studio. Versions Microsoft started development on the .NET Framework in the late 1990s originally under the name of Next Generation Windows Services (NGWS). By late 2000 the first beta versions of .NET 1.0 were released. The .NET Framework stack. Versio Version Number Release Date n 1.0 1.1 2.0 3.0 3.5 1.0.3705.0 1.1.4322.573 2.0.50727.42 3.0.4506.30 3.5.21022.8 2002-01-05 2003-04-01 2005-11-07 2006-11-06 2007-11-09

.NET Framework 1.0 The old .NET Framework logo This is the first release of the .NET Framework, released on 13 February 2002 and available for Windows 98, NT 4.0, 2000, and XP. Mainstream support by Microsoft for this version ended 10 July 2007, and extended support ends 14 July 2009. .NET Framework 1.1 This is the first major .NET Framework upgrade. It is available on its own as a redistributable package or in a software development kit, and was published on 3 April 2003. It is also part of the second release of Microsoft Visual Studio .NET (released as Visual Studio .NET 2003). This is the first version of the .NET Framework to be included as part of the Windows operating system, shipping with Windows Server 2003. Mainstream support for .NET Framework 1.1 ended on

14 October 2008, and extended support ends on 8 October 2013. Since .NET 1.1 is a component of Windows Server 2003, extended support for .NET 1.1 on Server 2003 will run out with that of the OS currently 30 June 2013. .NET Framework 2.0 Released with Visual Studio 2005, Microsoft SQL Server 2005, and BizTalk 2006. The 2.0 Redistributable Package can be downloaded for free from Microsoft, and was published on 2006-01-22. The 2.0 Software Development Kit (SDK) can be downloaded for free from Microsoft. It is included as part of Visual Studio 2005 and Microsoft SQL Server 2005. Version 2.0 is the last version with support for Windows 2000, Windows 98 and Windows Me. It shipped with Windows Server 2003 R2 (not installed by default). Changes in 2.0 on comparison with 1.1 Numerous API changes. A new hosting API for native applications wishing to host an instance of the .NET runtime. The new API gives a fine grain control on the behavior of the runtime with regards to multithreading, memory allocation, assembly loading and more). It was initially developed to efficiently host the runtime in Microsoft SQL Server, which implements its own scheduler and memory manager. Full 64-bit support for both the x64 and the IA64 hardware platforms. Language support for generics built directly into the .NET CLR. Many additional and improved ASP.NET web controls. New data controls with declarative data binding. New personalization features for ASP.NET, such as support for themes, skins and webparts. .NET Micro Framework - a version of the .NET Framework related to the Smart Personal Objects Technology initiative. .NET Framework 3.0 .NET Framework 3.0, formerly called WinFX, includes a new set of managed code APIs that are an integral part of Windows Vista and Windows Server 2008 operating systems. It is also available for Windows XP SP2 and Windows Server 2003 as a download. There are no major architectural changes included with this release; .NET Framework 3.0 uses the Common Language Runtime of .NET Framework 2.0. Unlike the previous major .NET releases there was no .NET Compact Framework release made as a counterpart of this version. .NET Framework 3.0 consists of four major new components:

Windows Presentation Foundation (WPF), formerly codenamed Avalon; a new user interface subsystem and API based on XML and vector graphics, which uses 3D computer graphics hardware and Direct3D technologies. Windows Communication Foundation (WCF), formerly codenamed Indigo; a service-oriented messaging system which allows programs to interoperate locally or remotely similar to web services. Windows Workflow Foundation (WF) allows for building of task automation and integrated transactions using workflows. Windows CardSpace, formerly code-named InfoCard; a software component which securely stores a person's digital identities and provides a unified interface for choosing the identity for a particular transaction, such as logging in to a website. .NET Framework 3.5 Version 3.5 of the .NET Framework was released on 19 November 2007, but it is not included with Windows Server 2008. As with .NET Framework 3.0, version 3.5 uses the CLR of version 2.0. In addition, it installs .NET Framework 2.0 SP1 and .NET Framework 3.0 SP1, which adds some methods and properties to the BCL classes in version 2.0 which are required for version 3.5 features such as Language Integrated Query (LINQ). These changes do not affect applications written for version 2.0, however. As with previous versions, a new .NET Compact Framework 3.5 was released in tandem with this update in order to provide support for additional features on Windows Mobile and Windows Embedded CE devices. Changes since version 3.0 New language features in C# 3.0 and VB.NET 9.0 compiler Adds support for expression trees and lambda methods Extension methods Expression trees to represent high-level source code at runtime. Anonymous types with static type inference Language Integrated Query (LINQ) along with its various providers LINQ to Objects LINQ to XML LINQ to SQL Paging support for ADO.NET ADO.NET synchronization API to synchronize local caches and server side datastores Asynchronous network I/O API Peer-to-peer networking stack, including a managed PNRP resolver

Managed wrappers for Windows Management Instrumentation and Active Directory Enhanced WCF and WF runtimes, which let WCF work with POX and JSON data, and also expose WF workflows as WCF services. WCF services can be made stateful using the WF persistence model. Support for HTTP pipelining and syndication feeds.[ ASP.NET AJAX is included

New System.CodeDom namespace Overview of C# 3.0C# 3.0 (C# Orcas) introduces several language extensions that build on C# 2.0 to support the creation and use of higher order, functional style class libraries. The extensions enable construction of compositional APIs that have equal expressive power of query languages in domains such as relational databases and XML. The extensions include: Implicitly typed local variables, which permit the type of local variables to be inferred from the expressions used to initialize them. Extension methods, which make it possible to extend existing types and constructed types with additional methods. Lambda expressions, an evolution of anonymous methods that provides improved type inference and conversions to both delegate types and expression trees. Object initializers, which ease construction and initialization of objects. Anonymous types, which are tuple types automatically inferred and created from object initializers. Implicitly typed arrays, a form of array creation and initialization that infers the element type of the array from an array initializer. Query expressions, which provide a language integrated syntax for queries that is similar to relational and hierarchical query languages such as SQL and XQuery. Expression trees, which permit lambda expressions to be represented as data (expression trees) instead of as code (delegates). Implicitly typed local variables In an implicitly typed local variable declaration, the type of the local variable being declared is inferred from the expression used to initialize the variable. When a local variable declaration specifies var as the type and no type named var is in scope, the declaration is an implicitly typed local variable declaration. For example:

var i = 5; var s = "Hello"; var d = 1.0; var numbers = new int[] {1, 2, 3}; var orders = new Dictionary(); The implicitly typed local variable declarations above are precisely equivalent to the following explicitly typed declarations: int i = 5; string s = "Hello"; double d = 1.0; int[] numbers = new int[] {1, 2, 3}; Dictionary orders = new Dictionary(); A local variable declarator in an implicitly typed local variable declaration is subject to the following restrictions: The declarator must include an initializer. The initializer must be an expression. The initializer cannot be an object or collection initializer () by itself, but it can be a new expression that includes an object or collection initializer. The compile-time type of the initializer expression cannot be the null type. If the local variable declaration includes multiple declarators, the initializers must all have the same compile-time type. The following are examples of incorrect implicitly typed local variable declarations: var x; // Error, no initializer to infer type from var y = {1, 2, 3}; // Error, collection initializer not permitted var z = null; // Error, null type not permitted For reasons of backward compatibility, when a local variable declaration specifies var as the type and a type named var is in scope, the declaration refers to that type; however, a warning is generated to call attention to the ambiguity. Since a type named var violates the established convention of starting type names with an upper case letter, this situation is unlikely to occur. The for-initializer of a for statement (8.8.3) and the resourceacquisition of a using statement (8.13) can be an implicitly typed local variable declaration. Likewise, the iteration variable of a foreach statement (8.8.4) may be declared as an implicitly typed local variable, in which case the type of the iteration variable is inferred to be the element type of the collection being enumerated. In the example int[] numbers = { 1, 3, 5, 7, 9 }; foreach (var n in numbers) Console.WriteLine(n); the type of n is inferred to be int, the element type of numbers. Extension methods

Extension methods are static methods that can be invoked using instance method syntax. In effect, extension methods make it possible to extend existing types and constructed types with additional methods. Declaring extension methods Extension methods are declared by specifying the keyword this as a modifier on the first parameter of the methods. Extension methods can only be declared in static classes. The following is an example of a static class that declares two extension methods namespace Acme.Utilities { public static class Extensions { public static int ToInt32(this string s) { return Int32.Parse(s); } public static T[] Slice(this T[] source, int index, int count) { if (index < 0 || count < 0 || source.Length index < count) throw new ArgumentException(); T[] result = new T[count]; Array.Copy(source, index, result, 0, count); return result; } } } Extension methods have all the capabilities of regular static methods. In addition, once imported, extension methods can be invoked using instance method syntax. Importing extension methods Extension methods are imported through using-namespace-directives (9.3.2). In addition to importing the types contained in a namespace, a using-namespace-directive imports all extension methods in all static classes in the namespace. In effect, imported extension methods appear as additional methods on the types that are given by their first parameter and have lower precedence than regular instance methods. For example, when the Acme.Utilities namespace from the example above is imported with the usingnamespace-directive using Acme.Utilities; it becomes possible to invoke the extension methods in the static class Extensions using instance method syntax:

string s = "1234"; int i = s.ToInt32(); // Same as Extensions.ToInt32(s) int[] digits = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; int[] a = digits.Slice(4, 3); // Same as Extensions.Slice(digits, 4, 3) Extension method invocations The detailed rules for extension method invocation are described in the following. In a method invocation (7.5.5.1) of one of the forms expr . identifier ( ) expr . identifier ( args ) expr . identifier < typeargs > ( ) expr . identifier < typeargs > ( args ) if the normal processing of the invocation finds no applicable instance methods (specifically, if the set of candidate methods for the invocation is empty), an attempt is made to process the construct as an extension method invocation. The method invocation is first rewritten to one of the following, respectively: identifier ( expr ) identifier ( expr , args ) identifier < typeargs > ( expr ) identifier < typeargs > ( expr , args ) The rewritten form is then processed as a static method invocation, except for the way in which identifier is resolved: Starting with the closest enclosing namespace declaration, continuing with each enclosing namespace declaration, and ending with the containing compilation unit, successive attempts are made to process the rewritten method invocation with a method group consisting of all accessible extension methods with the name given by identifier imported by the namespace declarations using-namespace-directives. The first method group that yields a non-empty set of candidate methods is the one chosen for the rewritten method invocation. If all attempts yield empty sets of candidate methods, a compile-time error occurs. The preceeding rules mean that instance methods take precedence over extension methods, and extension methods imported in inner namespace declarations take precedence over extension methods imported in outer namespace declarations. For example: using N1; namespace N1 { public static class E { public static void F(this object obj, int i) { }

{}

public static void F(this object obj, string s)

} } class A { } class B { public void F(int i) { } } class C { public void F(object obj) { } } class X { static void Test(A a, B b, C c) { a.F(1); // E.F(object, int) a.F("hello"); // E.F(object, string) b.F(1); // B.F(int) b.F("hello"); // E.F(object, string) c.F(1); // C.F(object) c.F("hello"); // C.F(object) } } In the example, Bs method takes precedence over the first extension method, and Cs method takes precedence over both extension methods Lambda expressions C# 2.0 introduces anonymous methods, which allow code blocks to be written in-line where delegate values are expected. While anonymous methods provide much of the expressive power of functional programming languages, the anonymous method syntax is rather verbose and imperative in nature. Lambda expressions provide a more concise, functional syntax for writing anonymous methods. A lambda expression is written as a parameter list, followed by the => token, followed by an expression or a statement block. expression: assignment non-assignment-expression non-assignment-expression: conditional-expression lambda-expression query-expression

lambda-expression: ( lambda-parameter-listopt ) => lambdaexpression-body implicitly-typed-lambda-parameter => lambdaexpression-body lambda-parameter-list: explicitly-typed-lambda-parameter-list implicitly-typed-lambda-parameter-list explicitly-typed-lambda-parameter-list explicitly-typed-lambda-parameter explicitly-typed-lambda-parameter-list , explicitlytyped-lambda-parameter explicitly-typed-lambda-parameter: parameter-modifieropt type identifier implicitly-typed-lambda-parameter-list implicitly-typed-lambda-parameter implicitly-typed-lambda-parameter-list , implicitlytyped-lambda-parameter implicitly-typed-lambda-parameter: identifier lambda-expression-body: expression block The parameters of a lambda expression can be explicitly or implicitly typed. In an explicitly typed parameter list, the type of each parameter is explicitly stated. In an implicitly typed parameter list, the types of the parameters are inferred from the context in which the lambda expression occursspecifically, when the lambda expression is converted to a compatible delegate type, that delegate type provides the parameter types . In a lambda expression with a single, implicitly typed parameter, the parentheses may be omitted from the parameter list. In other words, a lambda expression of the form ( param ) => expr can be abbreviated to param => expr Some examples of lambda expressions follow below: x => x + 1 x => { return x + 1; } body (int x) => x + 1 typed, expression body (int x) => { return x + 1; } (x, y) => x * y () => Console.WriteLine() // Implicitly typed, statement // Explicitly // Explicitly typed, statement body // Multiple parameters // No parameters

In general, the specification of anonymous methods, of the C# 2.0 Specification, also applies to lambda expressions. Lambda expressions are a functional superset of anonymous methods, providing the following additional functionality: Lambda expressions permit parameter types to be omitted and inferred whereas anonymous methods require parameter types to be explicitly stated. The body of a lambda expression can be an expression or a statement block whereas the body of an anonymous method can only be a statement block. Lambda expressions passed as arguments participate in type argument inference and in method overload resolution. Lambda expressions with an expression body can be converted to expression trees Lambda expression conversions Similar to an anonymous-method-expression, a lambda-expression is classified as a value with special conversion rules. The value does not have a type but can be implicitly converted to a compatible delegate type. Specifically, a delegate type D is compatible with a lambdaexpression L provided: D and L have the same number of parameters. If L has an explicitly typed parameter list, each parameter in D has the same type and modifiers as the corresponding parameter in L. If L has an implicitly typed parameter list, D has no ref or out parameters. If D has a void return type and the body of L is an expression, when each parameter of L is given the type of the corresponding parameter in D, the body of L is a valid expression that would be permitted as a statement-expression (8.6). If D has a void return type and the body of L is a statement block, when each parameter of L is given the type of the corresponding parameter in D, the body of L is a valid statement block in which no return statement specifies an expression. If D has a non-void return type and the body of L is an expression, when each parameter of L is given the type of the corresponding parameter in D, the body of L is a valid expression that is implicitly convertible to the return type of D. If D has a non-void return type and the body of L is a statement block, when each parameter of L is given the type of the corresponding parameter in D, the body of L is a valid statement block with a non-reachable end point in which each return statement specifies an expression that is implicitly convertible to the return type of D. The examples that follow use a generic delegate type Func which represents a function taking an argument of type A and returning a value of type R: delegate R Func(A arg);

In the assignments Func f1 = x => x + 1; // Ok Func f2 = x => x + 1; // Ok Func f3 = x => x + 1; // Error the parameter and return types of each lambda expression are determined from the type of the variable to which the lambda expression is assigned. The first assignment successfully converts the lambda expression to the delegate type Func because, when x is given type int, x + 1 is a valid expression that is implicitly convertible to type int. Likewise, the second assignment successfully converts the lambda expression to the delegate type Func because the result of x + 1 (of type int) is implicitly convertible to type double. However, the third assignment is a compile-time error because, when x is given type double, the result of x + 1 (of type double) is not implicitly convertible to type int Type inference When a generic method is called without specifying type arguments, a type inference process attempts to infer type arguments for the call. Lambda expressions passed as arguments to the generic method participate in this type inference process. type inference first occurs independently for each argument. In this initial phase, nothing is inferred from arguments that are lambda expressions. However, following the initial phase, additional inferences are made from lambda expressions using an iterative process. Specifically, inferences are made as long as one or more arguments exist for which all of the following are true: The argument is a lambda expression, in the following called L, from which no inferences have yet been made. The corresponding parameters type, in the following called P, is a delegate type with a return type that involves one or more method type parameters. P and L have the same number of parameters, and each parameter in P has the same modifiers as the corresponding parameter in L, or no modifiers if L has an implicitly typed parameter list. Ps parameter types involve no method type parameters or involve only method type parameters for which a consistent set of inferences have already been made. If L has an explicitly typed parameter list, when inferred types are substituted for method type parameters in P, each parameter in P has the same type as the the corresponding parameter in L. If L has an implicitly typed parameter list, when inferred types are substituted for method type parameters in P and the resulting parameter types are given to the parameters of L, the body of L is a valid expression or statement block. A return type can be inferred for L, as described below.

For each such argument, inferences are made from that argument by relating the return type of P with the inferred return type of L and the new inferences are added to the accumulated set of inferences. This process is repeated until no further inferences can be made. For purposes of type inference and overload resolution, the inferred return type of a lambda expression L is determined as follows: If the body of L is an expression, the type of that expression is the inferred return type of L. If the body of L is a statement block, if the set formed by the types of the expressions in the blocks return statements contains exactly one type to which each type in the set is implicitly convertible, and if that type is not the null type, then that type is the inferred return type of L. Otherwise, a return type cannot be inferred for L. As an example of type inference involving lambda expressions, consider the Select extension method declared in the System.Query.Sequence class: namespace System.Query { public static class Sequence { public static IEnumerable Select( this IEnumerable source, Func selector) { foreach (T element in source) yield return selector(element); } } } Assuming the System.Query namespace was imported with a using clause, and given a class Customer with a Name property of type string, the Select method can be used to select the names of a list of customers: List customers = GetCustomerList(); IEnumerable names = customers.Select(c => c.Name); The extension method invocation () of Select is processed by rewriting the invocation to a static method invocation: IEnumerable names = Sequence.Select(customers, c => c.Name); Since type arguments were not explicitly specified, type inference is used to infer the type arguments. First, the customers argument is related to the source parameter, inferring T to be Customer. Then, using the lambda expression type inference process described above, c is given type Customer, and the expression c.Name is related to the return type of the selector parameter, inferring S to be string. Thus, the invocation is equivalent to

Sequence.Select(customers, (Customer c) => c.Name) and the result is of type IEnumerable. The following example demonstrates how lambda expression type inference allows type information to flow between arguments in a generic method invocation. Given the method static Z F(X value, Func f1, Func f2) { return f2(f1(value)); } type inference for the invocation double seconds = F("1:15:30", s => TimeSpan.Parse(s), t => t.TotalSeconds); proceeds as follows: First, the argument "1:15:30" is related to the value parameter, inferring X to be string. Then, the parameter of the first lambda expression, s, is given the inferred type string, and the expression TimeSpan.Parse(s) is related to the return type of f1, inferring Y to be System.TimeSpan. Finally, the parameter of the second lambda expression, t, is given the inferred type System.TimeSpan, and the expression t.TotalSeconds is related to the return type of f2, inferring Z to be double. Thus, the result of the invocation is of type double. Overload resolution Lambda expressions in an argument list affect overload resolution in certain situations. The following rule augments 7.4.2.3: Given a lambda expression L for which an inferred return type () exists, an implicit conversion of L to a delegate type D1 is a better conversion than an implicit conversion of L to a delegate type D2 if D1 and D2 have identical parameter lists and the implicit conversion from Ls inferred return type to D1s return type is a better conversion than the implicit conversion from Ls inferred return type to D2s return type. If these conditions are not true, neither conversion is better. The following example illustrates the effect of this rule. class ItemList: List { public int Sum(Func selector) { int sum = 0; foreach (T item in this) sum += selector(item); return sum; } public double Sum(Func selector) { double sum = 0; foreach (T item in this) sum += selector(item); return sum; } }

The ItemList class has two Sum methods. Each takes a selector argument, which extracts the value to sum over from a list item. The extracted value can be either an int or a double and the resulting sum is likewise either an int or a double. The Sum methods could for example be used to compute sums from a list of detail lines in an order. class Detail { public int UnitCount; public double UnitPrice; ... } void ComputeSums() { ItemList orderDetails = GetOrderDetails(...); int totalUnits = orderDetails.Sum(d => d.UnitCount); double orderTotal = orderDetails.Sum(d => d.UnitPrice * d.UnitCount); ... } In the first invocation of orderDetails.Sum, both Sum methods are applicable because the lambda expression d => d.UnitCount is compatible with both Func and Func. However, overload resolution picks the first Sum method because the conversion to Func is better than the conversion to Func. In the second invocation of orderDetails.Sum, only the second Sum method is applicable because the lambda expression d => d.UnitPrice * d.UnitCount produces a value of type double. Thus, overload resolution picks the second Sum method for that invocation. Object and collection initializers An object creation expression may include an object or collection initializer which initializes the members of the newly created object or the elements of the newly created collection. object-creation-expression: new type ( argument-listopt ) object-or-collectioninitializeropt new type object-or-collection-initializer object-or-collection-initializer: object-initializer collection-initializer An object creation expression can omit the constructor argument list and enclosing parentheses provided it includes an object or collection initializer. Omitting the constructor argument list and enclosing parentheses is equivalent to specifying an empty argument list.

Execution of an object creation expression that includes an object or collection initializer consists of first invoking the instance constructor and then performing the member or element initializations specified by the object or collection initializer. It is not possible for an object or collection initializer to refer to the object instance being initialized. Object initializers An object initializer specifies values for one or more fields or properties of an object. object-initializer: { member-initializer-listopt } { member-initializer-list , } member-initializer-list: member-initializer member-initializer-list , member-initializer member-initializer: identifier = initializer-value initializer-value: expression object-or-collection-initializer An object initializer consists of a sequence of member initializers, enclosed by { and } tokens and separated by commas. Each member initializer must name an accessible field or property of the object being initialized, followed by an equals sign and an expression or an object or collection initializer. It is an error for an object initializer to include more than one member initializer for the same field or property. A member initializer that specifies an expression after the equals sign is processed in the same way as an assignment (7.13.1) to the field or property. A member initializer that specifes an object initializer after the equals sign is an initialization of an embedded object. Instead of assigning a new value to the field or property, the assignments in the object initializer are treated as assignments to members of the field or property. A property of a value type cannot be initialized using this construct. A member initializer that specifies a collection initializer after the equals sign is an initialization of an embedded collection. Instead of assigning a new collection to the field or property, the elements given in the initializer are added to the collection referenced by the field or property. The field or property must be of a collection type that satisfies the requirements specified in . The following class represents a point with two coordinates: public class Point { int x, y;

public int X { get { return x; } set { x = value; } } public int Y { get { return y; } set { y = value; } } } An instance of Point can be created an initialized as follows: var a = new Point { X = 0, Y = 1 }; which has the same effect as var a = new Point(); a.X = 0; a.Y = 1; The following class represents a rectangle created from two points: public class Rectangle { Point p1, p2; public Point P1 { get { return p1; } set { p1 = value; } } public Point P2 { get { return p2; } set { p2 = value; } } } An instance of Rectangle can be created and initialized as follows: var r = new Rectangle { P1 = new Point { X = 0, Y = 1 }, P2 = new Point { X = 2, Y = 3 } }; which has the same effect as var r = new Rectangle(); var __p1 = new Point(); __p1.X = 0; __p1.Y = 1; r.P1 = __p1; var __p2 = new Point(); __p2.X = 2; __p2.Y = 3; r.P2 = __p2; where __p1 and __p2 are temporary variables that are otherwise invisible and inaccessible. If Rectangles constructor allocates the two embedded Point instances public class Rectangle { Point p1 = new Point(); Point p2 = new Point(); public Point P1 { get { return p1; } } public Point P2 { get { return p2; } } } the following construct can be used to initialize the embedded Point instances instead of assigning new instances:

var r = new Rectangle { P1 = { X = 0, Y = 1 }, P2 = { X = 2, Y = 3 } }; which has the same effect as var r = new Rectangle(); r.P1.X = 0; r.P1.Y = 1; r.P2.X = 2; r.P2.Y = 3; Collection initializers A collection initializer specifies the elements of a collection. collection-initializer: { element-initializer-listopt } { element-initializer-list , } element-initializer-list: element-initializer element-initializer-list , element-initializer element-initializer: non-assignment-expression A collection initializer consists of a sequence of element initializers, enclosed by { and } tokens and separated by commas. Each element initializer specifies an element to be added to the collection object being initialized. To avoid ambiguity with member initializers, element initializers cannot be assignment expressions. The non-assignment-expression production is defined in . The following is an example of an object creation expression that includes a collection initializer: List digits = new List { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; The collection object to which a collection initializer is applied must be of a type that implements System.Collections.Generic.ICollection for exactly one T. Furthermore, an implicit conversion (6.1) must exist from the type of each element initializer to T. A compile-time error occurs if these requirements are not satisfied. A collection initializer invokes the ICollection.Add(T) method for each specified element in order. The following class represents a contact with a name and a list of phone numbers: public class Contact { string name; List phoneNumbers = new List(); public string Name { get { return name; } set { name = value; } }

public List PhoneNumbers { get { return phoneNumbers; } } } A List can be created and initialized as follows: var contacts = new List { new Contact { Name = "Chris Smith", PhoneNumbers = { "206-555-0101", "425-8828080" } }, new Contact { Name = "Bob Harris", PhoneNumbers = { "650-555-0199" } } }; which has the same effect as var contacts = new List(); var __c1 = new Contact(); __c1.Name = "Chris Smith"; __c1.PhoneNumbers.Add("206-555-0101"); __c1.PhoneNumbers.Add("425-882-8080"); contacts.Add(__c1); var __c2 = new Contact(); __c2.Name = "Bob Harris"; __c2.PhoneNumbers.Add("650-555-0199"); contacts.Add(__c2); where __c1 and __c2 are temporary variables that are otherwise invisible and inaccessible. Anonymous types C# 3.0 permits the new operator to be used with an anonymous object initializer to create an object of an anonymous type. primary-no-array-creation-expression: anonymous-object-creation-expression anonymous-object-creation-expression: new anonymous-object-initializer anonymous-object-initializer: { member-declarator-listopt } { member-declarator-list , } member-declarator-list: member-declarator member-declarator-list , member-declarator member-declarator: simple-name member-access identifier = expression

An anonymous object initializer declares an anonymous type and returns an instance of that type. An anonymous type is a nameless class type that inherits directly from object. The members of an anonymous type are a sequence of read/write properties inferred from the object initializer(s) used to create instances of the type. Specifically, an anonymous object initializer of the form new { p1 = e1 , p2 = e2 , pn = en } declares an anonymous type of the form class __Anonymous1 { private T1 f1 ; private T2 f2 ; private Tn fn ; public T1 p1 { get { return f1 ; } set { f1 = value ; } } public T2 p2 { get { return f2 ; } set { f2 = value ; } } public T1 p1 { get { return f1 ; } set { f1 = value ; } } } where each Tx is the type of the corresponding expression ex. It is a compile-time error for an expression in an anonymous object initializer to be of the null type. The name of an anonymous type is automatically generated by the compiler and cannot be referenced in program text. Within the same program, two anonymous object initializers that specify a sequence of properties of the same names and types in the same order will produce instances of the same anonymous type. (This definition includes the order of the properties because it is observable and material in certain circumstances, such as reflection.) In the example var p1 = new { Name = "Lawnmower", Price = 495.00 }; var p2 = new { Name = "Shovel", Price = 26.95 }; p1 = p2; the assignment on the last line is permitted because p1 and p2 are of the same anonymous type. A member declarator can be abbreviated to a simple name (7.5.2) or a member access (7.5.4). This is called a projection initializer and is shorthand for a declaration of and assignment to a property with the same name. Specifically, member declarators of the forms identifier expr . identifier are precisely equivalent to the following, respectively: identifer = identifier identifier = expr . identifier

Thus, in a projection initializer the identifier selects both the value and the field or property to which the value is assigned. Intuitively, a projection initializer projects not just a value, but also the name of the value. Implicitly typed arrays The syntax of array creation expressions (7.5.10.2) is extended to support implicitly typed array creation expressions: array-creation-expression: new [ ] array-initializer In an implicitly typed array creation expression, the type of the array instance is inferred from the elements specified in the array initializer. Specifically, the set formed by the types of the expressions in the array initializer must contain exactly one type to which each type in the set is implicitly convertible, and if that type is not the null type, an array of that type is created. If exactly one type cannot be inferred, or if the inferred type is the null type, a compiletime error occurs. The following are examples of implicitly typed array creation expressions: var a = new[] { 1, 10, 100, 1000 }; // int[] var b = new[] { 1, 1.5, 2, 2.5 }; // double[] var c = new[] { "hello", null, "world }; // string[] var d = new[] { 1, "one", 2, "two" }; // Error The last expression causes a compile-time error because neither int nor string is implicitly convertible to the other. An explicitly typed array creation expression must be used in this case, for example specifying the type to be object[]. Alternatively, one of the elements can be cast to a common base type, which would then become the inferred element type. Implicitly typed array creation expressions can be combined with anonymous object initializers to create anonymously typed data structures. For example: var contacts = new[] { new { Name = "Chris Smith", PhoneNumbers = new[] { "206-555-0101", "425-8828080" } }, new { Name = "Bob Harris", PhoneNumbers = new[] { "650-555-0199" } } }; Query expressions

Query expressions provide a language integrated syntax for queries that is similar to relational and hierarchical query languages such as SQL and XQuery. query-expression: from-clause query-body from-clause: from from-generators from-generators: from-generator from-generators , from-generator from-generator: identifier in expression query-body: from-or-where-clausesopt orderby-clauseopt select-or-groupclause into-clauseopt from-or-where-clauses: from-or-where-clause from-or-where-clauses from-or-where-clause from-or-where-clause: from-clause where-clause where-clause: where boolean-expression orderby-clause: orderby ordering-clauses ordering-clauses: ordering-clause ordering-clauses , ordering-clause ordering-clause: expression ordering-directionopt ordering-direction: ascending descending select-or-group-clause: select-clause group-clause select-clause: select expression group-clause: group expression by expression into-clause: into identifier query-body A query-expression is classified as a non-assignment-expression, the definition of which occurs in .

A query expression begins with a from clause and ends with either a select or group clause. The initial from clause can be followed by zero or more from or where clauses. Each from clause is a generator that introduces an iteration variable ranging over a sequence, and each where clause is a filter that excludes items from the result. The final select or group clause specfies the shape of the result in terms of the iteration variable(s). The select or group clause may be preceded by an orderby clause that specifies an ordering for the result. Finally, an into clause can be used to splice queries by treating the results of one query as a generator in a subsequent query. In a query expression, a from clause with multiple generators is exactly equivalent to multiple consecutive from clauses with a single generator. Query expression translation The C# 3.0 language does not specify the exact execution semantics of query expressions. Rather, C# 3.0 translates query expressions into invocations of methods that adhere to the query expression pattern. Specifically, query expressions are translated into invocations of methods named Where, Select, SelectMany, OrderBy, OrderByDescending, ThenBy, ThenByDescending, and GroupBy that are expected to have particular signatures and result types, as described in . These methods can be instance methods of the object being queried or extension methods that are external to the object, and they implement the actual execution of the query. The translation from query expressions to method invocations is a syntactic mapping that occurs before any type binding or overload resolution has been performed. The translation is guaranteed to be syntactically correct, but it is not guaranteed to produce semantically correct C# code. Following translation of query expressions, the resulting method invocations are processed as regular method invocations, and this may in turn uncover errors, for example if the methods do not exist, if arguments have wrong types, or if the methods are generic and type inference fails. The translation of query expressions is demonstrated through a series of examples in the following. A formal description of the translation rules is provided in a later section. where clauses A where clause in a query expression: from c in customers where c.City == "London" select c translates to an invocation of a Where method with a synthesized lambda expression created by combining the iteration variable identifier and the expression of the where clause: customers. Where(c => c.City == "London")

select clauses The example in the previous section demonstrates how a select clause that selects the innermost iteration variable is erased by the translation to method invocations. A select clause that selects something other than the innermost iteration variable: from c in customers where c.City == "London" select c.Name translates to an invocation of a Select method with a synthesized lambda expression: customers. Where(c => c.City == "London"). Select(c => c.Name) group clauses A group clause: from c in customers group c.Name by c.Country translates to an invocation of a GroupBy method: customers. GroupBy(c => c.Country, c => c.Name) orderby clauses An orderby clause: from c in customers orderby c.Name select new { c.Name, c.Phone } translates to an invocation of an OrderBy method, or an OrderByDescending method if a descending direction was specified: customers. OrderBy(c => c.Name). Select(c => new { c.Name, c.Phone }) Secondary orderings in an orderby clause: from c in customers orderby c.Country, c.Balance descending select new { c.Name, c.Country, c.Balance } translate to invocations of ThenBy and ThenByDescending methods: customers. OrderBy(c => c.Country). ThenByDescending(c => c.Balance). Select(c => new { c.Name, c.Country, c.Balance }) Multiple generators Multiple generators: from c in customers where c.City == "London" from o in c.Orders where o.OrderDate.Year == 2005 select new { c.Name, o.OrderID, o.Total }

translate to invocations of SelectMany for all but the innermost generator: customers. Where(c => c.City == "London"). SelectMany(c => c.Orders. Where(o => o.OrderDate.Year == 2005). Select(o => new { c.Name, o.OrderID, o.Total }) ) When multiple generators are combined with an orderby clause: from c in customers, o in c.Orders where o.OrderDate.Year == 2005 orderby o.Total descending select new { c.Name, o.OrderID, o.Total } an additional Select is injected to collect the ordering expressions and the final result in a sequence of tuples. This is necessary such that OrderBy can operate on the entire sequence. Following OrderBy, the final result is extracted from the tuples: customers. SelectMany(c => c.Orders. Where(o => o.OrderDate.Year == 2005). Select(o => new { k1 = o.Total, v = new { c.Name, o.OrderID, o.Total } }) ). OrderByDescending(x => x.k1). Select(x => x.v) into clauses An into clause: from c in customers group c by c.Country into g select new { Country = g.Key, CustCount = g.Group.Count() } is simply a more convenient notation for a nested query: from g in from c in customers group c by c.Country select new { Country = g.Key, CustCount = g.Group.Count() } the translation of which is: customers. GroupBy(c => c.Country). Select(g => new { Country = g.Key, CustCount = g.Group.Count() })

The query expression pattern The Query Expression Pattern establishes a pattern of methods that types can implement to support query expressions. Because query expressions are translated to method invocations by means of a syntactic mapping, types have considerable flexibility in how they implement the query expression pattern. For example, the methods of the pattern can be implemented as instance methods or as extension methods because the two have the same invocation syntax, and the methods can request delegates or expression trees because lambda expressions are convertible to both. The recommended shape of a generic type C that supports the query expression pattern is shown below. A generic type is used in order to illustrate the proper relationships between parameter and result types, but it is possible to implement the pattern for nongeneric types as well. delegate R Func(A arg); class C { public C Where(Func predicate); public C Select(Func selector); public C SelectMany(Func selector); public O OrderBy(Func keyExpr); public O OrderByDescending(Func keyExpr); public C GroupBy(Func keyExpr); public C GroupBy(Func keyExpr, Func elemExpr); } class O : C { public O ThenBy(Func keySelector); public O ThenByDescending(Func keySelector); } class G { public K Key { get; } public C Group { get; } } The methods above use a generic delegate type Func, but they could equally well have used other delegate or expression tree types with the same relationships in parameter and result types. Notice the recommended relationship between C and O which ensures that the ThenBy and ThenByDescending methods are available only on the result of an OrderBy or OrderByDescending. Also notice the recommended shape of the result of GroupBy, which is a sequence of groupings that each have a Key and Group property.

The Standard Query Operators (described in a separate specification) provide an implementation of the query operator pattern for any type that implements the System.Collections.Generic.IEnumerable interface. Formal translation rules A query expression is processed by repeatedly applying the following translations in order. Each translation is applied until there are no more occurrences of the specified pattern. Note that in the translations that produce invocations of OrderBy and ThenBy, if the corresponding ordering clause specifies a descending direction indicator, an invocation of OrderByDescending or ThenByDescending is produced instead. A query that contains an into clause q1 into x q2 is translated into from x in ( q1 ) q2 A from clause with multiple generators from g1 , g2 , gn is translated into from g1 from g2 from gn A from clause immediately followed by a where clause from x in e where f is translated into from x in ( e ) . Where ( x => f ) A query expression with multiple from clauses, an orderby clause, and a select clause from x1 in e1 from x2 in e2 orderby k1 , k2 select v is translated into ( from x1 in e1 from x2 in e2 select new { k1 = k1 , k2 = k2 , v = v } ) . OrderBy ( x => x . k1 ) . ThenBy ( x => x . k2 ) . Select ( x => x . v ) A query expression with multiple from clauses, an orderby clause, and a group clause from x1 in e1 from x2 in e2 orderby k1 , k2 group v by g is translated into ( from x1 in e1 from x2 in e2 select new { k1 = k1 , k2 = k2 , v = v , g = g } ) . OrderBy ( x => x . k1 ) . ThenBy ( x => x . k2 ) . GroupBy ( x => x . g , x => x . v ) A query expression with multiple from clauses and a select clause from x in e from x1 in e1 select v is translated into ( e ) . SelectMany ( x => from x1 in e1 select v ) A query expression with multiple from clauses and a group clause from x in e from x1 in e1 group v by g is translated into

( e ) . SelectMany ( x => from x1 in e1 group v by g ) A query expression with a single from clause, no orderby clause, and a select clause from x in e select v is translated into ( e ) . Select ( x => v ) except when v is the identifier x, the translation is simply (e) A query expression with a single from clause, no orderby clause, and a group clause from x in e group v by g is translated into ( e ) . GroupBy ( x => g , x => v ) except when v is the identifier x, the translation is ( e ) . GroupBy ( x => g ) A query expression with a single from clause, an orderby clause, and a select clause from x in e orderby k1 , k2 select v is translated into ( e ) . OrderBy ( x => k1 ) . ThenBy ( x => k2 ) . Select ( x => v ) except when v is the identifier x, the translation is simply ( e ) . OrderBy ( x => k1 ) . ThenBy ( x => k2 ) A query expression with a single from clause, an orderby clause, and a group clause from x in e orderby k1 , k2 group v by g is translated into ( e ) . OrderBy ( x => k1 ) . ThenBy ( x => k2 ) . GroupBy ( x => g , x => v ) except when v is the identifier x, the translation is ( e ) . OrderBy ( x => k1 ) . ThenBy ( x => k2 ) . GroupBy ( x => g )

Migration from .NET Framework 2.0 to .NET Framework 3.0 .NET framework 3.0 combines the power of .NET Framework 2.0 with new technologies for building applications that have a visually compelling user experience, seamless communication across technology boundaries, and support for a wide range of business processes. With Windows Vista, Microsoft has made .NET framework an integral part of the operating system itself rather than a layer on top of it, with some additions to .NET framework 2.0 aimed at standardization of different facets of system and application software for greater interoperability between .NET applications and future Microsoft products. These additions include Windows Presentation Foundation (WPF): WPF aims at standardization of user interface definition, rendering and behavior using XAML (Extensible Application Markup Language) so as to achieve a uniform programming model for all types of applications (thin-client, thick-client, mobile-client), all types of operating system platforms, and all types of browsers. This is achieved by means of WPF/E (Windows Presentation Foundation/Everywhere) that allows building plug-ins and extensions to support different types of applications, browsers, and operating systems that do not offer native support for WPF. Windows Communication Foundation (WCF): WCF aims at standardization of local and remote communication between different software systems and components using asynchronous messagedriven architecture similar to web services. It also strives to make remote messaging more secure and reliable. Workflow Foundation (WF): WF aims at standardization in defining, managing and executing different types of workflows like user interface control workflow, document management workflow, business rules workflow, system workflow as well as software emulation of human processes as workflows in .NET applications and products. Windows CardSpace (WCS): WCS aims at standardization of global digital identity management and authentication/ authorization mechanisms for software systems around the world by means of a Identity Metasystem based on WS-* open industry-standard protocols, consolidating existing identity systems to make them interoperable, secure and reliable. Conceptually, a user can use the same digital identity to log in to his home PC, local corporate network, corporate intranet, as well as any website across the globe that requires authentication. In practice, a user can maintain multiple digital identities revealing varying degree of information about him or her, and judiciously use a relevant identity for authentication in different software systems

A Quick Tour of Visual Studio 2008 Windows Vista marked the release of the .NET Framework 3.0. This release included many great new features for the Windows developer. Among them was the initial release of Windows Presentation Foundation (WPF), Windows Communication Foundation (WCF), and Windows Workflow Foundation (WWF). However, Visual Studio remained unchanged. You could use these new features but they were not built in to the IDE. Instead, you had to use extensions to build applications on these .NET Framework elements and Visual Studio 2005. Visual Studio 2008 represents a re-synch of the development tools and the .NET Framework. The .NET Framework evolves from 3.0 (released with Vista) to 3.5, an incremental release that ships with Visual Studio 2008. The IDE now natively supports WPF, WCF, and WWF out of the box. In addition, there are many other new bells and whistles including direct Office application support, CardSpace, LINQ, a large revi-sion to ASP.NET, the CLR addin framework, and more. In addition to Visual Studio, SQL Server will get an update in 2008. Some Welcome Enhancements to the IDE Visual Studio 2008 and the .NET Framework 3.5 introduce hundreds of new features to an already full-featured toolset. This latest version is about increasing developer productivity when writing applications targeted at the new version of the .NET Framework. This includes expanded project types, a reduction in mundane tasks, and everevolving aspects of team-oriented software engineering. This section and those that follow highlight these enhancements that promise to make your work life easier. Of course, we will go over each of these items in greater detail throughout the book; think of the content in this chapter as your executive overview for the hurried developer.

Use a Single Tool for Many Jobs

Many of us work in environments that include applications built on various versions of the .NET Framework. This becomes even more prevalent as more versions are released. For example, you may have an existing application in production built on .NET 2.0. You may be writing a new application on .NET 3.5. However, if your production application requires occasional maintenance, you do not want to have to keep two versions of Visual Studio on your machine. Visual Studio 2008 supports the ability to target a specific version of the .NET Framework for an application. This means you can use a single tool to develop against many applica-tions built on various .NET Framework flavors. Setting the .NET Framework version of an application will appropriately set the toolbox, project types, available references, and even IntelliSense inside the IDE to be in synch with the chosen .NET Framework version. Figure 1.1 shows creating a new application with Visual Studio 2008 and selecting the .NET Framework version (upperright corner). Notice the Add Reference dialog in Figure 1.2. It shows adding a reference to a Windows application that targets .NET Framework 2.0. In this instance, any component that is part of the 3.0 or 3.5 version of the .NET Framework is disabled

FIGURE 1.1 Creating an application that targets a specific version of the .NET Framework.

The IDE Navigator Developers can now navigate open windows in the IDE without touching a mouse. This keeps your fingers on the keyboard and can lead to greater productivity. Visual Studio 2008 provides a couple of options here. The first is a simple Window switching hotkey. Suppose you have a number of code windows open in the IDE. To navigate forward (left to right) through them, you can use the key combination Ctrl+(minus sign). This is for the standard development settings in the IDE; your settings may differ. To go backward (right to left), you use Ctrl+Shift+- (minus sign). This provides faster Window switching without your having to scroll with the mouse or search through your solution. You can get similar results using a new visual aid called the IDE Navigator. This tool is similar to the Alt+Tab feature of Windows that allows for fast application switching. To

access it, you use Ctrl+Tab (and Ctrl+Shift+Tab). You use this key combination to open the dialog and navigate open code Windows and active tool Windows. Figure 1.4 shows the result. Notice that active files are cycled through on the right.

Alternatively, you can access the IDE Navigator directly using Alt+F7. This brings up the tool with the active tool windows list selected. You can jump between the lists using the right- and left-arrow keys. Improved Docking In prior versions, it was often difficult to get your code or tool window to dock correctly in the IDE. In 2008, docking windows is much improved. There are new icons and visualizations that make this process very simple. Figure 1.5 shows an example of docking the Server Explorer window on top of the Toolbox pane. You can see that there are options to move this window to the left of the toolbox, below it, and so on. Selecting each option shows a visual representation of the results before you release your mouse button.

FIGURE 1.5 Standard Dialogs

Improved window docking.

Another welcome change to the IDE is the use of Windows standard dialog boxes for doing such tasks as opening a file, saving something, or printing code. In prior version of Visual Studio, the IDE had its own versions of these common tasks. However, this only made things confusing because most Windows users are accustomed to working using specific tools. As an example, consider Figures 1.6 and 1.7. Figure 1.6 is the Open File dialog in Visual Studio 2005. This dialog was specific to Visual Studio. Figure 1.7 shows the same dialog in Visual Studio 2008. Notice that the dialog is the same dialog you would get in any other Windows-based application. Choose Your Font There is a new setting called Environment Font inside the Options dialog (Tools menu) under the Environment node, Fonts and Colors. This option allows you to set the font for the entire IDE to the selection of your choice. Figure 1.8 shows selecting this option from the list.

Identifying the Architectural Difference between .NET 2.0 and .NET 3.0 As shown in this illustration .NET 2.0 and 3.0 share the same CLR version which means that all your .NET 2.0 applications will work fine in .NET 3.0 as well (unlike .NET 1.1 and .NET 2.0 where the CLR version changed) .NET 3.0 = .NET 2.0 + WCF + WCS + WF + WPF Using .NET 3.0 will greatly enhance productivity, reduces infrastructure plumbing and provides solutions in the areas of providing an identity meta-system, developing enterprise-class services, Work flow and the next generation UI. Please note that with respect to .NET 3.5 all the usual disclaimers apply, the name will probably change and the composition might change as well, the interesting thing to note is that we plan to keep the same CLR version which means that your .NET 2.0 applications will continue to work. Please also note that our AJAX APIs do have the "Go Live" license already, e.g. you can try the Accordian and DragPanel to have a tangible idea of how you can enhance your existing Web Sites or develop new ones.

Windows Communication Foundation (WCF) Introduction to WCF Windows Communication Foundation (WCF) is Microsoft's unified programming model for building

service-oriented applications. It enables developers to build secure, reliable, transacted solutions that interoperate with applications in different platforms. Interoperability is the fundamental characteristic of WCF. The fundamental communication mechanism is based on Web Services specifications such as SOAP, XML, XSD, WSDL and newly established standards including the WS-* protocols. These specifications address several areas, including basic messaging, security, reliability, transactions, and working with a service's metadata. WCF relies on WS-Policy and WS-Metadata Exchange to discover information about the communications partners. Reliable communication is essential for most situations (no duplicates messages), and WS-Reliable Messaging would be used to interact with many of the other applications in this scenario. WS-Security and the related specifications might also be used for establishing a secure channel. The specifications support the main security services such as authentication, integrity and confidentiality. WSAtomic Transaction is very important for managing transactional context involving several transactional resources. The key point is that WCF implements interoperable Web services, complete with cross-platform security, reliability, transactions, and other services. It also is

transport neutral, protocol neutral, and format neutral. For example, services are free to make use of HTTP, TCP, named pipes, and any other transport mechanisms for which there is an implementation. It is possible the WCF-to-WCF communication to be optimized, but all other communication uses standard Web services protocols. What Are WCF Services? A service is a