Dot Net Framework 3.5 From MSDN

You might also like

Download as doc, pdf, or txt
Download as doc, pdf, or txt
You are on page 1of 18

1 .

NET Framework Conceptual Overview


The .NET Framework is an integral Windows component that supports building and running the next generation of
applications and XML Web services. The .NET Framework is designed to fulfill the following objectives:

 To provide a consistent object-oriented programming environment whether object code is stored and
executed locally, executed locally but Internet-distributed, or executed remotely.
 To provide a code-execution environment that minimizes software deployment and versioning conflicts.
 To provide a code-execution environment that promotes safe execution of code, including code created by an
unknown or semi-trusted third party.
 To provide a code-execution environment that eliminates the performance problems of scripted or interpreted
environments.
 To make the developer experience consistent across widely varying types of applications, such as Windows-
based applications and Web-based applications.
 To build all communication on industry standards to ensure that code based on the .NET Framework can
integrate with any other code.

The .NET Framework has two main components: the common language runtime and the .NET Framework class library.
The common language runtime is the foundation of the .NET Framework. You can think of the runtime as an agent
that manages code at execution time, providing core services such as memory management, thread management, and
remoting, while also enforcing strict type safety and other forms of code accuracy that promote security and
robustness. In fact, the concept of code management is a fundamental principle of the runtime. Code that targets the
runtime is known as managed code, while code that does not target the runtime is known as unmanaged code. The
class library, the other main component of the .NET Framework, is a comprehensive, object-oriented collection of
reusable types that you can use to develop applications ranging from traditional command-line or graphical user
interface (GUI) applications to applications based on the latest innovations provided by ASP.NET, such as Web Forms
and XML Web services.

The .NET Framework can be hosted by unmanaged components that load the common language runtime into their
processes and initiate the execution of managed code, thereby creating a software environment that can exploit both
managed and unmanaged features. The .NET Framework not only provides several runtime hosts, but also supports
the development of third-party runtime hosts.

For example, ASP.NET hosts the runtime to provide a scalable, server-side environment for managed code. ASP.NET
works directly with the runtime to enable ASP.NET applications and XML Web services, both of which are discussed
later in this topic.

Internet Explorer is an example of an unmanaged application that hosts the runtime (in the form of a MIME type
extension). Using Internet Explorer to host the runtime enables you to embed managed components or Windows
Forms controls in HTML documents. Hosting the runtime in this way makes managed mobile code (similar to
Microsoft® ActiveX® controls) possible, but with significant improvements that only managed code can offer, such as
semi-trusted execution and isolated file storage.

1.1 Features of the Common Language Runtime

The common language runtime manages memory, thread execution, code execution, code safety verification,
compilation, and other system services. These features are intrinsic to the managed code that runs on the common
language runtime.

With regards to security, managed components are awarded varying degrees of trust, depending on a number of
factors that include their origin (such as the Internet, enterprise network, or local computer). This means that a
managed component might or might not be able to perform file-access operations, registry-access operations, or
other sensitive functions, even if it is being used in the same active application.
The runtime enforces code access security. For example, users can trust that an executable embedded in a Web page
can play an animation on screen or sing a song, but cannot access their personal data, file system, or network. The
security features of the runtime thus enable legitimate Internet-deployed software to be exceptionally feature rich.

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-describing. The various Microsoft and
third-party language compilers generate managed code that conforms to the CTS. This means that managed code can
consume other managed types and instances, while strictly enforcing type fidelity and type safety.

In addition, the managed environment of the runtime eliminates many common software issues. For example, the
runtime automatically handles object layout and manages references to objects, releasing them when they are no
longer being used. This automatic memory management resolves the two most common application errors, memory
leaks and invalid memory references.

The runtime also accelerates developer productivity. For example, programmers can write applications in their
development language of choice, yet take full advantage of the runtime, the class library, and components written in
other languages by other developers. Any compiler vendor who chooses to target the runtime can do so. Language
compilers that target the .NET Framework make the features of the .NET Framework available to existing code written
in that language, greatly easing the migration process for existing applications.

While the runtime is designed for the software of the future, it also supports software of today and yesterday.
Interoperability between managed and unmanaged code enables developers to continue to use necessary COM
components and DLLs.

The runtime is designed to enhance performance. Although the common language runtime provides many standard
runtime services, managed code is never interpreted. A feature called just-in-time (JIT) compiling enables all managed
code to run in the native machine language of the system on which it is executing. Meanwhile, the memory manager
removes the possibilities of fragmented memory and increases memory locality-of-reference to further increase
performance.

Finally, the runtime can be hosted by high-performance, server-side applications, such as Microsoft® SQL Server™ and
Internet Information Services (IIS). This infrastructure enables you to use managed code to write your business logic,
while still enjoying the superior performance of the industry's best enterprise servers that support runtime hosting.

1.2 .NET Framework Class Library

The .NET Framework class library is a collection of reusable types that tightly integrate with the common language
runtime. The class library is object oriented, providing types from which your own managed code can derive
functionality. This not only makes the .NET Framework types easy to use, but also reduces the time associated with
learning new features of the .NET Framework. In addition, third-party components can integrate seamlessly with
classes in the .NET Framework.

For example, the .NET Framework collection classes implement a set of interfaces that you can use to develop your
own collection classes. Your collection classes will blend seamlessly with the classes in the .NET Framework.

As you would expect from an object-oriented class library, the .NET Framework types enable you to accomplish a
range of common programming tasks, including tasks such as string management, data collection, database
connectivity, and file access. In addition to these common tasks, the class library includes types that support a variety
of specialized development scenarios. For example, you can use the .NET Framework to develop the following types of
applications and services:

 Console applications. See Building Console Applications.


 Windows GUI applications (Windows Forms). See Windows Forms.
 Windows Presentation Foundation (WPF) applications. See Introduction to Windows Presentation Foundation.
 ASP.NET applications. See Creating ASP.NET Web Pages.
 Web services. See Creating Web Services in Managed Code.
 Windows services. See Introduction to Windows Service Applications.

.NET Framework architecture

.NET Provides the first additions to the base class libraries to the .NET Framework since version 2.0. The
Framework 3.5 following technologies are introduced in the .NET Framework 3.5:
 Language Integrated Query (LINQ).
 New compilers for C#, Visual Basic, and C++.
 ASP.NET AJAX.

For a complete list of features, see

What's New in the .NET Framework Version 3.5

2 Common Language Runtime Overview


Compilers and tools expose the runtime's functionality and enable you to write code that benefits from this managed
execution environment. Code that you develop with a language compiler that targets the runtime is called managed
code; it benefits from features such as cross-language integration, cross-language exception handling, enhanced
security, versioning and deployment support, a simplified model for component interaction, and debugging and
profiling services.

To enable the runtime to provide services to managed code, language compilers must emit metadata that describes
the types, members, and references in your code. Metadata is stored with the code; every loadable common language
runtime portable executable (PE) file contains metadata. The runtime uses metadata to locate and load classes, lay out
instances in memory, resolve method invocations, generate native code, enforce security, and set run-time context
boundaries.

The runtime automatically handles object layout and manages references to objects, releasing them when they are no
longer being used. Objects whose lifetimes are managed in this way are called managed data. Garbage collection
eliminates memory leaks as well as some other common programming errors. If your code is managed, you can use
managed data, unmanaged data, or both managed and unmanaged data in your .NET Framework application. Because
language compilers supply their own types, such as primitive types, you might not always know (or need to know)
whether your data is being managed.

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

As part of their metadata, all managed components carry information about the components and resources they were
built against. The runtime uses this information to ensure that your component or application has the specified
versions of everything it needs, which makes your code less likely to break because of some unmet dependency.
Registration information and state data are no longer stored in the registry where they can be difficult to establish and
maintain. Rather, information about the types you define (and their dependencies) is stored with the code as
metadata, making the tasks of component replication and removal much less complicated.
Language compilers and tools expose the runtime's functionality in ways that are intended to be useful and intuitive to
developers. This means that some features of the runtime might be more noticeable in one environment than in
another. How you experience the runtime depends on which language compilers or tools you use. For example, if you
are a Visual Basic developer, you might notice that with the common language runtime, the Visual Basic language has
more object-oriented features than before. Following are some benefits of the runtime:

 Performance improvements.
 The ability to easily use components developed in other languages.
 Extensible types provided by a class library.
 New language features such as inheritance, interfaces, and overloading for object-oriented programming;
support for explicit free threading that allows creation of multithreaded, scalable applications; support for
structured exception handling and custom attributes.

If you use Microsoft® Visual C++® .NET, you can write managed code using Visual C++, which provides the benefits
of a managed execution environment as well as access to powerful capabilities and expressive data types that you are
familiar with. Additional runtime features include:

 Cross-language integration, especially cross-language inheritance.


 Garbage collection, which manages object lifetime so that reference counting is unnecessary.
 Self-describing objects, which make using Interface Definition Language (IDL) unnecessary.
 The ability to compile once and run on any CPU and operating system that supports the runtime.

You can also write managed code using the C# language, which provides the following benefits:

 Complete object-oriented design.


 Very strong type safety.
 A good blend of Visual Basic simplicity and C++ power.
 Garbage collection.
 Syntax and keywords similar to C and C++.
 Use of delegates rather than function pointers for increased type safety and security. Function pointers are
available through the use of the unsafe C# keyword and the /unsafe option of the C# compiler (Csc.exe) for
unmanaged code and data.

2.1 Managed Execution Process


The managed execution process includes the following steps:

1. Choosing a compiler.

To obtain the benefits provided by the common language runtime, you must use one or more language
compilers that target the runtime.

2. Compiling your code to Microsoft intermediate language (MSIL).

Compiling translates your source code into MSIL and generates the required metadata.

3. Compiling MSIL to native code.

At execution time, a just-in-time (JIT) compiler translates the MSIL into native code. During this compilation,
code must pass a verification process that examines the MSIL and metadata to find out whether the code can
be determined to be type safe.

4. Running code.

The common language runtime provides the infrastructure that enables execution to take place as well as a
variety of services that can be used during execution.
2.1.1 Choosing a Compiler
To obtain the benefits provided by the common language runtime (CLR), you must use one or more language
compilers that target the runtime, such as Visual Basic, C#, Visual C++, JScript, or one of many third-party compilers
such as an Eiffel, Perl, or COBOL compiler.

Because it is a multilanguage execution environment, the runtime supports a wide variety of data types and language
features. The language compiler you use determines which runtime features are available, and you design your code
using those features. Your compiler, not the runtime, establishes the syntax your code must use. If your component
must be completely usable by components written in other languages, your component's exported types must expose
only language features that are included in the Common Language Specification (CLS). You can use the
CLSCompliantAttribute attribute to ensure that your code is CLS-compliant. For details, see Writing CLS-Compliant
Code.

2.1.2 Compiling to MSIL


When compiling to managed code, the compiler translates your source code into Microsoft intermediate language
(MSIL), which is a CPU-independent set of instructions that can be efficiently converted to native code. MSIL includes
instructions for loading, storing, initializing, and calling methods on objects, as well as instructions for arithmetic and
logical operations, control flow, direct memory access, exception handling, and other operations. Before code can be
run, MSIL must be converted to CPU-specific code, usually by a just-in-time (JIT) compiler. Because the common
language runtime supplies one or more JIT compilers for each computer architecture it supports, the same set of MSIL
can be JIT-compiled and run on any supported architecture.

When a compiler produces MSIL, it also produces metadata. Metadata describes the types in your code, including the
definition of each type, the signatures of each type's members, the members that your code references, and other data
that the runtime uses at execution time. The MSIL and metadata are contained in a portable executable (PE) file that is
based on and extends the published Microsoft PE and common object file format (COFF) used historically for
executable content. This file format, which accommodates MSIL or native code as well as metadata, enables the
operating system to recognize common language runtime images. The presence of metadata in the file along with the
MSIL enables your code to describe itself, which means that there is no need for type libraries or Interface Definition
Language (IDL). The runtime locates and extracts the metadata from the file as needed during execution.

2.1.3 Compiling MSIL to Native Code


Before you can run Microsoft intermediate language (MSIL), it must be compiled against the common language
runtime to native code for the target machine architecture. The .NET Framework provides two ways to perform this
conversion:

 A .NET Framework just-in-time (JIT) compiler.

Compilation by the Just-in-time Compiler

JIT compilation converts MSIL to native code on demand at application run time, when the contents of an assembly
are loaded and executed. Because the common language runtime supplies a JIT compiler for each supported CPU
architecture, developers can build a set of MSIL assemblies that can be JIT-compiled and run on different computers
with different machine architectures. However, your managed code will run only on a specific operating system if it
calls platform-specific native APIs, or a platform-specific class library.

JIT compilation takes into account the fact that some code might never get called during execution. Rather than using
time and memory to convert all the MSIL in a portable executable (PE) file to native code, it converts the MSIL as
needed during execution and stores the resulting native code in memory so that it is accessible for subsequent calls in
the context of that process. The loader creates and attaches a stub to each method in a type when the type is loaded
and initialized. When a method is called for the first time, the stub passes control to the JIT compiler, which converts
the MSIL for that method into native code and modifies the stub to point directly to the generated native code.
Subsequent calls to the JIT-compiled method therefore proceed directly to the native code.

Code Verification

As part of compiling MSIL to native code, the MSIL code must pass a verification process unless an administrator has
established a security policy that allows the code to bypass verification. Verification examines MSIL and metadata to
find out whether the code is type safe, which means that it only accesses the memory locations it is authorized to
access. Type safety helps isolate objects from each other and therefore helps protect them from inadvertent or
malicious corruption. It also provides assurance that security restrictions on code can be reliably enforced.

The runtime relies on the fact that the following statements are true for code that is verifiably type safe:

 A reference to a type is strictly compatible with the type being referenced.


 Only appropriately defined operations are invoked on an object.
 Identities are what they claim to be.

During the verification process, MSIL code is examined in an attempt to confirm that the code can access memory
locations and call methods only through properly defined types. For example, code cannot allow an object's fields to
be accessed in a manner that allows memory locations to be overrun. Additionally, verification inspects code to
determine whether the MSIL has been correctly generated, because incorrect MSIL can lead to a violation of the type
safety rules. The verification process passes a well-defined set of type-safe code, and it passes only code that is type
safe. However, some type-safe code might not pass verification because of some limitations of the verification process,
and some languages, by design, do not produce verifiably type-safe code. If type-safe code is required by the security
policy but the code does not pass verification, an exception is thrown when the code is run.

2.1.4 Running

2.1.4 Running Code


The common language runtime provides the infrastructure that enables managed execution to take place as well as a
variety of services that can be used during execution. Before a method can be run, it must be compiled to processor-
specific code. Each method for which Microsoft intermediate language (MSIL) has been generated is just-in-time-
compiled (JIT-compiled) when it is called for the first time, and then run. The next time the method is run, the existing
JIT-compiled native code is run. The process of JIT-compiling and then executing the code is repeated until execution
is complete.

During execution, managed code receives services such as garbage collection, security, interoperability with
unmanaged code, cross-language debugging support, and enhanced deployment and versioning support.

2.2 Automatic Memory Management


Automatic memory management is one of the services that the common language runtime provides during Managed
Execution. The common language runtime's garbage collector manages the allocation and release of memory for an
application. For developers, this means that you do not have to write code to perform memory management tasks
when you develop managed applications. Automatic memory management can eliminate common problems, such as
forgetting to free an object and causing a memory leak, or attempting to access memory for an object that has already
been freed. This section describes how the garbage collector allocates and releases memory.

Allocating Memory
When you initialize a new process, the runtime reserves a contiguous region of address space for the process. This
reserved address space is called the managed heap. The managed heap maintains a pointer to the address where the
next object in the heap will be allocated. Initially, this pointer is set to the managed heap's base address. All reference
types are allocated on the managed heap. When an application creates the first reference type, memory is allocated
for the type at the base address of the managed heap. When the application creates the next object, the garbage
collector allocates memory for it in the address space immediately following the first object. As long as address space
is available, the garbage collector continues to allocate space for new objects in this manner.

Allocating memory from the managed heap is faster than unmanaged memory allocation. Because the runtime
allocates memory for an object by adding a value to a pointer, it is almost as fast as allocating memory from the stack.
In addition, because new objects that are allocated consecutively are stored contiguously in the managed heap, an
application can access the objects very quickly.

Releasing Memory

The garbage collector's optimizing engine determines the best time to perform a collection based on the allocations
being made. When the garbage collector performs a collection, it releases the memory for objects that are no longer
being used by the application. It determines which objects are no longer being used by examining the application's
roots. Every application has a set of roots. Each root either refers to an object on the managed heap or is set to null.
An application's roots include global and static object pointers, local variables and reference object parameters on a
thread's stack, and CPU registers. The garbage collector has access to the list of active roots that the just-in-time (JIT)
compiler and the runtime maintain. Using this list, it examines an application's roots, and in the process creates a
graph that contains all the objects that are reachable from the roots.

Objects that are not in the graph are unreachable from the application's roots. The garbage collector considers
unreachable objects garbage and will release the memory allocated for them. During a collection, the garbage
collector examines the managed heap, looking for the blocks of address space occupied by unreachable objects. As it
discovers each unreachable object, it uses a memory-copying function to compact the reachable objects in memory,
freeing up the blocks of address spaces allocated to unreachable objects. Once the memory for the reachable objects
has been compacted, the garbage collector makes the necessary pointer corrections so that the application's roots
point to the objects in their new locations. It also positions the managed heap's pointer after the last reachable object.
Note that memory is compacted only if a collection discovers a significant number of unreachable objects. If all the
objects in the managed heap survive a collection, then there is no need for memory compaction.

To improve performance, the runtime allocates memory for large objects in a separate heap. The garbage collector
automatically releases the memory for large objects. However, to avoid moving large objects in memory, this memory
is not compacted.

3 Common Type System


The common type system defines how types are declared, used, and managed in the runtime, and is also an important
part of the runtime's support for cross-language integration. The common type system performs the following
functions:

 Establishes a framework that helps enable cross-language integration, type safety, and high performance code
execution.
 Provides an object-oriented model that supports the complete implementation of many programming
languages.
 Defines rules that languages must follow, which helps ensure that objects written in different languages can
interact with each other.

Common Type System Overview


Describes concepts and defines terms relating to the common type system.

Type Definitions

Describes user-defined types.

Type Members

Describes events, fields, nested types, methods, and properties, and concepts such as member overloading,
overriding, and inheritance.

Value Types in the Common Type System

Describes built-in and user-defined value types.

Classes in the Common Type System

Describes the characteristics of common language runtime classes.

Delegates in the Common Type System

Describes the delegate object, which is the managed alternative to unmanaged function pointers.

Arrays in the Common Type System

Describes common language runtime array types.

Interfaces in the Common Type System

Describes characteristics of interfaces and the restrictions on interfaces imposed by the common language
runtime.

Pointers in the Common Type System

Describes managed pointers, unmanaged pointers, and unmanaged function pointers.

3.1 Common Type System Overview


This section describes concepts and defines terms that will help you understand and work with your language's
implementation of the common type system.

Classification of Types

The common type system supports two general categories of types, each of which is further divided into
subcategories:

 Value types

Value types directly contain their data, and instances of value types are either allocated on the stack or
allocated inline in a structure. Value types can be built-in (implemented by the runtime), user-defined, or
enumerations. For a list of built-in value types, see the .NET Framework Class Library.

 Reference types
Reference types store a reference to the value's memory address, and are allocated on the heap. Reference
types can be self-describing types, pointer types, or interface types. The type of a reference type can be
determined from values of self-describing types. Self-describing types are further split into arrays and class
types. The class types are user-defined classes, boxed value types, and delegates.

Variables that are value types each have their own copy of the data, and therefore operations on one variable do not
affect other variables. Variables that are reference types can refer to the same object; therefore, operations on one
variable can affect the same object referred to by another variable.

All types derive from the System.Object base type.

The following example shows the difference between reference types and value types.

VB
C#
C++
F#
JScript
Copy
Class Class1
Public Value As Integer = 0
End Class 'Class1

Class Test

Shared Sub Main()


Dim val1 As Integer = 0
Dim val2 As Integer = val1
val2 = 123
Dim ref1 As New Class1()
Dim ref2 As Class1 = ref1
ref2.Value = 123
Console.WriteLine("Values: {0}, {1}", val1, val2)
Console.WriteLine("Refs: {0}, {1}", ref1.Value, ref2.Value)
End Sub 'Main
End Class 'Test

The output from this program is as follows.

Copy
Values: 0, 123
Refs: 123, 123

The following diagram illustrates how these various types are related. Note that instances of types can be simply value
types or self-describing types, even though there are subcategories of these types.

Type classification
Values and Objects

Values are binary representations of data, and types provide a way of interpreting this data. A value type is stored
directly as a binary representation of the type's data. The value of a reference type is the location of the sequence of
bits that represent the type's data.

Every value has an exact type that completely defines the value's representation and the operations that are defined
on the value. Values of self-describing types are called objects. While it is always possible to determine the exact type
of an object by examining its value, you cannot do so with a value type or pointer type. A value can have more than
one type. A value of a type that implements an interface is also a value of that interface type. Likewise, a value of a
type that derives from a base type is also a value of that base type.

Types and Assemblies

The runtime uses assemblies to locate and load types. The assembly manifest contains the information that the
runtime uses to resolve all type references made within the scope of the assembly.

A type name in the runtime has two logical parts: the assembly name and the name of the type within the assembly.
Two types with the same name but in different assemblies are defined as two distinct types.

Assemblies provide consistency between the scope of names seen by the developer and the scope of names seen by
the runtime system. Developers author types in the context of an assembly. The content of the assembly a developer is
building establishes the scope of names that will be available at run time.

Types and Namespaces

From the viewpoint of the runtime, a namespace is just a collection of type names. Particular languages might have
constructs and corresponding syntax that help developers form logical groups of types, but these constructs are not
used by the runtime when binding types. Thus, both the Object and String classes are part of the System namespace,
but the runtime only recognizes the full names of each type, which are System.Object and System.String, respectively.
You can build a single assembly that exposes types that look like they come from two different hierarchical
namespaces, such as System.Collections and System.Windows.Forms. You can also build two assemblies that both
export types whose names contain MyDll.MyClass.

If you create a tool to represent types in an assembly as belonging to a hierarchical namespace, the tool must
enumerate the types in an assembly or group of assemblies and parse the type names to derive a hierarchical
relationnship.

Type Definitions
You define new types from existing types. Built-in value types, pointers, arrays, and delegates are defined when they
are used and are referred to as implicit types. Types can be nested; that is, a type can be a member of another type.

A type definition includes:

 Any attributes defined on the type.


 The type's visibility.
 The type's name.
 The type's base type.
 Any interfaces implemented by the type.
 Definitions for each of the type's members.

Type Members
 The runtime allows you to define members of your type: events, fields, nested types, methods, and
properties. Each member has a signature. The following table describes the type members used in the
.NET Framework.

Member Description

Event Defines an incident that can be responded to, and defines methods for subscribing to, unsubscribing from,
and raising the event. Events are often used to inform other types of state changes.

Field Describes and contains part of the type's state. Fields can be of any type supported by the runtime.

Nested Defines a type within the scope of the enclosing type.


type

Describes operations available on the type. A method's signature specifies the allowable types of all its
Method arguments and of its return value.

A constructor is a special kind of method that creates new instances of a type.

Property Names a value or state of the type and defines methods for getting or setting the property's value.
Properties can be primitive types, collections of primitive types, user-defined types, or collections of user-
defined types. Properties are often used to keep the public interface of a type independent from the type's
actual representation.
4 Metadata and Self-Describing Components
In the past, a software component (.exe or .dll) written in one language could not easily use a software component
written in another language. COM provided a step forward in solving this problem. The .NET Framework makes
component interoperation even easier by allowing compilers to emit additional declarative information into all
modules and assemblies. This information, called metadata, helps components to seamlessly interact.

4.1 Metadata Overview


Metadata is binary information describing your program that is stored either in a common language runtime portable
executable (PE) file or in memory. When you compile your code into a PE file, metadata is inserted into one portion of
the file, while your code is converted to Microsoft intermediate language (MSIL) and inserted into another portion of
the file. Every type and member defined and referenced in a module or assembly is described within metadata. When
code is executed, the runtime loads metadata into memory and references it to discover information about your
code's classes, members, inheritance, and so on.

Metadata describes every type and member defined in your code in a language-neutral manner. Metadata stores the
following information:

 Description of the assembly.


o Identity (name, version, culture, public key).

o The types that are exported.

o Other assemblies that this assembly depends on.

o Security permissions needed to run.

 Description of types.

o Name, visibility, base class, and interfaces implemented.

o Members (methods, fields, properties, events, nested types).

 Attributes.

o Additional descriptive elements that modify types and members.

4.2 Benefits of Metadata

Metadata is the key to a simpler programming model, eliminating the need for Interface Definition Language (IDL)
files, header files, or any external method of component reference. Metadata allows .NET languages to describe
themselves automatically in a language-neutral manner, unseen by both the developer and the user. Additionally,
metadata is extensible through the use of attributes. Metadata provides the following major benefits:

 Self-describing files.

Common language runtime modules and assemblies are self-describing. A module's metadata contains
everything needed to interact with another module. Metadata automatically provides the functionality of IDL
in COM, allowing you to use one file for both definition and implementation. Runtime modules and
assemblies do not even require registration with the operating system. As a result, the descriptions used by
the runtime always reflect the actual code in your compiled file, which increases application reliability.

 Language interoperability and easier component-based design.

Metadata provides all the information required about compiled code for you to inherit a class from a PE file
written in a different language. You can create an instance of any class written in any managed language (any
language that targets the common language runtime) without worrying about explicit marshaling or using
custom interoperability code.

 Attributes.

The .NET Framework allows you to declare specific kinds of metadata, called attributes, in your compiled file.
Attributes can be found throughout the .NET Framework and are used to control in more detail how your
program behaves at run time. Additionally, you can emit your own custom metadata into .NET Framework files
through user-defined custom attributes. For more information, see Extending Metadata Using Attributes.

4.3 Structure and Use of Metadata


Although most developers do not need to know the implementation details of metadata, some might want a deeper
understanding. This section provides an overview of how metadata is stored in a .NET Framework portable executable
(PE) file and an explanation of metadata's role in managed execution. You do not need to read this section to
understand .NET programming or how to use attributes.

Metadata and the PE File Structure


Metadata is stored in one section of a .NET Framework portable executable (PE) file, while Microsoft intermediate
language (MSIL) is stored in another section of the PE file. The metadata portion of the file contains a series of table
and heap data structures. The MSIL portion contains MSIL and metadata tokens that reference the metadata portion
of the PE file. You might encounter metadata tokens when you use tools such as the MSIL Disassembler (Ildasm.exe) to
view your code's MSIL or the Runtime Debugger (Cordbg.exe) to perform a memory dump.

Metadata within a PE File

When a program is compiled for the common language runtime, it is converted to a PE file that consists of
three parts. The following table describes the contents of each part.

PE section Contents of PE section


The index of the PE file's main sections and the address of the entry point.
PE header
The runtime uses this information to identify the file as a PE file and to determine where execution
starts when loading the program into memory.

MSIL The Microsoft intermediate language instructions (MSIL) that make up your code. Many MSIL
instructions instructions are accompanied by metadata tokens.

Metadata Metadata tables and heaps. The runtime uses this section to record information about every type and
member in your code. This section also includes custom attributes and security information.

5. Cross-Language Interoperability
The common language runtime provides built-in support for language interoperability. However, this support does not
guarantee that code you write can be used by developers using another programming language. To ensure that you
can develop managed code that can be fully used by developers using any programming language, a set of language
features and rules for using them, called the Common Language Specification (CLS), has been defined. Components
that follow these rules and expose only CLS features are considered CLS-compliant.

This section describes the common language runtime's built-in support for language interoperability and explains the
role that the CLS plays in enabling guaranteed cross-language interoperability. CLS features and rules are identified,
and CLS compliance is discussed.

5.1 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.

If your component uses only CLS features in the API that it exposes to other code (including derived classes), the
component is guaranteed to be accessible from any programming language that supports the CLS. Components that
adhere to the CLS rules and use only the features included in the CLS are said to be CLS-compliant components.

Most of the members defined by types in the .NET Framework Class Library are CLS-compliant. However, some types
in the class library have one or more members that are not CLS-compliant. These members enable support for
language features that are not in the CLS. The types and members that are not CLS-compliant are identified as such in
the reference documentation, and in all cases a CLS-compliant alternative is available. For more information about the
types in the .NET Framework class library, see the .NET Framework Class Library.

The CLS was designed to be large enough to include the language constructs that are commonly needed by
developers, yet small enough that most languages are able to support it. In addition, any language construct that
makes it impossible to rapidly verify the type safety of code was excluded from the CLS so that all CLS-compliant
languages can produce verifiable code if they choose to do so. For more information about verification of type safety,
see Compiling MSIL to Native Code.

5.2 Writing CLS-Compliant Code


Common Language Specification (CLS) compliance generally refers to the claim that CLS rules and restrictions are
being followed. However, the concept has a more specific meaning depending on whether you are describing CLS-
compliant code or CLS-compliant development tools, such as a compiler. CLS-compliant tools can help you write CLS-
compliant code.

CLS-Compliant Code
If you want your code to be CLS-compliant, you must expose functionality in a way that is CLS-compliant in the
following places:

 Definitions of your public classes.


 Definitions of the public members of public classes, and of members accessible to derived classes (family
access).

 Parameters and return types of public methods of public classes, and of methods accessible to derived classes.

6. Assemblies Overview
Assemblies are a fundamental part of programming with the .NET Framework. An assembly performs the following
functions:

 It contains code that the common language runtime executes. Microsoft intermediate language (MSIL) code in
a portable executable (PE) file will not be executed if it does not have an associated assembly manifest. Note
that each assembly can have only one entry point (that is, DllMain, WinMain, or Main).
 It forms a security boundary. An assembly is the unit at which permissions are requested and granted. For
more information about security boundaries as they apply to assemblies, see Assembly Security
Considerations.

 It forms a type boundary. Every type's identity includes the name of the assembly in which it resides. A type
called MyType loaded in the scope of one assembly is not the same as a type called MyType loaded in the
scope of another assembly.

 It forms a reference scope boundary. The assembly's manifest contains assembly metadata that is used for
resolving types and satisfying resource requests. It specifies the types and resources that are exposed outside
the assembly. The manifest also enumerates other assemblies on which it depends.

 It forms a version boundary. The assembly is the smallest versionable unit in the common language runtime;
all types and resources in the same assembly are versioned as a unit. The assembly's manifest describes the
version dependencies you specify for any dependent assemblies. For more information about versioning, see
Assembly Versioning.

 It forms a deployment unit. When an application starts, only the assemblies that the application initially calls
must be present. Other assemblies, such as localization resources or assemblies containing utility classes, can
be retrieved on demand. This allows applications to be kept simple and thin when first downloaded. For more
information about deploying assemblies, see Deploying Applications.

 It is the unit at which side-by-side execution is supported. For more information about running multiple
versions of an assembly, see Assemblies and Side-by-Side Execution.

Assemblies can be static or dynamic. Static assemblies can include .NET Framework types (interfaces and classes), as
well as resources for the assembly (bitmaps, JPEG files, resource files, and so on). Static assemblies are stored on disk
in portable executable (PE) files. You can also use the .NET Framework to create dynamic assemblies, which are run
directly from memory and are not saved to disk before execution. You can save dynamic assemblies to disk after they
have executed.

There are several ways to create assemblies. You can use development tools, such as Visual Studio 2005, that you have
used in the past to create .dll or .exe files. You can use tools provided in the Windows Software Development Kit (SDK)
to create assemblies with modules created in other development environments. You can also use common language
runtime APIs, such as Reflection.Emit, to create dynamic assemblies.

6.1 Assembly Benefits


Assemblies are designed to simplify application deployment and to solve versioning problems that can occur with
component-based applications.

End users and developers are familiar with versioning and deployment issues that arise from today's component-
based systems. Some end users have experienced the frustration of installing a new application on their computer,
only to find that an existing application has suddenly stopped working. Many developers have spent countless hours
trying to keep all necessary registry entries consistent in order to activate a COM class.

Many deployment problems have been solved by the use of assemblies in the .NET Framework. Because they are self-
describing components that have no dependencies on registry entries, assemblies enable zero-impact application
installation. They also simplify uninstalling and replicating applications.

Versioning Problems

Currently two versioning problems occur with Win32 applications:

 Versioning rules cannot be expressed between pieces of an application and enforced by the operating system.
The current approach relies on backward compatibility, which is often difficult to guarantee. Interface
definitions must be static, once published, and a single piece of code must maintain backward compatibility
with previous versions. Furthermore, code is typically designed so that only a single version of it can be
present and executing on a computer at any given time.
 There is no way to maintain consistency between sets of components that are built together and the set that is
present at run time.

These two versioning problems combine to create DLL conflicts, where installing one application can inadvertently
break an existing application because a certain software component or DLL was installed that was not fully backward
compatible with a previous version. Once this situation occurs, there is no support in the system for diagnosing and
fixing the problem.

An End to DLL Conflicts

Microsoft® Windows® 2000 began to fully address these problems. It provides two features that partially fix DLL
conflicts:

 Windows 2000 enables you to create client applications where the dependent .dll files are located in the same
directory as the application's .exe file. Windows 2000 can be configured to check for a component in the
directory where the .exe file is located before checking the fully qualified path or searching the normal path.
This enables components to be independent of components installed and used by other applications.
 Windows 2000 locks files that are shipped with the operating system in the System32 directory so they cannot
be inadvertently replaced when applications are installed.

The common language runtime uses assemblies to continue this evolution toward a complete solution to DLL
conflicts.

The Assembly Solution

To solve versioning problems, as well as the remaining problems that lead to DLL conflicts, the runtime uses
assemblies to do the following:

 Enable developers to specify version rules between different software components.


 Provide the infrastructure to enforce versioning rules.
 Provide the infrastructure to allow multiple versions of a component to be run simultaneously (called side-by-
side execution).

Assembly Contents
In general, a static assembly can consist of four elements:

 The assembly manifest, which contains assembly metadata.


 Type metadata.

 Microsoft intermediate language (MSIL) code that implements the types.

 A set of resources.

Only the assembly manifest is required, but either types or resources are needed to give the assembly any meaningful
functionality.

There are several ways to group these elements in an assembly. You can group all elements in a single physical file,
which is shown in the following illustration.

Single-file assembly

Alternatively, the elements of an assembly can be contained in several files. These files can be modules of compiled
code (.netmodule), resources (such as .bmp or .jpg files), or other files required by the application. Create a multifile
assembly when you want to combine modules written in different languages and to optimize downloading an
application by putting seldom used types in a module that is downloaded only when needed.

In the following illustration, the developer of a hypothetical application has chosen to separate some utility code into a
different module and to keep a large resource file (in this case a .bmp image) in its original file. The .NET Framework
downloads a file only when it is referenced; keeping infrequently referenced code in a separate file from the
application optimizes code download.

Multifile assembly

Note:
The files that make up a multifile assembly are not physically linked by the file system. Rather, they are linked through
the assembly manifest and the common language runtime manages them as a unit.
In this illustration, all three files belong to an assembly, as described in the assembly manifest contained in
MyAssembly.dll. To the file system, they are three separate files. Note that the file Util.netmodule was compiled as a
module because it contains no assembly information. When the assembly was created, the assembly manifest was
added to MyAssembly.dll, indicating its relationship with Util.netmodule and Graphic.bmp.

As you currently design your source code, you make explicit decisions about how to partition the functionality of your
application into one or more files. When designing .NET Framework code, you will make similar decisions about how
to partition the functionality into one or more assemblies.

Assembly Manifest
Every assembly, whether static or dynamic, contains a collection of data that describes how the elements in the
assembly relate to each other. The assembly manifest contains this assembly metadata. An assembly manifest contains
all the metadata needed to specify the assembly's version requirements and security identity, and all metadata needed
to define the scope of the assembly and resolve references to resources and classes. The assembly manifest can be
stored in either a PE file (an .exe or .dll) with Microsoft intermediate language (MSIL) code or in a standalone PE file
that contains only assembly manifest information.

The following illustration shows the different ways the manifest can be stored.

Types of assemblies

For an assembly with one associated file, the manifest is incorporated into the PE file to form a single-file assembly.
You can create a multifile assembly with a standalone manifest file or with the manifest incorporated into one of the
PE files in the assembly.

Each assembly's manifest performs the following functions:

 Enumerates the files that make up the assembly.


 Governs how references to the assembly's types and resources map to the files that contain their declarations
and implementations.
 Enumerates other assemblies on which the assembly depends.
 Provides a level of indirection between consumers of the assembly and the assembly's implementation details.
 Renders the assembly self-describing.

About Shared assembly & private assembly

You might also like