The CLR’s Execution Model
Compiling Source Code into Managed Modules
As the figure shows, you can create source code files written in any programming language that supports the CLR. Then you use the corresponding compiler to check the syntax and analyze the source code. Regardlessof which compiler you use, the result is a managed module. A managed module is a standard 32-bit Windows portable executable (PE32) file or a standard 64-bit Windows portable executable (PE32+) file that requires the CLR to execute. By the way, managed assemblies always take advantage of Data Execution Prevention (DEP) and Address Space Layout Randomization (ASLR) in Windows; these two features improve the security of your whole system
In addition to emitting IL, every compiler targeting the CLR is required to emit full metadatainto every managed module. In brief, metadata is a set of data tables that describe what is defined in the module, such as types and their members. In addition, metadata also has tables indicating what the managed module references, such as imported types and their members. Metadata is a superset of older technologies such as COM’s Type Libraries and Interface Definition Language (IDL) files. The important thing to note is that CLR metadata is far more complete. And, unlike Type Libraries and IDL, metadata is always associated with the file that contains the IL code. In fact, the metadata is always embedded in the same EXE/DLL as the code, making it impossible to separate the two. Because the compiler produces the metadata and the code at the same time and binds them into the resulting managed module, the metadata and the IL code it describes are never out of sync with one another.
Metadatahas many uses. Here are some of them:
■ Metadata removes the need for native C/C++ header and library files when compiling because all the information about the referenced types/members is contained in the file that has the IL that implements the type/members. Compilers can read metadata directly from managed modules.
■ Microsoft Visual Studio uses metadata to help you write code. Its IntelliSense feature parses metadata to tell you what methods, properties, events, and fields a type offers, and in the case of a method, what parameters the method expects.
■ The CLR’s code verification process uses metadata to ensure that your code performs only “type-safe” operations. (I’ll discuss verification shortly.)
■ Metadata allows an object’s fields to be serialized into a memory block, sent to another machine, and then deserialized, re-creating the object’s state on the remote machine.
■ Metadata allows the garbage collector to track the lifetime of objects. For any object, the garbage collector can determine the type of the object and, from the metadata, know which fields within that object refer to other objects.
Combining Managed Modules into Assemblies
An assembly allows you to decouple the logical and physical notions of a reusable, securable, versionable component. How you partition your code and resources into different files is completely up to you.
Assemblies allow you to break up the deployment of the files while still treating all of the files as a single collection.
Loading the Common Language Runtime
Microsoft ships two SDK command-line utilities, DumpBin.exe and CorFlags.exe, that you can use to examine the header information emitted in a managed module by the compiler.
Executing Your Assembly’s Code
There are two C# compiler switches that impact code optimization: /optimizeand /debug.
Furthermore, thecompiler produces a Program Database (PDB) file only if you specify the /debug(+/full/pdbonly) switch. The PDB file helps the debugger find local variables and map the IL instructions to source code.
When you create a new C# project in Visual Studio, the Debug configuration of the project has /optimizeand /debug:fullswitches, and the Release configuration has /optimize+ and /debug:pdbonlyswitches specified.
Ifyour experiments show that the CLR’s JIT compiler doesn’t offer your application the kind of performance it requires, you may want to take advantage of the NGen.exe tool that ships with the .NET Framework SDK. This tool compiles all of an assembly’s IL code into native code and saves the resulting native code to a file on disk.
IL and Verification
Unsafe Code
Microsoft supplies a utility called PEVerify.exe, which examines all of an assembly’s methods and notifies you of any methods that contain unsafe code.
The Native Code Generator Tool: NGen.exe
The NGen.exe tool is interesting in two scenarios:
■ Improving an application’s startup time Running NGen.exe can improve startup time because the code will already be compiled into native code so that compilation doesn’t have to occur at run time.
■ Reducing an application’s working set If you believe that an assembly will be loaded into multiple processes simultaneously, running NGen.exe on that assembly can reduce the applications’ working set. The reason is because the NGen.exe tool compiles the IL to native code and saves the output in a separate file. This file can be memory-mapped into multiple-process address spaces simultaneously, allowing the code to be shared; not every process needs its own copy of the code.
When a setup program invokes NGen.exe on an application or a single assembly, all of the assemblies for that application or the one specified assembly have their IL code compiled into native code. A new assembly file containing only this native code instead of IL code is created by NGen.exe. This new file is placed in a folder under the directory with a name like %SystemRoot%\Assembly\NativeImages_v4.0.#####_64. The directory name includes the version of the CLR and information denoting whether the native code is ompiled for 32-bit or 64-bit versions of Windows.
There are several potential problems with respect to NGen’d files:
■ No intellectual property protection
■ NGen’d files can get out of sync
• CLR version: This changes with patches or service packs.
• CPU type: This changes if you upgrade your processor hardware.
• Windows operating system version: This changes with a new service pack update.
• Assembly’s identity module version ID (MVID): This changes when recompiling.
• Referenced assembly’s version IDs: This changes when you recompile a referenced assembly.
• Security: This changes when you revoke permissions (such as declarative inheritance, declarative link-time, SkipVerification, or UnmanagedCodepermissions), that were once granted.
■ Inferior execution-time performance
For large client applications that experience very long startup times, Microsoft provides a Managed Profile Guided Optimization tool (MPGO.exe). This tool analyzes the execution of your application to see what it needs at startup. This information is then fed to the NGen.exe tool in order to better optimize the resulting native image.
The Framework Class Library
The Common Type System
The following list shows the valid options for controlling access to a member:
■ Private Themember is accessible only by other members in the same class type.
■ Family The member is accessible by derived types, regardless of whether they are within the same assembly. Note that many languages (such as C++ and C#) refer to family as protected.
■ Family and assembly The member is accessible by derived types, but only if the derived type is defined in the same assembly. Many languages (such as C# and Visual Basic) don’t offer this access control. Of course, IL Assembly language makes it available.
■ Assembly The member is accessible by any code in the same assembly. Many languages refer to assemblyas internal.
■ Family or assembly The member is accessible by derived types in any assembly. The member is also accessible by any types in the same assembly. C# refers to familyor assemblyas protected internal.
■ Public The member is accessible by any code in any assembly.
The Common Language Specification
If you’re designing a type in one language, and you expect that type to be used by another language, you shouldn’t take advantage of any features that are outside of the CLS in its public and protected members.
// Tell compiler to check for CLS compliance
[assembly: CLSCompliant(true)]
Interoperability with Unmanaged Code
■ Managed code can call an unmanaged function in a DLL
■ Managed code can use an existing COM component (server)
■ Unmanaged code can use a managed type (server)