Exploring the CLR
In this chapter, I dig a little deeper into the CLR. In the .NET overview in Chapter 1, I briefly discussed metadata, MSIL, CTS, CLS, VOS, and VES. In this chapter, I dive deeper into all of these concepts. You will also understand what an assembly is and how the CLR locates assemblies, executes managed code, and enforces security. You'll learn how the CLR implements automatic memory management (garbage collection) and what changes you need to make to your programming style to take advantage of it. As I go through this material, keep in mind that, just as you didn't have to understand all the low-level details of the Win32 API to program on the Windows platform, you don't have to be an expert on the CLR to use .NET. Understanding how the CLR works will make you a better programmer though, and this knowledge will help you to be a true .NET expert.
Describing The CLR
The CLR is an execution environment that loads and executes code. All Win32 operating systems (and indeed all other operating systems) have facilities to load and run binary files. However, no operating systems that I know of have a mechanism for verifying that the code they are running has not been tampered with or that the code does not violate type safety or access memory that it should not. This sort of security checking is particularly necessary in the Internet era when executable code may be received as an attachment to an email or downloaded automatically from a Web site. It's also not usually the goal of most operating systems to make it easy for people to port software written for one operating system to other operating systems. Moreover, most operating systems don't provide system-level support for features desired by today's software developers (garbage collection, stack walking, metadata, programming language independence, and so forth). Some programming languages, like VB, provide support for some of these features in their language-specific runtimes. However, no operating system currently provides all of these features at the system level so that the features are available to any programming language that targets that operating system. Also, few operating systems have features specifically designed to make it easy to deploy and version software. DLL hell was becoming a sad fact of life with Windows applications and a huge waste of time. Enhanced security, portability, and ease of development and deployment are just some of the goals of the CLR.
The CLR is system-level code that subsumes some of the functionality of a traditional compiler (because it compiles MSIL code into native code). It also subsumes some of the functionality of the code loader in the operating system (because it reads PE format binary files and loads them into memory), and of language runtimes like the C runtime or the VB runtime (because it manages heap memory and provides services that make it easier to write software). The CLR is implemented as a set of DLLs. The most important of these is the runtime execution engine. The runtime execution engine is the part of the CLR that executes code; it can be found in a DLL called mscoree.dll that resides in your System32 directory. Other files required by the runtime, such as the file that contains the core pieces of the class library, mscorlib.dll, can be found in a directory called WINNT\Microsoft.NET\Framework\v1.0.3705. Your version number may vary. The binary files for the CLR are installed when you install the .NET Framework SDK or Visual Studio .NET. You will have to redistribute these files when you deploy a .NET Framework application. Microsoft provides a merge module that you can add to your setup to simplify this. With Microsoft's newer operating systems, like Windows .NET Server, these files will be bundled with the operating system. However, even if the target platform has the .NET Framework installed, you may still need to distribute the specific version of the Framework that you built your application with.