Monday, April 13, 2015

DotNet Fundamantals 1

Introduction To .Net
The .NET platform is an integral component of the Microsoft Windows operating system for building and running next generation software applications and Web services. The .NET development framework provides a new and simplified model for programming and deploying applications on the Windows platform. It provides such advantages as multiplatform applications, automatic resource management, and simplification of application deployment. As security is an essential part of .NET, it provides security support, such as code authenticity check, resources access authorizations, declarative and imperative security, and cryptographic security methods for embedding into the user’s application.
.NET provides a simple object-oriented model to access most of the Windows application programming interfaces (APIs). It also provides mechanisms by which you can use the existing native code. In addition, it significantly extends the development platform by providing tools and technologies to develop Internet-based distributed applications.

The .NET Platform


https://technet.microsoft.com/en-us/library/Bb496996.uamv4c1_01_big(l=en-us).gif
Basics of .Net Frame work
  • The .NET Framework is a multilanguage, application execution environment that transparently manages core infrastructure services. It is a set of multiple languages/technologies used for developing and creating components to create Web Forms, Web services, and Windows applications. It supports the software life cycle for development, debugging, deployment, and maintenance of applications. The version of .NET framework that ships with Visual Studio .NET 2003 is version 1.1. The .NET Framework consists of the following parts (also depicted in Figure 1.2):
    • Common Language Runtime (CLR).
    • .NET Framework base class library.
    • Common Language Specification (CLS).
    • .NET-compliant languages.
    • Data and XML classes such as ADO.NET and XML.
    • A set of class libraries for building XML Web services.
    • ASP.NET Web Forms-based Web applications.
    • Windows Forms-based rich client applications.
    • Common Type System (CTS).
    • Microsoft Visual Studio .NET 2003 integrated development environment (IDE).
  • Development tools. Microsoft provides the programming model, the development environment, and the tools necessary to build, deploy, and operate Web services with applications such as Visual Studio .NET 2003.
  • .NET enterprise servers. The Microsoft .NET enterprise servers make up the Microsoft .NET server infrastructure for deploying, managing, and operating XML Web services and traditional applications. Examples of enterprise servers are Microsoft SQL Server™ 2000 and Microsoft Commerce Server 2000.
  • .NET foundation services. A core set of building block services that execute standard tasks and act as a basis for developers to build upon. These foundation services are known as Microsoft .NET My Services and provide many features and functions. Most of the foundation services are hosted (outsourced) services. An example of a currently available Web service is Microsoft .NET Passport.
The .NET Framework overview

Advantages of .NET

The .NET Framework provides the following advantages:
·         A consistent, object-oriented programming environment.
·         A code-execution environment that:
o    Promotes safe execution of code.
o    Eliminates the performance problems of scripted or interpreted environments.
o    Minimizes software deployment and versioning conflicts.
·         A consistent experience for both developers and users across various types of Windows-based and Web-based applications on multiple devices.
·         Communication built on the industry standards to ensure that code based on the .NET Framework can integrate with any other code.
.NET is based on open Internet standards, which include Hypertext Transfer Protocol (HTTP), Extensible Markup Language (XML), and Simple Object Access Protocol (SOAP).
Note   More information on XML is available at http://msdn.microsoft.com/xml/ . 
More information on SOAP is available at
 
http://msdn.microsoft.com/library/en-us/dnsoap/html/understandsoap.asp.
Figure 1.2 depicts the overall architecture of the .NET Framework components.
Figure 1.2. The .NET Framework architecture
Figure 1.2. The .NET Framework architecture

Features of the .NET Framework

This section discusses some of the features of the Microsoft .NET Framework and how to use these features in migrating code from the UNIX environment.
Common Language Runtime (CLR)
The core of the .NET Framework is the CLR, the run-time environment provided by .NET. The runtime manages code at execution time and provides core services such as memory management, thread management, remoting, and strict type safety enforcement.
Figure 1.3 depicts the components of CLR.
Figure 1.3. CLR components
Figure 1.3. CLR components
CLR Features
UNIX applications, redeveloped on .NET, can make use of all the features provided by the CLR, including:
·         Simplified development and deployment of applications.
·         Application memory management.
·         Improved performance, scalability, and reliability.
·         Cross-language inheritance.
·         Multiple language support.
·         Automatic garbage collection.
·         Security.
·         Strong type checking.
·         Access to type metadata.
·         Unified exception handling.
·         Interoperability with existing code in COM (Component Object Model) objects and Microsoft Win32® DLLs.
·         Loading and executing code.
·         Just-in-time (JIT) compilation of Microsoft intermediate language (MSIL) to native code.
·         Side-by-side execution for multiple assembly versions.
·         Other developer support services that include debugging and run-time profiling.
·         Versioning and deployment support.
The .NET runtime also enforces other forms of controlled code access that promote security and robustness. Code management is a fundamental principle of the runtime. Code that targets the CLR is known as managed code, whereas code that does not target the CLR is known as unmanaged code. Unmanaged code can also be used in the .NET environment using interoperability techniques as explained in Chapter 3, “.NET Interoperability” of this volume.
All .NET applications compile to a common language called MSIL. A JIT compiler then compiles MSIL to optimized native code.
Benefits of CLR
This various benefits offered by the CLR are as follows.
Security
The runtime enforces code access security. The managed components have varied degrees of trust level depending on a number of factors, including their origin. Even if the same active application is using the managed component, depending on the trust level, the managed component might or might not be capable of performing file-access operations, registry-access operations, or other sensitive functions.
For example, users can trust that an executable embedded in a Web page can play an animation or a song, but cannot access their personal data, file system, or network.
Code Robustness
The runtime also enforces code robustness by implementing a strict type-and-code-verification infrastructure called the Common Type System (CTS). The CTS ensures that all managed code is self-descriptive. The various Microsoft and third-party language compilers generate managed code that conforms to the CTS.
Developer Productivity
The runtime also accelerates developer productivity by enabling the developers to write applications in the development language of their choice and still take advantage of all the features of the runtime. The language compilers that target the .NET Framework make the features of the .NET Framework available to the existing code written in that language, thus greatly facilitating the migration process for the existing applications.
Performance
The runtime is designed to enhance performance. JIT compiling enables all managed code to run in the native code of the system on which it is executed. At the same time, the memory manager removes the possibilities of fragmented memory and increases the memory locality-of-reference to improve the performance further.
Interoperability
The runtime, although designed for modern software, also offers backward compatibility by supporting older software. Interoperability between managed and unmanaged code provides seamless integration to developers to continue to use necessary COM objects and exported functions in unmanaged DLLs.
.NET Framework Base Class Library
The Microsoft .NET Framework 1.1 base class library is an object-oriented class library providing an integrated set of classes that expose the underlying functionality of the Win32 API as well as some other additional capabilities. These classes integrate tightly with the CLR. Third-party components can also integrate with the classes in the .NET Framework. In Microsoft .NET library, all class (types) are grouped in namespaces. A namespace is a grouping of similar kinds of classes.
The .NET Framework classes enable you to perform a range of common programming tasks such as string management, data collection, database connectivity, and file access. In addition to these common tasks, the class library includes classes that support a variety of specialized development functions. For example, you can use the .NET Framework to develop a variety of applications such as console applications, GUI (graphic user interface) applications, and Web applications.
All .NET languages can use these language-independent classes. This enables the programmers to choose the language and tools best suited for the job or the language with which they have the most experience and still share their code and create new subclasses from classes written in a different language. This code reuse can dramatically increase team productivity and decrease development costs. Figure 1.4 depicts some of the namespaces and their classes in the .NET Framework.
Figure 1.4. The .NET Framework base class library
Figure 1.4. The .NET Framework base class library
.NET Tools and Technologies
From a migration perspective, .NET provides various tools and technologies that help you to migrate or redevelop a UNIX application on Windows. Some of these tools and technologies are discussed in the following sections.
Database - ADO.NET
.NET provides ADO.NET for migrating the database-related components of a UNIX application to .NET. ADO.NET is a collection of classes, structures, and interfaces that manage the data access for different databases. .NET provides this data access technology to enable you to connect to different databases including ODBC-aware (open database connectivity) databases.
Networking - System.NET
The System.NET namespace in .NET allows you to replicate the networking functionality of a UNIX application on Windows.
Transaction - COM+ Services
.NET provides COM+ services, also referred to as Enterprise Services in .NET, to migrate applications that involve large amount of transactions.
Rich Client - Windows Forms
Windows Forms enable you to replicate the X/Motif-based GUI of a UNIX application on Windows. Windows Forms facilitate building of Windows rich-client applications that take advantage of the CLR. The Visual Studio .NET 2003 IDE also aids in the rapid redevelopment of GUI on Windows with the same look and feel as in UNIX.
Web Applications - ASP.NET
.NET provides Web Forms and ASP.NET for migrating the existing Web application on UNIX to Windows. Web Forms and ASP.NET enable you to develop real-world Web applications on Windows.
Application Integration - XML, SOAP, and Web Services
.NET supports XML, SOAP, Web services, and .NET servers that enable a migrated application to integrate with the older applications and other applications in your enterprise.

.NET XML Framework

This section lists the XML APIs available in the .NET class library that you can use for various XML-related operations.
XML is truly a core technology substrate in .NET. All other parts of the .NET Framework (such as ASP .NET and Web services) use XML as their native data representation format. The .NET Framework XML classes are also tightly coupled with Managed Data Access (ADO .NET). Traditionally, there have always been different programming models for working with relational and hierarchical data. .NET breaks that tradition by offering a more deeply integrated programming model for all types of data.

New Suite of XML APIs

Microsoft .NET introduces a new suite of XML APIs built on such industry standards as Document Object Model (DOM), XPath, XML Structured Definitions (XSD), and Extensible Stylesheet Language Transformations (XSLT). The .NET Framework XML classes offer convenience and better performance. The .NET XML Framework also provides a more familiar programming model, tightly coupled with the various classes present in System.Data and System.Xml namespaces, which encapsulate a number of functionalities that previously had to be accomplished manually.

.NET XML Namespaces

The System.Xml assembly contains a broad range of general-purpose XML support features, such as:
·         Basic I/O model.
·         I/O of primitive types.
·         In-memory traversal.
·         Filtering based on XPath expressions.
·         Transformations based on XSLT.
The .NET XML stack is partitioned over several namespaces, such as:
·         System.Xml.XPath
·         System.Xml.Xsl
·         System.Xml.Schema
·         System.Xml.Serialization
XML-based I/O
All XML-based I/O is performed using a streaming interface suite as follows:
·         Streams are supported in both pull-mode (read) and push-mode (write).
·         Built-in streaming adapters use the System.IO.Stream class library.
·         Abstract interfaces allow you to provide your own XML providers/consumers.
.NET DOM Implementation
The .NET DOM implementation (System.Xml.XmlDocument) supports all W3C DOM Level 1 core and all DOM Level 2 core specifications, but with a few minor naming changes. The DOM loading is built on top of XmlReader, while the DOM serialization is built on XmlWriter. This makes it possible to extend how the DOM interacts with applications in numerous ways.
Note   More information on W3C DOM Level 1 core and Level 2 core specifications is available at http://www.w3.org/TR/1998/REC-DOM-Level-1-19981001/ and http://www.w3.org/TR/2000/REC-DOM-Level-2-Core-20001113/.
Transformations
The XslTransform class manages XSLT transformations in the .NET Framework. XslTransform resides in the System.Xml.Xsl namespace and uses XmlNavigator during the transformation process. As with all XSLT processors, XslTransform accepts an XML document, an XSLT document, and some optional parameters as input. It can produce any type of text-based output; it also supports reading the result of the transformation using a custom XmlReader.

.NET Application Security

This section provides an overview of various security models available in the .NET Framework. The .NET Framework provides a rich security system, capable of confining code to run in a tightly constrained, administrator-defined, security context.

Role-based Security

The .NET Framework provides a developer-defined security model called role-based security that attaches security to the users and their groups (or roles). The principal abstractions of role-based security are principal and identity.

Code Access Security

Additionally, the .NET Framework also provides security on code, referred to as code access security (also referred to as evidence-based security). With code access security, a user may be trusted to access a resource but if the code that the user executes is not trusted, then access to the resource is denied. Code access security also provides a highly protective way of securing the assemblies from malicious attacks. Security based on code, as opposed to specific user, is a fundamental facility that permits security to be expressed on mobile code. Any number of users may download and execute mobile code, which is unknown at the time of development. Code access security focuses on some core abstractions, namely, evidence, policies, and permissions.
The security abstractions for role-based security and code access security are represented as types in the .NET Framework class library and are user-extendable.
The .NET Framework security system functions atop the traditional operating system security. This adds a second, more expressive and extensible level to the operating system’s security. Both layers complement each other. (It is conceivable that an operating system security system can delegate some responsibility to the CLR security system for managed code because the run-time security system is more configurable then the traditional operating system security.)
Note   More information on .NET Framework security is available at http://msdn.microsoft.com/security/securecode/dotnet/default.aspx.

Implementation in .NET

Chapter 1, “Introduction to Win32/Win64” of Volume 3 has already discussed the platform differences between UNIX and Windows from various aspects. The following topics give an overview for implementing the following architectural elements in .NET:
·         Processes and threads
·         Memory management
·         File management
·         Signals, exceptions, and events
·         Networking
·         Interprocess communication
·         User interface
·         Daemons versus services
·         Deployment

Processes and Threads

The .NET Framework further divides an operating system process into lightweight managed subprocesses, called application domains, which provide a versatile unit of processing in .NET applications. These application domains are used to provide isolation between applications and even within a single process. Several application domains can be run in a single process with the same level of isolation that would exist in separate processes. Historically, process boundaries have been used to provide isolation between applications, but application domains provide a level of isolation equivalent to that of a process boundary, however at a much lower cost of performance.
The System.Threading namespace in .NET provides all the classes and interfaces necessary to enable multithreaded programming. In addition to classes for synchronizing thread activities and providing access to data (for example, Mutex, Monitor, Interlocked, and AutoResetEvent), this namespace includes a ThreadPool class that allows use of a pool of system-supplied threads and a Timer class that executes callback methods on the thread pool threads. The next chapters discuss application domains and the threading namespaces in detail.

Memory Management

The garbage collector of the .NET Framework provides automatic memory management. It allocates and releases the memory for managed objects and, when necessary, executes the appropriate methods at the appropriate times in order to properly clean up the unmanaged resources. Automatic memory management simplifies development by eliminating the common bugs that arise from manual memory management schemes.

File Management

In .NET, the System.IO namespace provides an object-oriented tool to work with files and folders. It provides a collection of properties, methods, and events to process text and data, thus enabling you to perform file and directory operations with greater ease. For more information on the System.IO namespace, refer to Chapter 4, “Memory and File Management” of this volume.

Signals, Exceptions, and Events

.NET Framework provides an event handler mechanism to handle events. An event handler is a procedure in your code that determines the actions that must be performed when an event (such as the user clicking a button or a message queue receiving a message) occurs. When an event is raised, the event handler (or a handler) that receives the event is executed. Events can be assigned to multiple handlers and the method that handles a particular event can be changed dynamically.
The .NET Framework handles exceptions through the exception handling mechanism. In the .NET Framework, an exception is an object that it inherits from the System.Exception class. An exception originates from an area of code where a problem occurred. The exception is passed up the stack until the application handles it or the program terminates. All .NET languages handle exceptions in a similar manner. Each language uses a form of try/catch/finally structured exception handling.

Networking

The .NET Framework class library includes two namespaces that consists of classes that help you with networking; these are System.Net and System.Net.Sockets.
The System.Net classes provide a simple, yet complete solution for writing networked applications in managed code. The System.Net.Sockets classes deals with the TCP/UDP and sockets.

Interprocess Communication

In the .NET environment, application domains enable more than one application to run within a single process, thus eliminating the overhead of making cross-process calls but still maintaining the same level of application isolation that would exist in separate processes. .NET also supports the concept of thread local storage, by which data can be stored in a thread and accessed anywhere the thread exists.
Microsoft .NET Remoting provides a rich and extensible framework for objects residing in different application domains, in different processes, and in different computers to communicate with each other seamlessly. .NET Remoting offers a powerful, yet simple, programming model and run-time support for making these interactions transparent.

User Interface

In the .NET environment, user interfaces can be developed as Windows or Web Forms. Some of the advantages of using these forms include the following:
·         Simplicity and power
·         Rich graphics
·         Flexible controls
·         Lower total cost of ownership
·         Architecture for controls
·         High security
·         XML Web services support
·         Data awareness
·         ActiveX control support
·         Easy licensing
·         Enhanced printing support
·         Accessibility
·         Design-time support

Daemons vs. Services

The .NET Framework class library includes the System.ServiceProcess namespace that provides classes to implement, install, and control Windows service applications.
Services are installed using an installation tool, such as InstallUtil.exe. The System.ServiceProcess namespace provides installation classes that write service information to the registry.
The ServiceController class enables you to connect to an existing service and manipulate it or get information about it. This class is typically used in an administrative capacity; it enables you to start, stop, pause, continue, or perform custom commands on a service.

Deployment

In .NET Framework applications, assemblies are the building blocks. They form the fundamental unit of deployment, version control, reuse, activation scoping, and security permissions. Current Win32 applications have two versioning problems with their building blocks (dynamic-link libraries):
·         Versioning rules cannot be expressed between pieces of an application and enforced by the operating system.
·         Inability to maintain consistency between sets of components that are built together and the set that is present at runtime.
These two versioning problems combine to create DLL conflicts, or DLL Hell, where installing one application can inadvertently break an existing application because a certain software component or DLL that was installed was not fully backward compatible with a previous version. The CLR uses assemblies to provide a complete solution for DLL conflicts. Assemblies allow the runtime to:
·         Enable developers to specify version rules between different software components.
·         Enable the infrastructure to enforce versioning rules.
·         Enable the infrastructure to allow multiple versions of a component to run simultaneously (called side-by-side execution).
Each computer, where the CLR is installed, has a machine-wide code cache called the Global Assembly Cache (GAC). The GAC stores assemblies specifically designated to be shared by several applications on the computer.
Assemblies deployed in the GAC must have a strong name. When an assembly is added to the GAC, integrity checks are performed on all files that make up the assembly. The cache performs these integrity checks to ensure that an assembly has not been tampered with.

Summary of Platform Differences

Table 1.1 lists the basic platform differences that exist between UNIX, Windows, and .NET.
Table 1.1. Summary of Platform Differences
Architectural Element
UNIX
Windows
.NET
Processes
Processes have a parent-child relationship.
Process boundary provides isolation between applications.
Processes do not have a parent-child relationship.
Process boundary provides isolation between applications.
Processes do not have a parent-child relationship.
An operating system process is further divided into subprocesses called application domains. Application domains provide isolation between applications.
Threads
UNIX threads are built upon the POSIX standard, known as Pthreads.
The Windows operating system provides built-in support for threads and thread synchronization using Platform SDK.
.NET provides the System.Threading namespace to support multithreading in conjunction with Windows threads.
Memory
At application level, memory management is manual (in the hands of the programmer).
At application level, memory management is manual (in the hands of the programmer).
Memory management is automatic and controlled by the CLR, eliminating bugs such as memory leakages from manual memory management.
File
File operations are performed through low-level I/O functions and stream I/O functions.
File operations are performed through low-level I/O functions and stream I/O functions.
The System.IO namespace provides an object-oriented framework for handling files and folders.
Signals
UNIX supports a wide range of signals. Signals are software interrupts that catch or indicate different types of events.
Windows supports only a small set of signals that is restricted to exception events. Native signals, event objects, and messages are the recommended mechanisms to replace common UNIX signals.
.NET does not support signals.
Events and exception handling mechanisms in .NET are the recommended mechanisms to replace common UNIX signals.
Networking
UNIX supports networking through sockets.
In Windows, sockets are implemented using WinSock libraries.
The System.Net.Sockets namespace provides networking support in .NET.
Interprocess communication
UNIX provides shared memory, pipes, and message queues for interprocess communication.
Windows provides shared memory, pipes, events, Dynamic Data Exchange (DDE), Component Object Model (COM), and mailslots for interprocess communication.
.NET Framework provides .NET Remoting and Microsoft Message Queue for interprocess communication.
UI differences
UI is developed using X Windows and Motif, which are the standard windowing system and windowing system library respectively on UNIX.
UI is developed using MFC (Microsoft Foundation Classes), ATL (Active Template Library), or GDI+ (Graphics Device Interface).
.NET Framework provides Windows Forms and Web Forms for development of UI of rich client and Web applications respectively.
Deployment differences
UNIX provides shared objects for developers to group common functionality and deploy them.
Windows provides DLLs for developers to group common functionality and deploy them.
In .NET, assemblies form the fundamental unit of deployment, version control, reuse, activation scoping, and security permissions.
Daemons and services
UNIX supports daemons (a process that runs in the background and does not require a user interface).
Windows service is the equivalent of daemons.
.NET provides the System.ServiceProcess namespace to implement, install, and control Windows service applications.

.NET Migration Paths

This section discusses the various .NET migration paths. You can use this information in reengineering code in .NET and in understanding the interaction of the .NET code with existing applications. This section also helps you to choose the best migration path based on the nature of existing UNIX applications.
To move UNIX applications to the Microsoft .NET Framework, you need to migrate the existing UNIX C or C++ code to Windows. For example, if the UNIX applications use third-party libraries and if the equivalents of such third-party libraries are already available on Windows, then the UNIX to Windows move is much easier. The code migrated from UNIX can then integrate the .NET Framework features.
For UNIX applications involving code in Java, Visual Studio .NET 2003 provides a tool known as Java Language Conversion Assistant (JLCA) that can automatically convert existing Java language code into C#. You can use this tool in migration scenarios where the existing UNIX application contains Java code.
With a large code base of installed UNIX applications, you are unlikely to relish the thought of throwing out the entire environment and starting again with an unfamiliar platform. Fortunately, you do not necessarily have to do this. As illustrated in this guide, methods are available by which you can preserve the existing code while moving to .NET.

Analyzing Application Types

The application type and the ease with which you can move the application from UNIX to Windows should decide whether to use the .NET interoperability strategies or to redevelop the application completely on the .NET environment. Different application types and strategies for migrating these application types are discussed in the following sections.
Static Application
Static applications are applications that are in the later stages of their life cycle, with stable code, and with little or no changes planned. If these applications can be migrated to Win32 using little or no code changes, then they can also be adapted to make use of the capabilities of the .NET platform by using the interoperability services provided by .NET. This way you can not only speed the application migration but also preserve your investments in the existing code. If the static application is an enterprise application, such as a portal or a content management system, then you can take advantage of the capabilities of the .NET servers, in addition to reusing the existing code.
Evolving Application
Evolving applications are applications that are constantly being changed and enhanced. An evolving application typically contains both static and dynamic components. Static components are the parts of the application that do not change, whereas dynamic components are the parts of the application that are evolving.
First, identify the static and dynamic components of the application and then use the .NET interoperability strategies to migrate the static components.
The dynamic components can be redeveloped in .NET targeting the benefits offered by the CLR and making full use of the other benefits of the .NET development platform.
Table 1.2 lists the .NET migration strategies for the different types of applications.
Table 1.2. Migration Strategies
Application
Nature of Existing Application
Recommended Solution
Static application
Native UNIX application (UNIX APIs, X Windows, and Motif).
Migrate the application to Win32/Win64 with minor code changes and then interoperate with the .NET code to preserve and make use of the investments made earlier.
Static application
Enterprise applications such as portal, content management, and others.
Use .NET servers and interoperate with the migrated Win32/Win64 or unmanaged code.
Evolving application
Native UNIX application (Unix APIs, X Windows, and Motif).
Reengineer in .NET
Evolving application
Enterprise applications such as portal, content management, and others.
Use .NET servers; interoperate with the migrated Win32/Win64 or unmanaged code, and reengineer in .NET.
The subsequent sections discuss the different migration strategies listed in Table 1.2.
·         Reengineering using the .NET Framework.
·         Interoperating with the existing code.
·         Utilizing .NET servers.

Reengineering Using the .NET Framework

This section describes reengineering the applications using the .NET Framework and its advantages. A reengineering strategy is appropriate when an application needs to evolve further and the costs of porting the application outweigh the benefits, or when specific application qualities (such as performance or scalability) require that the code be written specifically for the Windows platform.
Rewriting an application has a number of significant advantages, including:
·         Code robustness.
·         Accelerates developer productivity.
·         Enhanced performance and scalability.
·         Interoperability between managed code and unmanaged code.
·         Flexible language options.
·         Improved tool support.
·         Rich class library.
You can redevelop an application using any of the .NET compatible languages, such as Microsoft Visual Basic® .NET, C#, and Managed C++. Managed code, which is compiled to Intermediate Language (IL) and not to machine code, is created using these languages. The redeveloped code on .NET can make use of all the features of the CLR. The code that is redeveloped in .NET to target the CLR goes through the managed execution process. The following steps are involved in the managed execution process.
1.     Choose a compiler.
To obtain the benefits provided by the CLR, you must use one or more language compilers that target the runtime, such as C#, Microsoft Visual C++®, Microsoft Visual Basic .NET, Microsoft Visual J#®, Microsoft JScript®, or one of the many third-party compilers such as Eiffel, Perl, or COBOL. Multiple .NET languages support a common set of data types. For example, a string in C# is the same data type as a string in Visual Basic .NET. If you are migrating a C++ application, consider using the Visual C++ .NET for redevelopment. If you are migrating a Java application, you can consider Visual C# for redevelopment.
2.     Compile code.
On compiling the code, it is converted to Microsoft Intermediate Language (MSIL) code using the selected .NET language compiler. When you execute the code for the first time, the Just-In-Time (JIT) compiler translates MSIL into the native code. During this compilation, code must pass a verification process that examines MSIL and the metadata to find out whether the code can be determined to be type safe. There are two kinds of JIT compilers: Standard JIT and Econo-JIT. Econo-JIT has a faster compilation speed and a lesser compiler overhead than Standard-JIT. However, the Standard-JIT generates more optimized code than the Econo-JIT and includes the verification of MSIL code.
3.     Execute code.
The CLR provides the infrastructure for executing the code as well as a variety of services that can be used during execution.
Figure 1.5 illustrates the managed execution process in a .NET application.
Figure 1.5. Managed execution process

Common Language Specification
To fully interact with other objects regardless of the language they were implemented in, objects must expose to callers only those features that are common to all the languages they must interoperate with. For this reason, the Common Language Specification (CLS), which is a set of basic language features needed by many applications, has been defined. The CLS rules define a subset of the Common Type System; that is, all the rules that apply to the common type system apply to the CLS, except where stricter rules are defined in the CLS. The CLS helps enhance and ensure language interoperability by defining a set of features that developers can rely on to be available in a wide variety of languages. The CLS also establishes requirements for CLS compliance; these help you determine whether your managed code conforms to the CLS and to what extent a given tool supports the development of managed code that uses CLS features.

IL code, CLR, CTS, CLS & JIT
IL/MSIL/CIL- IL code is a CPU independent partially compiled code. It’s partially compiled because we do not know in what kind of environment .Net code will run and on runtime IL Code will compile to machine code using the environmental properties (CPU, OS, machine configuration etc).
ILDASM- this is tool provided by visual studio to view IL code. To run ILDASM we have to select option “Visual Studio Command Prompt” from “Visual Studio Tools” and type ildasm. It will open the ildasm tool where we can open any exe/dll.ildasm tool read the assembly by reflection and it is showing us various properties, methods which our assembly has. Here we can see IL code of any method/property by clicking on that

CLR- CLR is the heart of the .Net framework and it does 4 primary important things-
1. Garbage collection
2. CAS (Code Access Security)
3. CV (Code Verification)
4. IL to Native translation.

CTS- CTS ensure that data types defined in two different languages get compiled to a common data type. This is useful because there may be situations when we want code in one language to be called in other language.
we can see practical demonstration of CTS by creating same application in C# and VB.Net and then compare the IL code of both application. Here the datatype of both IL code is same.

CLS- CLS is a subset of CTS. CLS is a set of rules or guidelines. When any programming language adheres to these set of rules it can be consumed by any .Net language.CTS


JIT-JIT compiles the IL code to Machine code just before execution and then saves this transaction in memory.


.Net Platform Independent or not

.NET is platform independent as long as the platform is .NET, the same way that Java is platform independent as long as the platform is Java. That is to say, .NET (and Java) are, in part, platforms in themselves (CLR, JVM). As long as there is an implementation of that platform available for a given physical platform, yes, you can run the compiled code on it independently.

Assemblies and the Global Assembly Cache
Assemblies form the fundamental unit of deployment, version control, reuse, activation scoping, and security permissions for a .NET-based application. Assemblies take the form of an executable (.exe) file or dynamic link library (.dll) file, and are the building blocks of the .NET Framework. They provide the common language runtime with the information it needs to be aware of type implementations. You can think of an assembly as a collection of types and resources that form a logical unit of functionality and are built to work together.
Assemblies can contain one or more modules. For example, larger projects may be planned in such a way that several individual developers work on separate modules, all coming together to create a single assembly. For more information about modules, see the topic How to: Build a Multifile Assembly.
Assemblies have the following properties:
·         Assemblies are implemented as .exe or .dll files.
·         You can share an assembly between applications by putting it in the global assembly cache. Assemblies must be strong-named before they can be included in the global assembly cache. For more information, see Strong-Named Assemblies.
·         Assemblies are only loaded into memory if they are required. If they are not used, they are not loaded. This means that assemblies can be an efficient way to manage resources in larger projects.
·         You can programmatically obtain information about an assembly by using reflection. For more information, see Reflection.
·         If you want to load an assembly only to inspect it, use a method such as ReflectionOnlyLoadFrom.

Assembly Manifest

Within every assembly is an assembly manifest. Similar to a table of contents, the assembly manifest contains the following:
·         The assembly's identity (its name and version).
·         A file table describing all the other files that make up the assembly, for example, any other assemblies you created that your .exe or .dll file relies on, or even bitmap or Readme files.
·         An assembly reference list, which is a list of all external dependencies—.dlls or other files your application needs that may have been created by someone else. Assembly references contain references to both global and private objects. Global objects reside in the global assembly cache, an area available to other applications, somewhat like the System32 directory. The Microsoft.VisualBasic namespace is an example of an assembly in the global assembly cache. Private objects must be in a directory at either the same level as or below the directory in which your application is installed.

Strong Name is a technology introduced with the .NET platform and it brings many possibilities into .NET applications. But many .NET developers still see Strong Names as security enablers (which is very wrong!) and not as a technology uniquely identifying assemblies. There is a lot of misunderstanding about SNs (as we could see in the article "Building Security Awareness in .NET Assemblies : Part 3 - Learn to break Strong Name .NET Assemblies ") and this article attempts to clear those up.

Managed and Un Managed code
Managed code is not compiled to machine code but to an intermediate language which is interpreted and executed by some service on a machine and is therefore operating within a (hopefully!) secure framework which handles dangerous things like memory and threads for you. In modern usage this frequently means .NET but does not have to.
Unmanaged code is compiled to machine code and therefore executed by the OS directly. It therefore has the ability to do damaging/powerful things Managed code does not. This is how everything used to work, so typically it's associated with old stuff like .dlls

Managed Code
Managed code is what Visual Basic .NET and C# compilers create. It runs on the CLR (Common Language Runtime), which, among other things, offers services like garbage collection, run-time type checking, and reference checking. So, think of it as, "My code is managed by the CLR."
Visual Basic and C# can only produce managed code, so, if you're writing an application in one of those languages you are writing an application managed by the CLR. If you are writing an application in Visual C++ .NET you can produce managed code if you like, but it's optional.
Unmanaged Code
Unmanaged code compiles straight to machine code. So, by that definition all code compiled by traditional C/C++ compilers is 'unmanaged code'. Also, since it compiles to machine code and not an intermediate language it is non-portable.
No free memory management or anything else the CLR provides.
Since you cannot create unmanaged code with Visual Basic or C#, in Visual Studio all unmanaged code is written in C/C++.
Mixing the two
Since Visual C++ can be compiled to either managed or unmanaged code it is possible to mix the two in the same application. This blurs the line between the two and complicates the definition, but it's worth mentioning just so you know that you can still have memory leaks if, for example, you're using a third party library with some badly written unmanaged code.
Here's an example I found by googling:
#using <mscorlib.dll>
using namespace System;
 
#include "stdio.h"
 
void ManagedFunction(){
    printf("Hello, I'm managed in this section\n");
}
#pragma unmanaged
UnmanagedFunction(){
    printf("Hello, I am unmanaged through the wonder of IJW!\n");
    ManagedFunction();
}
 
#pragma managed
int main()
{
    UnmanagedFunction();
    return 0;
}


Reflection
Reflection is the ability of a managed code to read its own metadata for the purpose of finding assemblies, modules and type information at runtime. In other words, reflection provides objects that encapsulate assemblies, modules and types. A program reflects on itself by extracting metadata from its assembly and using that metadata either to inform the user or to modify its own behavior. Reflection is similar to C++ RTTI (Runtime Type Information), but much broader in scope and capability. By using Reflection in C#, one is able to find out details of an object, method, and create objects and invoke methods at runtime. The System.Reflection namespace contains classes and interfaces that provide a managed view of loaded types, methods, and fields, with the ability to dynamically create and invoke types. When writing a C# code that uses reflection, the coder can use the typeof operator to get the object's type or use the GetType() method to get the type of the current instance. Here are sample codes that demonstrate the use of reflection:

Example 1

Hide   Shrink http://www.codeproject.com/images/arrow-up-16.png  Copy Code
using System;
using System.Reflection;
 
public class MyClass
{
   public virtual int AddNumb(int numb1,int numb2)
   {
     int result = numb1 + numb2;
     return result;
   }
 
}
 
class MyMainClass
{
  public static int Main()
  {
    Console.WriteLine ("\nReflection.MethodInfo");
    // Create MyClass object
    MyClass myClassObj = new MyClass();
    // Get the Type information.
    Type myTypeObj = myClassObj.GetType();
    // Get Method Information.
    MethodInfo myMethodInfo = myTypeObj.GetMethod("AddNumb");
    object[] mParam = new object[] {5, 10};
    // Get and display the Invoke method.
    Console.Write("\nFirst method - " + myTypeObj.FullName + " returns "
                         myMethodInfo.Invoke(myClassObj, mParam) + "\n");
    return 0;
  }
}
Firstly, the code snippet below will get the type information:
Hide   Copy Code
Type myTypeObj = Type.GetType("MyClass");
And myTypeObj will now have the required information about MyClass. Therefore we can now check if the class is an abstract class or a regular class by using either of these statements:
Hide   Copy Code
myTypeObj.IsAbstract 
or:
Hide   Copy Code
myTypeObj.IsClass 
The code snippet below will get the method's information. And the method that we are interested in this case is AddNumb:
Hide   Copy Code
Methodinfo myMethodInfo = myTypeObj.GetMethod("AddNumb"); 
The following code snippet will invoke the AddNumb method:
Hide   Copy Code
myMethodInfo.Invoke(myClassObj, mParam);
//Example2: In this example, we will use the typeof keyword to obtain the
//          System.Type object for a type.
 
Public class MyClass2
{
  int answer;
  public MyClass2()
  {
    answer = 0;
  }
 
  public int AddNumb(intnumb1, intnumb2)
  {
    answer = numb1 + numb2;
    return answer;
  }
}
The code snippet below gets the System.Type object for the MyClass2 type.
Hide   Copy Code
Type type1 = typeof(MyClass2);
So we will now be able to create an instance of the type1 object by passing the type1 object to the Activator.CreateInstance(type1) method.
Hide   Copy Code
object obj = Activator.CreateInstance(type1);
Then we can now invoke the AddNumb method of the MyClass2 class by first creating an array of objects for the arguments that we would be passing to the AddNumb(int, int) method.
Hide   Copy Code
object[] mParam =newobject[] {5, 10}; 
Finally, we would invoke the AddNumb(int, int) method by passing the method name AddNumb to System.Type.InvokeMember() with the appropriate arguments.
Hide   Shrink http://www.codeproject.com/images/arrow-up-16.png  Copy Code
int res = (int)type1.InvokeMember("AddNumb", BindingFlags.InvokeMethod,null,
                                  obj, mParam);
//Here is the complete code:
using System;
using System.Reflection;
 
namespace Reflection
{
   class Class1
   {
    public int AddNumb(int numb1, int numb2)
    {
      int ans = numb1 + numb2;
      return ans;
    }
 
  [STAThread]
  static void Main(string[] args)
  {
     Type type1 = typeof(Class1); 
     //Create an instance of the type
     object obj = Activator.CreateInstance(type1);
     object[] mParam = new object[] {5, 10};
     //invoke AddMethod, passing in two parameters
     int res = (int)type1.InvokeMember("AddNumb", BindingFlags.InvokeMethod,
                                        null, obj, mParam);
     Console.Write("Result: {0} \n", res);
   }
  }
}
Using COM Components in .NET

Introduction

This Article will help you in understanding the Inter operation between .NET Environment and COM components (Which are nothing but Win32 Dynamic Linked Library and ActiveX controls.
That's .dll and .ocx files).

Background

Consider this, If I have few COM components which includes DLLs and ActiveX components as well, and now time has come to upgrade the application functionality and UI things, Also there is requirement of Application availability through Web. So what I have decided to write some part of the application in .NET so that Web Deployment and the registration problems of DLL and ActiveX problems will be removed.
In above scenario, either I can write the whole new application which is truly .NET Framework based, or I can make use of the available functionality of the business logic in newly developed Web Application and Desktop application. Yes, I am talking about the COM-.NET Inter Operation, the way by which I we can talk with COM components and vice versa.
Let's start digging and find out what exactly the COM Inter Op is and what are the different ways by which we can achieve it.

What Exactly the DLLs and OCX files are?

A Dynamic Linked Library (DLL) is a file code containing functions that can be called from other executable code (either an application or another DLL). Programmers use DLLs to provide code that they can reuse and ship with the product and to distribute. Unlike an executable (EXE) file, a DLL cannot be directly run. DLLs must be called from other code that is already executing.
A DLL is a file indicated by the extension DLL in its name.
e.g- > kernell32.dll, msvbvm60.dll, msvcrt32.dll
In Simple words DLL is a file which contains function calls available for the outside world and outside world can make use of these function calls. Here outside world is nothing but, Another DLL and or an Application.
On the other hand OCX or simply ActiveX components are the components which (Dlls and Ocx are together called as ActiveX components). In next section we will see what exactly the ActiveX Components are.

ActiveX Components

An ActiveX control is really just another term for "OLE Object" or, more specifically, "Component Object Model (COM) Object." In other words, a control, at the very least, is some COM object that supports the IUnknown interface and is also self-registering. Through QueryInterface a container can manage the lifetime of the control, as well as dynamically discover the full extent of a control's functionality based on the available interfaces. This allows a control to implement as little functionality as it needs to, instead of supporting a large number of interfaces that actually don't do anything. In short, this minimal requirement for nothing more than IUnknown allows any control to be as lightweight as it can. Other than IUnknown and self-registration, there are no other requirements for a control. There are, however, conventions that should be followed about what the support of an interface means in terms of functionality provided to the container by the control. This section describes what it means for a control to actually support an interface, as well as methods, properties, and events that a control should provide as a baseline if it has occasion to support methods, properties, and events.
I think, this is enough to see what and how exactly we can interact with COM from within the .NET and vice versa.

Runtime Callable Wrappers

As discussed in background, it is more likely that.NET Application will have to interoperate with COM, we will first find out how we can achieve that. A .NET application access COM through Runtime callable wrappers or RCW. RCW wraps COM object and acts as a bridge between COM and .NET Runtime, and acts as if RCW is a Native Object.
We can generate RCW, by one of the two ways. First, using Visual Studio.NET, In Microsoft Visual Studio.NET, right-click on the References section of your Project, (If you are unable to view the References section under project, then click on "Show All Files" icon on Solution Explorer window, by default References section is hidden in Visual Studio 2005). Select Add Reference, you will see the dialog box, (Fig.1) here you can browse for COM component that you want add into your project as a reference. Select the desired file and click on add, Visual Studio.NET will create RCW and will add it as a reference in the project.
<formulas /></formulas />
Screenshot - AddrefercenRCW.gif
(Fig.1.)
If you're not using Microsoft Visual Studio.NET Environment, there is another way bu which you can create RCW. When you install .NET Framework SDK (VS.NET), there are certain set of tools, gets installed on the system. Out of those tools, one tools called TlbImp.exe (Type Lib Importer Utility), which is useful for creating RCW or Runtime callable Wrappers. Let's find out how we can actually import COM as reference or how we can create RCW.
(Note: To run this example make sure you have Library path set in your system variables.)
For example you want to add COMDemo.dll Com component from command line as a reference, then on the command line you type following.
C:\> tlbimp comdemo.dll
It will create RCW in the directory you've specified; now you can refer RCW in your project by importing or creating objects.

COM Callable Wrappers

Suppose, on the other hand, that you have a client that already talks with COM and now you want to make it use a .NET object instead. This is a somewhat less common scenario than the reverse situation because it presupposes new COM development in a .NET world. But I can easily see it occurring if you have an existing COM client that uses 10 COM objects and you now want to add an additional set of functionality that exists only as a .NET object. The .NET Framework supports this situation as well, via a COM-callable wrapper (CCW).
Here exactly the reverse things happens, CCW wraps .NET Objects and makes it available for the COM interaction, it acts as if it is a COM Component to the Other COM objects and or application outside of the .NET world. Now there are some rules that we need to follow to make it happen and work properly. First, .NET component which is required to be exposed to the COM, must have signed strong name, otherwise CLR will not recognize it. Second, it must reside in local machines Global Assembly Cache (GAC). If you want your CCW to be available for the other applications also, then it must reside in GAC, if not (which is less common) then it must present in applications directory (then it will act as Private assembly and is only available to that particular application). As the matter of fact COM component does not know how to pass the parameters while creating an object, .NET component, which is to be exposed must have a default constructor (a constructor without parameter list).
In order to for COM components to find .NET Object, you also need to make registry entry for that .NET component. This we can do using a tool call RegAsm.exe, which is again available when you install .NET SDK. To register type following on the command line.
C:\> regasm <name of the .NET component>
After registration is successful, COM Components can take the advantages of .NET objects.
In next article we will look more deeply, how we can create .NET Components for COM interaction and how we can control the exposure.
Here is something useful which you can take advantage of.
1) Registering DLL,OCX using Win32 command line. In Start-> Run Type following if you want to register any dll or ocx file. Regsvr32 "path"\xyz.dll or Regsvr32 /i path"\xyz.dll
2) To un registering the registered path from the windows registry you type Regsvr32 /u path"\xyz.dll

Net Interoperability ( COM, CCW,RCW , regsvr32 )
One of the big challenges I had to overcome this week was how to launch an application with arguements from a hyperlink in the WebBrowser Control.  You would think this would be fairly easy, but underneath the workings of the WebBrowser Control is security-heavy Internet Explorer.  I guess one of Microsoft's ongoing challenges is to balance the amount of security  IE needs against viruses and wormbots and to make the control useable for developers. It seems to me, when it comes to automating IE,  Microsoft has lately been leaning on making life more secure for the consumer and more painful for developers.  I guess my mistake was to think I could use the WebBrowser Control as a Reporting Tool and extend it beyond simple reporting.  Still, it would be REALLY nice if there was a way to turn off the security for the WebBrowser control when you are developing it to be used as an application on a local machine.
Anyway, after three days of research and some hard learning experience, I managed to figure out how you could launch an application from a hyperlink in HTML.  The trick is to write javascript into your HTML report that will create an ActiveX control that will in turn call the application you wish to launch.
http://www.c-sharpcorner.com/UploadFile/mgold/HyperlinkExec03012007191054PM/Images/HyperLinkExecute.jpg
Figure 1 - Steps for running an executable from a hyperlink in IE
Javascript from a Hyperlink
Did you know that you can launch javascript from a hyperlink using the following syntax?
<a href = "javascript:alert('hello')"> post alert</a>
You can try it yourself by just typing
 javascript:alert('hello')
into your browser, which brings up figure 2:
http://www.c-sharpcorner.com/UploadFile/mgold/HyperlinkExec03012007191054PM/Images/javascriptalert.jpg
Figure 2 - Result of javascript command in browser edit window
The same technique can be used to call your own javascript function called launch, that will eventually launch your local machine process:
<a href = "javascript:launch('name', 'date')">launch it!</a>
In my current project, I needed to generate the line above for a report using xsl. If you are generating the hyperlink above from xsl,  your xslt for this might look like the following (xsl gives you the flexibility of populating the parameters in your javascript call with data from an xml file.)
Listing 1 - XSL for generating a hyperlink that calls javascript
<A>
<xsl:attribute name="HREF">
javascript:launch('<xsl:value-of select ="$name"/>', '<xsl:value-of select ="$date"/>')
</xsl:attribute>
<xsl:value-of select ="$title"/>
</A>
So what does the javascript launch code look like?  The javascript just gives us a conduit to an ActiveX control which we can call with the parameters name and date.  We simply use the javascript to create the ActiveX COM object and dispatch a Run call from the object.
Listing 2 - javascript for creating and calling an ActiveX Object

<script type="text/javascript">
function launch(name, date)
{
  var myLauncher = new ActiveXObject('HyperLinkLauncher.Launcher');
  alert ("name:" + name + " date:" + date);
  myLauncher.Run(name, date);
}
</script>




If we want to include the javascript in our xsl generation script, we can just stick the javascript all in a CDATA block so xsl won't get confused by the javascript symbols and characters:
Listing 3 - xsl for generating the javascript in listing 2
 <script type="text/javascript">
<![CDATA[
function launch(name, date)
{
  var myLauncher = new ActiveXObject('HyperLinkLauncher.Launcher');
  alert ("name:" + name + " date:" + date);
  myLauncher.Run(name, date);
}
]]>
</script>
Creating an COM Callable Wrapper (CCW) in .NET
Now we have all the pieces in our HTML to call an ActiveX Control with parameters from HTML.  The next step is to create the ActiveX control that will launch a process on our local machine.  Microsoft gives us an easy way to create ActiveX controls in .NET using the COM Callable Wrapper.  By just placing a few attributes in our classes and interfaces, we can add automation directly into a .NET program or library. (It sure beats the old way using ATL!!)
So let's review what we are trying to do.  We are trying to launch a process from the hyperlink and pass it parameters.  In order to launch the process we need to create an ActiveX Control called HyperLinkLauncher.Launcher.  The first step to creating are ActiveX COM callable wrapper is just to create a new project of type library.  ActiveX controls don't need to be executables, we just need to be able to create them and use their an interface to access their methods and properties.  Go to the File->New->Project menu and choose a Class Library project as shown in figure 2.
http://www.c-sharpcorner.com/UploadFile/mgold/HyperlinkExec03012007191054PM/Images/createlibproject.jpg
Figure 2 - Creating a C# Project of Type Library
Next we open up the Launcher class and add a ProgId attribute to the class named "HyperLinkLauncher.Launcher".  Adding this attribute will allow us to create a COM object with this name using javascript.  Also we want to add a Run method to run our command line application.  The Run method uses the System.Diagnostics.Process.Start method to launch our commandline process with the name and date parameters.
Listing 4 - Adding the ProgId attribute
    [ProgId("HyperLinkLauncher.Launcher")]
    [
ClassInterface(ClassInterfaceType.None)]
   
public class Launcher : ILauncher
    {
      public void Run(string name, string date)
        {
           
string commandString;
           
commandString = string.Format("/N {0} /D {1}", name, date);
            
Process.Start(@"C:\Program Files\Microgold\Apps\MyApp.exe",
                                                
commandString);
        }

    }
In order to access our run method through COM, we need to add an interface.  This interface will be used to create our dispatch interface which will expose our COM methods and properties.  The interface is shown in listing 5.  The InterfaceType attribute and the DispID attribute adds the plumbing  to create the necessary COM functionality:  Also you need a GUID (unique id) attribute, to distinguish your ActiveX controls from all the other activex controls on your computer system.  You can generate the GUID from the VS.NET menu under Tools->Create GUID and then paste the GUID into the Guid attribute above your interface.
Listing 5 - Adding the ProgId attribute
    [Guid("D1E4C49A-FA4B-424a-8D61-0F5CE8B6F2FB")]
    [
InterfaceType(ComInterfaceType.InterfaceIsIDispatch)]
   
public interface ILauncher
    {
        [
DispId(1)]
       
void Run(string name, string date);
    }
The full code for your the CCW is shown in Listing 6.  Note that there really isn't that much coding necessary to turn your .NET class into a COM object.
Listing 6- A COM Callable Wrapper for Launching a Process with Arguements
using System;
using
System.Collections.Generic;
using
System.Text;
using
System.Windows.Forms;
using
System.Diagnostics;
using
System.Runtime.InteropServices;
namespace HyperLinkLauncher
{
    [Guid("D1E4C49A-FA4B-424a-8D61-0F5CE8B6F2FB")]
    [
InterfaceType(ComInterfaceType.InterfaceIsIDispatch)]
   
public interface ILauncher
    {
        [
DispId(1)]
       
void Run(string name, string date);
    }
    [ProgId("HyperLinkLauncher.Launcher")]
    [
ClassInterface(ClassInterfaceType.None)]
   
public class Launcher : ILauncher
    {
       
public void Run(string name, string date)
        {
           
string commandString;
           
commandString = string.Format("/N {0} /D {1}", name, date);
            
Process.Start(@"C:\Program Files\Microgold\Apps\MyApp.exe",
                                                
commandString);
        }
    } 
}
Installing the COM Callable Wrapper
It's not enough to build the CCW and celebrate your successful hack.  In order to get your COM callable wrapper to work properly,  three things need to happen (1) Your CCW must be strong named  (2)  you need put your library assembly into the GAC.  (3)  You need to register your Active X control as a COM object.
In order to create a strong name for your assembly, go to your project properties in Visual Studio, pick the signing tab, and check Sign the assembly.  Also, you will need to provide a strong name key file name.
http://www.c-sharpcorner.com/UploadFile/mgold/HyperlinkExec03012007191054PM/Images/SignAssembly.jpg

Now we need to place the signed assembly in the GAC.  The easiest way to stick the CCW into the GAC is to open up c:\windows\assembly under file explorer and drag your compiled dll into the directory.  Of course, you could also use the command line tool gacutil.exe.
    gacutil.exe /i  Launcher.dll
To register your COM callable wrapper with your system,  you'll need to use regasm  (regsvr32.exe won't work on a .NET CCW).  Upon running regasm, the utility will indicate if your dll was registered successfully.  You can also use visual studio 6.0 tools such as OLE View to look at the contents of Launcher.tlb after it is generated to make sure that your COM interface was created properly.  The command line for regasm is (including type lib generation) is shown below:
regasm /tlb:Launcher.tlb Launcher.dll
Once you've successfully registered your COM object, you can test your javascript code to make sure it launches your app properly.  You may want to add a MessageBox.Show (you'll need to include System.Windows.Forms.dll in your library references.)  in your Run method to make sure your ActiveX Run command is being accessed.
Conclusion
Creating COM callable objects is a snap using the attributes provided with the .NET framework.  One of the great uses for these CCW's (along with javascript) is to allow you to launch applications from the WebBrowser control.  Unfortunately, you will still initially see the warning in the WebBrowser control that says,  "An active x control might be unsafe...".  I have not yet figured out how to get rid of this annoying message.  If you have any suggestions, feel free to contact me and I'll add it to this article.  Fortunately, the message disappears once you say Yes, but will come back next time you run the application.
http://www.c-sharpcorner.com/UploadFile/mgold/HyperlinkExec03012007191054PM/Images/activexwarning.jpg
Figure 3 - Warning that comes up in the WebBrowser Control
Anyway,  hopes this help you utilize the WebBrowser control as a more interactive part of your .NET arsenal.  Remember, if you have any COMments, please feel free to share them here on C# Corner.

C# 2.0 Features
Generics
First off, generics are not like C++ templates. They primarily provide for strongly typed collections.
Without Generics
Hide   Copy Code
public void WithoutGenerics()
{
  ArrayList list = new ArrayList();

  // ArrayList is of type object, therefore essentially untyped.
  // Results in boxing and unboxing of value types
  // Results in ability to mix types which is bad practice.
  list.Add(1);
  list.Add("foo");
}
Without generics, we incur a "boxing" penalty because lists are of type "object", and furthermore, we can quite easily add incompatible types to a list.
With Generics
Hide   Copy Code
public void WithGenerics()
{
  // Generics provide for strongly typed collections.
  List<int> list = new List<int>();
  list.Add(1); // allowed
  // list.Add("foo"); // not allowed
}
With generics we are prevented from using a typed collection with an incompatible type.
Constraints and Method Parameters and Return Types
Generics can also be used in non-collection scenarios, such as enforcing the type of a parameter or return value. For example, here we create a generic method (the reason we don't create a generic MyVector will be discussed in a minute:
Hide   Shrink http://www.codeproject.com/images/arrow-up-16.png  Copy Code
public class MyVector
{
    public int X { get; set; }
    public int Y { get; set; }
}

class Program
{
    public static T AddVector<T>(T a, T b)
      where T : MyVector, new()
    {
      T newVector = new T();
      newVector.X = a.X + b.X;
      newVector.Y = a.Y + b.Y;

      return newVector;
    }

    static void Main(string[] args)
    {
     MyVector a = new MyVector();
     a.X = 1;
     a.Y = 2;
     MyVector b = new MyVector();
     b.X = 10;
     b.Y = 11;
     MyVector c = AddVector(a, b);
     Console.WriteLine(c.X + ", " + c.Y);
   }
}
Notice the constraint. Read more about constraints here. The constraint is telling the compiler that the generic parameter must be of type MyVector, and that it is an object (the "new()") constraint, rather than a value type. The above code is not very helpful because it would require writing an "AddVector" method for vectors of different types (int, double, float, etc.)
What we can't do with generics (but could with C++ templates) is perform operator functions on generic types. For example, we can't do this:
Hide   Copy Code
public class MyVector<T>
{
  public T X { get; set; }
  public T Y { get; set; }

  // Doesn't work:
  public void AddVector<T>(MyVector<T> v)
  {
    X = X + v.X;
    Y = Y + v.Y;
  }
}
This results in a "operator '+=' cannot be applied to operands of type 'T' and 'T'" error! More on workarounds for this later.
Factories
You might see generics used in factories. For example:
Hide   Copy Code
public static T Create<T>() where T : new()
{
  return new T();
}
The above is a very silly thing to do, but if you are writing an Inversion of Control layer, you might be doing some complicated things (like loading assemblies) based on the type the factory needs to create.
Partial Types
Partial types can be used on classes, structs, and interface. In my opinion, partial types were created to separate out tool generated code from manually written code. For example, the Visual Studio form designer generates the code-behind for the UI layout, and to keep this code stable and independent from your manually written code, such as the event handlers, Visual Studio creates two separate files and indicates that the same class is of partial type. For example, let's say we have two separate files:
File 1:
Hide   Copy Code
public partial class MyPartial
{
  public int Foo { get; set; }
}
File 2:
Hide   Copy Code
public partial class MyPartial
{
  public int Bar { get; set; }
}
We can use the class, which has been defined in two separate files:
Hide   Copy Code
public class PartialExample
{
  public MyPartial foobar;

  public PartialExample()
  {
    foobar.Foo = 1;
    foobar.Bar = 2;
  }
}
Do not use partial classes to implement a model-view-controller pattern! Just because you can separate the code into different files, one for the model, one for the view, and one view the controller, does not mean you are implementing the MVC pattern correctly!
The old way of handling tool generated code was typically to put comments in the code like:
Hide   Copy Code
// Begin Tool Generated Code: DO NOT TOUCH
   ... code ...
// End Tool Generated Code
And the tool would place its code between the comments.
Anonymous Methods
Anonymous methods let us define the functionality of a delegate (such as an event) inline rather than as a separate method.
The Old Way
Before anonymous delegates, we would have to write a separate method for the delegate implementation:
Hide   Copy Code
public class Holloween
{
  public event EventHandler ScareMe;

  public void OldBoo()
  {
    ScareMe+=new EventHandler(DoIt);
  }

  public void Boo()
  {
    ScareMe(this, EventArgs.Empty);
  }

  public void DoIt(object sender, EventArgs args)
  {
    Console.WriteLine("Boo!");
  }
}
The New Way
With anonymous methods, we can implement the behavior inline:
Hide   Copy Code
public void NewBoo()
{
  ScareMe += delegate(object sender, EventArgs args) { Console.WriteLine("Boo!"); };
}
Async Tasks
We can do the same thing with the Thread class:
Hide   Copy Code
public void AsyncBoo()
{
  new Thread(delegate() { Console.WriteLine("Boo!"); }).Start();
}
Note that we cast the method as a "delegate()"--note the '()'--because there are two delegate forms and we have to specify the parameterless delegate form.
Updating the UI
My favorite example is calling the main application thread from a worker thread to update a UI component:
Hide   Copy Code
/// <summary>
/// Called from some async process:
/// </summary>
public void ApplicationThreadBoo()
{
  myForm.Invoke((MethodInvoker)delegate { textBox.Text = "Boo"; });
}
Iterators
Iterators reduce the amount of code we have to write to iterate over a custom collection.
The Old Way
Previous to C# 2.0, we had to implement the IEnumerator interface, supplying the Current, MoveNext, and Reset operations manually:
Hide   Shrink http://www.codeproject.com/images/arrow-up-16.png  Copy Code
public class DaysOfWeekOld : IEnumerable
{
  protected string[] days = new string[] { "Monday", "Tuesday", "Wednesday", "Thursday",
                                             "Friday", "Saturday", "Sunday" };
       
  public int Count { get { return days.Length; } }
  public string this[int idx] { get { return days[idx]; } }

  public IEnumerator GetEnumerator()
  {
    return new DaysOfWeekEnumerator(this);
  }
}

public class DaysOfWeekEnumerator : IEnumerator
{
  protected DaysOfWeekOld dow;
  protected int pos = -1;

  public DaysOfWeekEnumerator(DaysOfWeekOld dow)
  {
    this.dow = dow;
  }

  public object Current
  {
    get { return dow[pos]; }
  }

  public bool MoveNext()
  {
    ++pos;

    return (pos < dow.Count);
  }

  public void Reset()
  {
    pos = -1;
  }
}
The New Way
In the new approach, we can use the yield keyword to iterate through the collection:
Hide   Copy Code
public class DaysOfWeekNew : IEnumerable
{
  protected string[] days = new string[] { "Monday", "Tuesday", "Wednesday", "Thursday",
                                            "Friday", "Saturday", "Sunday" };

  public IEnumerator GetEnumerator()
  {
    for (int i = 0; i < days.Length; i++)
    {
      yield return days[i];
    }
  }
}
This is much more readable and also ensures that we don't access elements in the collection beyond the number of items in the collection.
We can also implement a generic enumerator, which provides a type safe iterator, but requires us to implement both generic and non-generic GetEnumerator method:
Hide   Copy Code
public class DaysOfWeekNewGeneric : IEnumerable<string>
{
  protected string[] days = new string[] { "Monday", "Tuesday", "Wednesday", "Thursday",
                                            "Friday", "Saturday", "Sunday" };

  IEnumerator IEnumerable.GetEnumerator()
  {
    return Enumerate();
  }

  public IEnumerator<int> GetEnumerator()
  {
    return Enumerate();
  }

  public IEnumerator<string> Enumerate()
  {
    for (int i = 0; i < days.Length; i++)
    {
      yield return days[i];
    }
  }
}
So, for example, in the non-generic version, I could write:
Hide   Copy Code
DaysOfWeekNew dow2 = new DaysOfWeekNew();

foreach (string day in dow2)
{
  Console.WriteLine(day);
}
which is perfectly valid, but I could also write:
Hide   Copy Code
DaysOfWeekNew dow2 = new DaysOfWeekNew();

foreach (int day in dow2)
{
  Console.WriteLine(day);
}
The error in casting from a string to an integer is caught at runtime, not compile time. Using a generic IEnumerable<T>, an improper cast is caught at compile time and also by the IDE:
Hide   Copy Code
DaysOfWeekNewGeneric dow3 = new DaysOfWeekNewGeneric();

foreach (int day in dow3)
{
  Console.WriteLine(day);
}
The above code is invalid and generates the compiler error:
"error CS0030: Cannot convert type 'string' to 'int'"
Thus, the implementation of generic iterators in C# 2.0 increases readability and type safety when using iterators.
Nullable Types
Nullable types allow a value type to take on an additional "value", being "null". I've found this primarily useful when working with data tables. For example:
Hide   Shrink http://www.codeproject.com/images/arrow-up-16.png  Copy Code
public class Record
{
  public int ID { get; set; }
  public string Name { get; set; }
  public int? ParentID { get; set; }
}

public class NullableTypes
{
  protected DataTable people;

  public NullableTypes()
  {
    people = new DataTable();

    // Note that I am mixing a C# 3.0 feature here, Object Initializers,
    // with regards to how AllowDBNull is initialized. I'm doing because I think
    // the example is more readable, even though not C# 2.0 compilable.

    people.Columns.Add(new DataColumn("ID", typeof(int)) {AllowDBNull=false});
    people.Columns.Add(new DataColumn("Name", typeof(string)) { AllowDBNull = false });
    people.Columns.Add(new DataColumn("ParentID", typeof(int)) { AllowDBNull = true });

    DataRow row = people.NewRow();
    row["ID"] = 1;
    row["Name"] = "Marc";
    row["ParentID"] = DBNull.Value; // Marc does not have a parent!
    people.Rows.Add(row);
  }

  public Record GetRecord(int idx)
  {
    return new Record()
    {
      ID = people.Rows[idx].Field<int>("ID"),
      Name = people.Rows[idx].Field<string>("Name"),
      ParentID = people.Rows[idx].Field<int?>("ParentID"),
    };
  }
}
In the above example, the Field extension method (I'll discuss extension methods later) converts DBNull.Value automatically to a "null", which in this schema is a valid foreign key value.
You will also see nullable types used in various third party frameworks to represent "no value." For example, in the DevExpress framework, a checkbox can be set to false, true, or no value. The reason for this is again to support mapping a control directly to a structure that backs a table with nullable fields. That said, I think you would most likely see nullable types in ORM implementations.
Private Setters (properties)
A private setter exposes a property as read-only, which is different from designating the property as readonly. With a field designated as readonly, it can only be initialized during construction or in the variable initializer. With a private setter, the property can be exposed as readonly to the outside world the class implementing the property can still write to it:
Hide   Shrink http://www.codeproject.com/images/arrow-up-16.png  Copy Code
public class PrivateSetter
{
  public int readable;
  public readonly int readable2;

  public int Readable
  {
    get { return readable; }
    // Accessible only by this class.
    private set { readable = value; }
  }

  public int Readable2
  {
    get { return readable2; }
    // what would the setter do here?
  }

  public PrivateSetter()
  {
    // readonly fields can be initialized in the constructor.
    readable2 = 20;
  }

  public void Update()
  {
    // Allowed:
    Readable = 10;
    // Not allowed:
    // readable2 = 30;
  }
}
Contrast the above implementation with C# 3.0's auto-implemented properties, which I discuss below.
Method Group Conversions (delegates)
I must admit to a "what the heck is this?" experience for this feature. First (for my education) a "method group" is a set of methods of the same name. In other words, a method with multiple overloads. This post was very helpful. I stumbled across this post that explained method group conversion with delegates. This also appears to have to do with covariance and contravariance, features of C# 4.0. Read more here. But let's try the basic concept, which is to assign a method to a delegate without having to use "new" (even though behind the scenes, that's apparently what the IL is emitting).
The Old Way
Hide   Copy Code
public class MethodGroupConversion
{
  public delegate string ChangeString(string str);
  public ChangeString StringOperation;

  public MethodGroupConversion()
  {
    StringOperation = new ChangeString(AddSpaces);
  }

  public string Go(string str)
  {
    return StringOperation(str);
  }

  protected string AddSpaces(string str)
  {
    return str + " ";
  }
}
The New Way
We replace the constructor with a more straightforward assignment:
Hide   Copy Code
public MethodGroupConversion()
{
  StringOperation = AddSpaces;
}
OK, that seems simple enough.
C# 3.0 Features
Implicitly Typed Local Variables
The "var" keyword is a new feature of C# 3.0. Using the "var" keyword, you are relying on the compiler to infer the variable type rather than explicitly defining it. So, for example, instead of:
Hide   Copy Code
public void Example1()
{
  // old:
  Dictionary<string, int> explicitDict = new Dictionary<string, int>();

  // new:
  var implicitDict = new Dictionary<string, int>();
}
While it seems like syntactical sugar, the real strength of implicit types is its use in conjunction with anonymous types (see below.)
Restrictions
Note the phrase "local variables" in the heading for this section. Implicitly typed variables cannot be passed to other methods as parameters nor returned by methods. As Richard Deeming commented below, what I mean by this is that you cannot specify var as a parameter or return type, but you can call a method with an implicit type of the method's parameter is an explicit type, and similarly (and more obviously) with return parameters -- an explicit return type can be assigned to a var.
Object and Collection Initializers
The Old Way
Previously, to initialize property values from outside of the class, we would have to write either use a constructor:
Hide   Copy Code
public Record(int id, string name, int? parentID)
{
  ID = id;
  Name = name;
  ParentID = parentID;
}
...
new Record(1, "Marc", null);
or initialize the properties separately:
Hide   Copy Code
Record rec=new Record();
rec.ID = 1;
rec.Name = "Marc";
rec.ParentID = null;
The New Way
In its explicit implementation, this simply allow us to initialize properties and collections when we create the object. We've already seen examples in the code above:
Hide   Copy Code
Record r = new Record() {ID = 1, Name = "Marc", ParentID = 3};
More interestingly is how this feature is used to initialize anonymous types (see below) especially with LINQ.
Initializing Collections
Similarly, a collection can be initialized inline:
Hide   Copy Code
List<Record> records = new List<Record>()
{
  new Record(1, "Marc", null),
  new Record(2, "Ian", 1),
};
Auto-Implemented Properties
In the C# 2.0 section, I described the private setter for properties. Let's look at the same implementation using auto-implemented properties:
Hide   Copy Code
public class AutoImplement
{
  public int Readable { get; private set; }
  public int Readable2 { get { return 20; } }

  public void Update()
  {
    // Allowed:
    Readable = 10;
    // Not allowed:
    // Readable2 = 30;
  }
}
The code is a lot cleaner, but the disadvantage is that, for properties that need to fire events or have some other business logic or validation associated with them, you have to go back to the old way of implementing the backing field manually. One proposed solution to firing property change events for auto-implemented properties is to use AOP techniques, as written up by Tamir Khason's Code Project technical blog.
Anonymous Types
Anonymous types lets us create "structures" without defining a backing class or struct, and rely on implicit types (vars) and object initializers. For example, if we have a collection of "Record" objects, we can return a subset of the properties in this LINQ statement:
Hide   Copy Code
public void Example()
{
  List<Record> records = new List<Record>();
    {
      new Record(1, "Marc", null),
      new Record(2, "Ian", 1),
    };

  var idAndName = from r in records select new { r.ID, r.Name };
}
Here we see how several features come into play at once:
LINQ
Implicit types
Object initialization
Anonymous types
If we run the debugger and inspect "idAndName", we'll see that it has a value:
Hide   Copy Code
{System.Linq.Enumerable.WhereSelectListIterator<CSharpComparison.Record,
          <>f__AnonymousType0<int,string>>}
and (ready for it?) the type:
Hide   Copy Code
System.Collections.Generic.IEnumerable<<>f__AnonymousType0<int,string>>
   {System.Linq.Enumerable.WhereSelectListIterator<CSharpComparison.Record,
   <>f__AnonymousType0<int,string>>}
Imagine having to explicitly state that type name. We can see advantages of implicit types, especially in conjunction with anonymous types.
Extension Methods
Extension methods are a mechanism for extending the behavior of a class external to its implementation. For example, the String class is sealed, so we can't inherit from it, but there's a lot of useful functions that the String class doesn't provide. For example, working with Graphviz, I often need to put quotes around the object name.
Before Extension Methods
Before extension methods, I would probably end up writing something like this:
Hide   Copy Code
string graphVizObjectName = "\"" + name +"\"";
Not very readable, re-usable, or bug proof (what if name is null?)
With Extension Methods
With extension methods, I can write an extension:
Hide   Copy Code
public static class StringHelpersExtensions
{
  public static string Quote(this String src)
  {
    return "\"" + src + "\"";
  }
}
(OK, that part looks pretty much the same) - but I would use it like this:
Hide   Copy Code
string graphVizObjectName = name.Quote();
Not only is this more readable, but it's also more reusable, as the behavior is now exposed everywhere.
Query Expressions
Query expressions seems to be a synonymous phrase for LINQ (Language-Integrated Query). Humorously, the Microsoft website I just referenced has the header "LINQ Query Expressions." Redundant!
Query expressions are written in a declarative syntax and provide the ability to query an enumerable or "queriable" object using complex filters, ordering, grouping, and joins, very similar in fact to how you would work with SQL and relational data.
As I wrote about above with regards to anonymous types, here's a LINQ statement:
Hide   Copy Code
var idAndName = from r in records select new { r.ID, r.Name };
LINQ expressions can get really complex and working with .NET classes and LINQ relies heavily on extension methods. LINQ is far to large a topic (there are whole books on the subject) and is definitely outside the purview of this article!
Left and Right Joins
Joins by default in LINQ are inner joins. I was perusing recently for how to do left and right joins and came across this useful post.
Lambda Expressions
Lambda expressions are a fundamental part of working with LINQ. You usually will not find LINQ without lambda expressions. A lambda expression is an anonymous method (ah ha!) that "can contain expressions and statements, and can be used to create delegates or expression tree types...The left side of the lambda operator specifies the input parameters (if any) and the right side holds the expression or statement block." (taken from the website referenced above.)
In LINQ, I could write:
Hide   Copy Code
var idAndName = from r in records
  where r.Name=="Marc"
  select new { r.ID, r.Name };
and I'd get the names of people with the name "Marc". With a lambda expression and the extension methods provided for a generic List, I can write:
Hide   Copy Code
var idAndName2 = records.All(r => r.Name == "Marc");
LINQ and lambda expressions can be combined. For example, here's some code from an article I recently wrote:
Hide   Copy Code
var unassoc = from et in dataSet.Tables["EntityType"].AsEnumerable()
  where !(dataSet.Tables["RelationshipType"].AsEnumerable().Any(
     rt =>
       (rt.Field<int>("EntityATypeID") == assocToAllEntity.ID) &&
       (rt.Field<int>("EntityBTypeID") == et.Field<int>("ID"))))
  select new { Name = et.Field<string>("Name"), ID = et.Field<int>("ID") };
LINQ, lambda expressions, anonymous types, implicit types, collection initializers and object initializers all work together to more concisely express the intent of the code. Previously, we would have to do this with nested for loops and lots of "if" statements.
Expression Trees
Let's revisit the MyVector example. With expression trees, we can however compile type-specific code at runtime that allows us to work with generic numeric types in a performance efficient manner (compare with "dynamic" in C# 4.0, discussed below).
Hide   Copy Code
public class MyVector<T>
{
  private static readonly Func<T, T, T> Add;

  // Create and cache adder delegate in the static constructor.
  // Will throw a TypeInitializationException if you can't add Ts or if T + T != T
  static MyVector()
  {
    var firstOperand = Expression.Parameter(typeof(T), "x");
    var secondOperand = Expression.Parameter(typeof(T), "y");
    var body = Expression.Add(firstOperand, secondOperand);
    Add = Expression.Lambda<Func<T, T, T>>(body, firstOperand, secondOperand).Compile();
  }

  public T X { get; set; }
  public T Y { get; set; }

  public MyVector(T x, T y)
  {
    X = x;
    Y = y;
  }

  public MyVector<T> AddVector(MyVector<T> v)
  {
    return new MyVector<T>(Add(X, v.X), Add(Y, v.Y));
  }
}
The above example comes from a post on StackOverflow.
C# 4.0 Features
Dynamic Binding
Let's revisit the MyVector implementation again. With the dynamic keyword, we can defer the operation to runtime when we know the type.
Hide   Copy Code
public class MyVector<T>
{
  public MyVector() {}

  public MyVector<T> AddVector(MyVector<T> v)
  {
    return new MyVector<T>()
    {
      X = (dynamic)X + v.X,
      Y = (dynamic)Y + v.Y,
    };
  }
}
Because this uses method invocation and reflection, it is very performance inefficient. According to MSDN referenced in the link above: The dynamic type simplifies access to COM APIs such as the Office Automation APIs, and also to dynamic APIs such as IronPython libraries, and to the HTML Document Object Model (DOM).
Named and Optional Arguments
As with the dynamic keyword, the primary purpose of this is to facilitate calls to COM. From the MSDN link referenced above:
Named arguments enable you to specify an argument for a particular parameter by associating the argument with the parameter's name rather than with the parameter's position in the parameter list. Optional arguments enable you to omit arguments for some parameters. Both techniques can be used with methods, indexers, constructors, and delegates.
When you use named and optional arguments, the arguments are evaluated in the order in which they appear in the argument list, not the parameter list.
Named and optional parameters, when used together, enable you to supply arguments for only a few parameters from a list of optional parameters. This capability greatly facilitates calls to COM interfaces such as the Microsoft Office Automation APIs.
I have never used named arguments and I rarely need to use optional arguments, though I remember when I moved from C++ to C#, kicking and screaming that optional arguments weren't part of the C# language specification!
Example
We can use named an optional arguments to specifically indicate which arguments we are supplying to a method:
Hide   Copy Code
public class NamedAndOptionalArgs
{
  public void Foo()
  {
    Bar(a: 1, c: 5);
  }

  public void Bar(int a, int b=1, int c=2)
  {
    // do something.
  }
}
As this example illustrates, we can specify the value for a, use the default value for b, and specify a non-default value for c. While I find named arguments to be of limited use in regular C# programming, optional arguments are definitely a nice thing to have.
Optional Arguments, The Old Way
Previously, we would have to write something like this:
Hide   Copy Code
public void OldWay()
{
  BarOld(1);
  BarOld(1, 2);
}

public void BarOld(int a)
{
  // 5 being the default value.
  BarOld(a, 5);
}

public void BarOld(int a, int b)
{
  // do something.
}
The syntax available in C# 4.0 is much cleaner.
Generic Covariance and Contravariance
What do these words even mean? From Wikipedia:
covariant: converting from wider to smaller (like double to float)
contravariant: converting from narrower to wider (like float to double)
First, let's look at co-contravariance with delegates, which has been around since Visual Studio 2005.
Delegates
Not wanting to restate the excellent "read more" example referenced above, I will simply state that covariance allows us to assign a method returning a sub-class type to the delegate defined as returning a base class type. This is an example of going from something wider (the base class) to something smaller (the inherited class) in terms of derivation.
Contravariance, with regards to delegates, lets us create a method in which the argument is the base class and the caller is using a sub-class (going from narrower to wider). For example, I remember being annoyed that I could not consume an event having a MouseEventArgs argument with a generic event handler having an EventArgs argument. This example of contravariance has been around since VS2005, but it makes for a useful example of the concept.
Generics
Again, the MSDN page referenced is an excellent read (in my opinion) on co-contravariance with generics. To briefly summarize: as with delegates, covariance allows a generic return type to be covariant, being able specify a "wide" return type (more general) but able to use a "smaller" (more specialized) return type. So, for example, the generic interfaces for enumeration support covariance.
Conversely, contravariance lets us go from something narrow (more specialized, a derived class) to something wider (more general, a base class), and is used as parameters in generic interfaces such as IComparer.
But How Do I Define My Own?
To specify a covariant return parameter, we use the "out" keyword in the generic type. To specify a contravariant method parameter, we use the "in" keyword in the generic type. For example (read more here):
Hide   Copy Code
public delegate T2 MyFunc<in T1,out T2>(T1 t1);
T2 is the covariant return type and T1 is the contravariant method parameter



Value Type

Value type variables can be assigned a value directly. They are derived from the classSystem.ValueType.
The value types directly contain data. Some examples are int, char, and float, which stores numbers, alphabets, and floating point numbers, respectively. When you declare an inttype, the system allocates memory to store the value.
The following table lists the available value types in C# 2010:
Type
Represents
Range
Default Value
bool
Boolean value
True or False
False
byte
8-bit unsigned integer
0 to 255
0
char
16-bit Unicode character
U +0000 to U +ffff
'\0'
decimal
128-bit precise decimal values with 28-29 significant digits
(-7.9 x 1028 to 7.9 x 1028) / 100 to 28
0.0M
double
64-bit double-precision floating point type
(+/-)5.0 x 10-324 to (+/-)1.7 x 10308
0.0D
float
32-bit single-precision floating point type
-3.4 x 1038 to + 3.4 x 1038
0.0F
int
32-bit signed integer type
-2,147,483,648 to 2,147,483,647
0
long
64-bit signed integer type
-923,372,036,854,775,808 to 9,223,372,036,854,775,807
0L
sbyte
8-bit signed integer type
-128 to 127
0
short
16-bit signed integer type
-32,768 to 32,767
0
uint
32-bit unsigned integer type
0 to 4,294,967,295
0
ulong
64-bit unsigned integer type
0 to 18,446,744,073,709,551,615
0
ushort
16-bit unsigned integer type
0 to 65,535
0
To get the exact size of a type or a variable on a particular platform, you can use the sizeofmethod. The expression sizeof(type) yields the storage size of the object or type in bytes. Following is an example to get the size of int type on any machine:
using System;
namespace DataTypeApplication
{
   class Program 
   {
      static void Main(string[] args)
      {
         Console.WriteLine("Size of int: {0}", sizeof(int));
         Console.ReadLine();
      }
   }
}
When the above code is compiled and executed, it produces the following result:
Size of int: 4

Reference Type

The reference types do not contain the actual data stored in a variable, but they contain a reference to the variables.
In other words, they refer to a memory location. Using multiple variables, the reference types can refer to a memory location. If the data in the memory location is changed by one of the variables, the other variable automatically reflects this change in value. Example ofbuilt-in reference types are: object, dynamic, and string.

Object Type

The Object Type is the ultimate base class for all data types in C# Common Type System (CTS). Object is an alias for System.Object class. The object types can be assigned values of any other types, value types, reference types, predefined or user-defined types. However, before assigning values, it needs type conversion.
When a value type is converted to object type, it is called boxing and on the other hand, when an object type is converted to a value type, it is called unboxing.
object obj;
obj = 100; // this is boxing

Dynamic Type

You can store any type of value in the dynamic data type variable. Type checking for these types of variables takes place at run-time.
Syntax for declaring a dynamic type is:
dynamic <variable_name> = value;
For example,
dynamic d = 20;
Dynamic types are similar to object types except that type checking for object type variables takes place at compile time, whereas that for the dynamic type variables takes place at run time.

String Type

The String Type allows you to assign any string values to a variable. The string type is an alias for the System.String class. It is derived from object type. The value for a string type can be assigned using string literals in two forms: quoted and @quoted.
For example,
String str = "Tutorials Point";
A @quoted string literal looks as follows:
@"Tutorials Point";
The user-defined reference types are: class, interface, or delegate. We will discuss these types in later chapter.

Pointer Type

Pointer type variables store the memory address of another type. Pointers in C# have the same capabilities as the pointers in C or C++.
Syntax for declaring a pointer type is:
type* identifier;
For example,
char* cptr;
int* iptr;
We will discuss pointer types in the chapter 'Unsafe Codes'.
Boxing is the process of converting a value type to the type object or to any interface type implemented by this value type. When the CLR boxes a value type, it wraps the value inside a System.Object and stores it on the managed heap. Unboxing extracts the value type from the object. Boxing is implicit; unboxing is explicit. The concept of boxing and unboxing underlies the C# unified view of the type system in which a value of any type can be treated as an object.
In the following example, the integer variable i is boxed and assigned to object o.
C#
int i = 123;
// The following line boxes i. 
object o = i; 
The object o can then be unboxed and assigned to integer variable i:
C#
o = 123;
i = (int)o;  // unboxing

Console Application
The Console class contains the following methods for reading console input and writing console output:
·         The overloads of the ReadKey method read an individual character.
·         The ReadLine method reads an entire line of input.
·         The Write method overloads convert an instance of a value type, an array of characters, or a set of objects to a formatted or unformatted string, and then write that string to the console.
·         A parallel set of WriteLine method overloads output the same string as the Write overloads but also add a line termination string.
The Console class also contains methods and properties to perform the following operations:
·         Get or set the size of the screen buffer. The BufferHeight and BufferWidth properties let you get or set the buffer height and width, respectively, and the SetBufferSize method lets you set the buffer size in a single method call.
·         Get or set the size of the console window. The WindowHeight and WindowWidth properties let you get or set the window height and width, respectively, and the SetWindowSize method lets you set the window size in a single method call.
·         Get or set the size of the cursor. The CursorSize property specifies the height of the cursor in a character cell.
·         Get or set the position of the console window relative to the screen buffer. The WindowTop and WindowLeft properties let you get or set the top row and leftmost column of the screen buffer that appears in the console window, and the SetWindowPosition method lets you set these values in a single method call.
·         Get or set the position of the cursor by getting or setting the CursorTop and CursorLeft properties, or set the position of the cursor by calling the SetCursorPosition method.
·         Move or clear data in the screen buffer by calling the MoveBufferArea or Clear method.
·         Get or set the foreground and background colors by using the ForegroundColor and BackgroundColor properties, or reset the background and foreground to their default colors by calling the ResetColor method.
·         Play the sound of a beep through the console speaker by calling the Beep method.

Examples


The following example demonstrates how to read data from, and write data to, the standard input and output streams. Note that these streams can be redirected by using the SetIn and SetOut methods.
C#
 
using System;
 
public class Example {
    public static void Main() 
    {
        Console.Write("Hello ");
        Console.WriteLine("World!");
        Console.Write("Enter your name: ");
        String name = Console.ReadLine();
        Console.Write("Good day, ");
        Console.Write(name);
        Console.WriteLine("!");
    }
}

Conditional and Looping Control Statements

C# Control Statements

In this lesson, we'll be covering the major control statements which are for, while, do while,switch and if. With these under your belt, you are well on the way to becoming a seasoned programmer.

The If and else-If Statement

Programs need to make decisions. Should this statement be executed or that one? Are these parameters correct and so on. This is done using the if statement. The syntax is pretty easy.

if ( conditional expression )
statement;

This can be extended with else.

if ( conditional expression )
{
statement1;
else
statement2;
}

This can be extended with else-if.

if ( conditional expression )
{
statement1;
else if ( conditional expression )
statement2;
}

So if the expression is true, statement1 is executed, otherwise statement2 is executed.

The For Loop

This is the syntax of a for statement.
for ( initial statement; conditional expression; loop statement ) main statement;
Note This is the one place where there is no need to put brackets around a conditional expression.

This code sums the array and prints the total of an array with 10 values in it.
int value =0;
for (index=0 ;index < 10;index++ )
value += numbers[ index ];
printf("Value = %i",value) ;

Break and Continue

These two words apply to all the loop types, i.e. while, for and do. Each behave differently.
Break
Break forces a loop to exit immediately. Here's an example:
int markerpos=-1;
for (index=0 ;index < 10;index++ )
{
if (values[index] ==-999 )
{
markerpos = index;
; break;
}
}
if (markerpos== 999)
printf("-1 Not located in array";
else
printf("-1 Found at index %i\n\r",markerpos) ;
That's a more complicated example. It searches the 10 element array values looking for a 999 value. The variable markerpos holds the position if a 999 is found. It is initialized to -1 and after the search this value is examined to see if a 999 was found.
Continue
This does the opposite of break; Instead of terminating the loop, it immediately loops again, skipping the rest of the code. So lets sum that integer array again, but this time we'll leave out elements with an index of 4 and 5.
int value =0;
for (index=0 ;index < 10;index++ )
{
if (index==4 || index==5)
continue;
value += numbers[index];
}
printf("Value = %i",value) ;
You probably won't use continue very often but it's useful on the odd occasion.

While and Do While

First is the while statement which has this syntax.
while (expression) statement
As long as the expression is true, the statement is executed.
int total =0;
int index =0;
while (total < 100)
{
index++;
total+=index;
printf("Sum of 1 to %i is %i",index,total) ;
}

Looping doesn't get much simpler than while. The most important thing to know with while loops is that the control expression is evaluated before the statement is run. If the expression is false, the statement is not run. So a while loop may never execute a statement.
Also because c allows a statement to be an expression it is possible to write complicated code like this
int c=10;
int a =0;
while (c--)
{
printf("Value of a is %i",a++) ;
}
c-- subtracts one from c.
Do While
Less popular than the while statement is the do while statement. This puts the expression at the end.
The syntax looks like this.
do
statement;
while (expression) ;
A while loop might never execute a statement if the expression is false but a do while will always execute the statement at least once.
Here is an example of a do while loop.
int count =0;
int index =9;
do
if (value[ index] ==999)
count++;
index--;
while ( index >= 0) ;
Break and Continue work equally well with for, while and do while loops.

About Switch Statements

When there are many choices, a switch statement may be better than an if. The syntax of a switch statement is:
switch ( expression) {

case a: statement1; break;
case b: statement2;
case d: statement3; break;
default: statement4;

}
Notes: Expression should be an int or a char type. e.g.
switch (character) {

case 'B':
case 'b': statement1; break;
case 'c': statement2;
case 'd': statement3; break;
default: statement4;
}
If the character is 'B' or 'b' then statement1 is executed, but if the character is 'c' then statement2 and statement3 are both executed. With 'd' though, only statement3 is executed. For all other characters statement4 is executed.
When a case matches, all statements from that case on, including those that follow are executed until a break is found. This is known as 'Fall Through'.
switch (value) {
case 3:statement3;
case 2:statement2;
case 1:statement1;
default: break;
}
http://docs.oracle.com/cd/A87860_01/doc/appdev.817/a77069/03_strua.gif


C# provides following types of loop to handle looping requirements. Click the following links to check their detail.
Loop Type
Description
It repeats a statement or a group of statements while a given condition is true. It tests the condition before executing the loop body.
It executes a sequence of statements multiple times and abbreviates the code that manages the loop variable.
It is similar to a while statement, except that it tests the condition at the end of the loop body
You can use one or more loop inside any another while, for or do..while loop.
Array
An array is a collection of same type variables which can be accessed using numeric index. The numeric index is written in square brackets after the array name.

Contents
·         Characteristics
·         Single Dimension Array
·         Iterating Through Single Dimension Array
·         2D Arrays
·         3D Arrays ...
·         Bounds of Multi Dimensional Arrays
·         Jagged Arrays
·         Mixed Arrays

Following is the declaration of a single dimension array:
Hide   Copy Code
int[ ] roll = new int[8];  
Arrays-dontumindit/roll.png
Characteristics
The numeric index is zero based. It goes from 0 to n-1 where n is size of array (total number of elements in array).
On declaration, default value of numeric type arrays is set to 0, and reference types are set to null.
Arrays are stored in continuous memory locations as shown in the figure.
In C#, arrays are objects, and they have certain properties like Length, which can be used by using (.) and property name. All arrays are derived from abstract class arrays so many built-in methods can be called.
Hide   Copy Code
//Rank propety Return number of dimensions 
int[ ] single = new int[4] { 1, 2, 3, 4 }; 
int dimension = single.Rank;
Single Dimension Arrays
It is the simplest form of array, it's kind of a row with n columns where each column is accessed with the zero based index. The above two code examples show single dimension arrays.
In C#, declaration of array is a bit different from C or C++. Here square brackets are placed after type name, then array-name, keyword new and then type with square brackets containing size of array.
Hide   Copy Code
Type[ ] arrayname = new Type[size];
The following code initializes a single dimension integer array of size 5. It contains 5 elements which can be accessed by arr[0] to arr[4].
Hide   Copy Code
//Integer Array declaration
int[ ] arr = new int[5]; 
Character type arrays are declared as follows:
Hide   Copy Code
//Character type array
char[ ] name = new char[10];
Arrays-dontumindit/NAME.jpg
In the same way, string type arrays are declared:
Hide   Copy Code
//String array declaration
string[ ] days = new string[7];
Arrays-dontumindit/DAYS.jpg
There are many ways to assign values to array. Array can be initialized in declaration line by placing the values between curly braces { } in comma separated fashion. Characters are placed in single quotes and strings are placed in double quotes.
Hide   Copy Code
//Integer Array Initialization    
int[ ] arr = new int[5] { 1, 2, 3, 4, 5 };  
//Character Array Initialization    
char[ ] name = new char[10] { 'i', ' ', 'a', 'm', ' ', 'f', 'i', 'n', 'e', '.' };  
//String Array Initialization 
string[ ] days = new string[7] { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" };
While initializing the array, size of array may be omitted. Then size of array will be calculated number of elements written in curly braces.
One other way of declaring, initializing array is:
Hide   Copy Code
//Integer Array Declaration, Initialization
int[ ] arr;arr = new int[5] { 1, 2, 3, 4, 5 };
Following way of assigning values to array will cause Error.
Hide   Copy Code
//Wrong way of writing
int[ ] arr = new int[5];
arr = { 1, 2, 3, 4, 5 };
Iterating Through Single Dimension Array
Since in C#, arrays are objects and they retain certain built in properties. Length property returns total number of elements in array. Right now we are dealing with single dimension, so total number of elements is equal to size of array.
Hide   Copy Code
for (int i = 0; i < arr.Length; i++)
{
    Console.WriteLine(i);
}Console.ReadLine();
Arrays-dontumindit/array4.gif
Multi Dimensional Arrays 

2D Arrays

Arrays can be multidimensional. The most widely used are two dimensional arrays, often Matrices form 2D arrays. In 2D array, 2 zero based index are used to access a particular value in the array.
Hide   Copy Code
//Integer 2D Array
int[,] matrix = new int[10, 10];
//Accessing Value
int val = matrix[5, 7];
Arrays-dontumindit/array5.gif
Value of element stored in 5th Row, 7th Column i.e., 58, will be assigned to variable val. Rows and Columns have zero based index. Total number of values which can be stored in 2D array is equal to product of rows and columns. For the above case, it is 100.
Single dimension array is a single Row with columns >0. 2D arrays have more than one Row, thus form a table.
Arrays-dontumindit/array6.gif
Accessing the element stored in 3rd row, 4th column in balances table.
To initialize 2D array, each row values are placed in curly braces as in the case of a single dimensional array and then these set of curly braces for all rows are placed in another set of curly braces in the same fashion.
Hide   Copy Code
//2D Array Initializtion
int[,] arr_2d = new int[3, 2] { { 1, 2 }, { 3, 4 }, { 5, 6 } }; 
//Initializing 2Dimensional Array
char[,] day = new char[2, 3] { { 'o', 'n', 'e' }, { 't', 'w', 'o' } };
In the above piece of code, there are 3 rows, 2 columns, thus total number of elements is 2 x 3 = 6. It's hard to initialize 2D array shown in the 1st figure, where it has 10 rows and 10 columns. Loops can be used to assign values to each location.
Hide   Copy Code
//Assigning Values to matrix[10,10] array
for (int i = 0; i < 10; i++)
{
    for (int j = 0; j < 10; j++)
    {
        matrix[i, j] = i * 10 + j + 1;                    
    }                
}
In case of multidimensional arrays, knowing number of dimensions is sometimes necessary to have more grip over the array. Rank property returns number of dimensions of the array.
Hide   Copy Code
//Getting Number of dimensions of array
int dim = matrix.Rank;
The GetUpperBound function returns the upper bound of the array in a particular dimension.
Hide   Copy Code
for (int i = 0; i <= matrix.GetUpperBound(0);i++)
{
    for (int j = 0; j <= matrix.GetUpperBound(1); j++)
    {
        Console.Write(matrix[i, j].ToString() + "\t");
    }
    Console.WriteLine();
}
Output of the above piece of code is as follows:
Arrays-dontumindit/array7.gif
GetLowerBound method gets the lower bound of the array in a particular dimension. The following figure shows the difference between length, upper bound and lower bound.
Arrays-dontumindit/array8.gif

3D Arrays 


We can have more than two dimensions for arrays as well. For three dimensional array, we need three indexes to access each element in array. Example of 3 dimensional array can be a point in space. Consider a block of small bricks, as shown in figure below, to address each small brick, there is one index for row, one for column and one for depth.
Arrays-dontumindit/array9.gif
Hide   Copy Code
//Block code 3D array
int[, ,] block_3d = new int[2, 3, 4];


4D Arrays


Example of 4 dimensional array can be taken as one second in a week, there are 60 seconds in one hour, 60 mins in one hour, 24 hours a day and 7 day a week.
Arrays-dontumindit/array10.gif
Hide   Copy Code
//Week 4D array
int[, , ,] week = new int[7, 24, 60, 60];


Arrays-dontumindit/array11.gif
Jagged Arrays 
Array of arrays are called jagged arrays.
Arrays-dontumindit/array12.gif
The statement might be confusing but consider the example of saving marks of few students who are studying different number of subjects.
Hide   Copy Code
Student-1 marks 65, 60, 76
Student-2 marks 78, 92, 68, 90, 55
Student-3 marks 45, 59, 88, 72
If we use 2 Dimensional array to store the above marks, then an array of 3 rows and 5 columns is needed. The extra info needs to be added at locations for which marks don't exist.
65
60
76
0
0
78
92
68
90
55
45
53
88
72
0
Jagged arrays come in handy in such situations. Jagged arrays may have different sizes and dimensions. For this situation, we need one single dimension array with three elements, and each of its elements is a single dimension array with length 3, 5, 4 respectively.
Hide   Copy Code
//Jagged arrays
int[ ][ ] student = new int[3][ ];
In the above piece of code, two sets of square brackets are used. Now each element of Jagged array needs to be assigned to a single dimension array.
Hide   Copy Code
//Declaring Each Element of Jagged Array
student[0] = new int[3];
student[1] = new int[5];
student[2] = new int[4];
Values can also be assigned just like single dimension array by placing after square brackets.
Hide   Copy Code
//Initializing Each Element of Jagged Array
student[0] = new int[3] { 65, 60, 76 };
student[1] = new int[5] { 78, 92, 68, 90, 55 };
         student[2] = new int[4] { 45, 59, 88, 72 };
A short way of doing this is:
Hide   Copy Code
//Jagged arrays
int[ ][ ] student = new int[3][ ]
{new int[3] { 65, 60, 76 },new int[5] { 78, 92, 68, 90, 55 },
         new int[4] { 45, 59, 88, 72 }};
Jagged arrays are reference type, thus they are initialized to null. To access elements in jagged array in student example, 2 indexes are used.
//Accessing elements in Jagged Array
student[2][2] = 80;for (int i = 0; i < student.Length; i++)
{
    for (int j = 0; j < student[i].Length; j++)
    {
        Console.Write(student[i][j]);
        Console.Write('\t');
    }
    Console.WriteLine();
}
Arrays-dontumindit/array13.gif
Mixed Arrays
Combination of jagged and multidimensional arrays is known as mixed arrays. In case of multidimensional arrays of different sizes, mixed arrays are used. Consider there are three tables, each with different number or rows and columns.
Hide   Copy Code
Table-1 3 rows, 5 columns
Table-2 4 rows, 3 columns
Table-2 6 rows, 4 columns
Hide   Copy Code
//Mixed Arrays int [ ][,]mixed=new int[3][ ]
 {
     new int[3,5],
     new int[4,3],
     new int[6,4]
 };

C# Arrays
There are following few important concepts related to array which should be clear to a C# programmer:
Concept
Description
C# supports multidimensional arrays. The simplest form of the multidimensional array is the two-dimensional array.
C# supports multidimensional arrays, which are arrays of arrays.
You can pass to the function a pointer to an array by specifying the array's name without an index.
This is used for passing unknown number of parameters to a function.
Defined in System namespace, it is the base class to all arrays, and provides various properties and methods for working with arrays.


Functions
A function allows you to encapsulate a piece of code and call it from other parts of your code. You may very soon run into a situation where you need to repeat a piece of code, from multiple places, and this is where functions come in. In C#, they are basically declared like this:
<visibility> <return type> <name>(<parameters>)
{
        <function code>
}
To call a function, you simply write its name, an open parenthesis, then parameters, if any, and then a closing parenthesis, like this:
DoStuff();
Here is an example of our DoStuff() function:
public void DoStuff()
{
    Console.WriteLine("I'm doing something...");
}
The first part, public, is the visibility, and is optional. If you don't define any, then the function will be private. More about that later on.
Next is the type to return. It could be any valid type in C#, or as we have done it here, void. A void means that this function returns absolutely nothing. Also, this function takes no parameters, as you can see from the empty set of parentheses, so it's actually just a tad bit boring. Let's change that:
public int AddNumbers(int number1, int number2)
{
    int result = number1 + number2;
    return result;
}
We've changed almost everything. The function now returns an integer, it takes two parameters (both integers), and instead of outputting something, it makes a calculation and then returns the result. This means that we can add two numbers from various places in our code, simply by calling this function, instead of having to write the calculation code each time. While we don't save that much time and effort in this small example, you better believe that you will learn to love functions, the more you use C#. This function is called like this:
int result = AddNumbers(10, 5);
Console.WriteLine(result);
As mentioned, this function actually returns something, and it has to, because we told C# that it's supposed to do so. When declaring anything else than void as a return type, we are forcing our self to return something. You can try removing the return line from the example above, and see the compiler complain:

'AddNumbers(int, int)': not all code paths return a value
Structures
To define a structure, you must use the struct statement. The struct statement defines a new data type, with more than one member for your program.
For example, here is the way you can declare the Book structure:
struct Books
{
   public string title;
   public string author;
   public string subject;
   public int book_id;
}; 
The following program shows the use of the structure:
using System;
struct Books
{
   public string title;
   public string author;
   public string subject;
   public int book_id;
}; 

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

      Books Book1;   /* Declare Book1 of type Book */
      Books Book2;   /* Declare Book2 of type Book */

      /* book 1 specification */
      Book1.title = "C Programming";
      Book1.author = "Nuha Ali";
      Book1.subject = "C Programming Tutorial";
      Book1.book_id = 6495407;

      /* book 2 specification */
      Book2.title = "Telecom Billing";
      Book2.author = "Zara Ali";
      Book2.subject =  "Telecom Billing Tutorial";
      Book2.book_id = 6495700;

      /* print Book1 info */
      Console.WriteLine( "Book 1 title : {0}", Book1.title);
      Console.WriteLine("Book 1 author : {0}", Book1.author);
      Console.WriteLine("Book 1 subject : {0}", Book1.subject);
      Console.WriteLine("Book 1 book_id :{0}", Book1.book_id);

      /* print Book2 info */
      Console.WriteLine("Book 2 title : {0}", Book2.title);
      Console.WriteLine("Book 2 author : {0}", Book2.author);
      Console.WriteLine("Book 2 subject : {0}", Book2.subject);
      Console.WriteLine("Book 2 book_id : {0}", Book2.book_id);      

      Console.ReadKey();

   }
}
When the above code is compiled and executed, it produces the following result:

Book 1 title : C Programming
Book 1 author : Nuha Ali
Book 1 subject : C Programming Tutorial
Book 1 book_id : 6495407
Book 2 title : Telecom Billing
Book 2 author : Zara Ali
Book 2 subject : Telecom Billing Tutorial
Book 2 book_id : 6495700

No comments:

Post a Comment