It's Becoming a Managed World
Aficionados of .NET divide the world into two types of code: managed and unmanaged. Managed code is compiled to an intermediate language called the Common Intermediate Language (CIL) that is run from within the .NET Framework. The .NET runtime verifies the proper execution of the managed code at run time[1]. When data is transferred between variables, the data type is checked to see whether it's compatible with the destination type, or that the proper conversion has been applied. Array indexes are checked to ensure that they are within the range of the array. Because of the use of a CPU-neutral byte code used by the runtime, a single managed binary can run on many different CPU types.Unmanaged, or native, code is code written the good old-fashioned way. Routines are compiled directly to machine code when compiled on the developer's machine. Unmanaged applications are written to talk either to the operating system's API or to a class library that wraps that API. Unmanaged applications depend on the compiler to verify the correctness of data types and array indexes. Few unmanaged compilers produce code to make these checks at run time.The advocates of managed code preach its advantages with almost a religious fervor. The problem with theological discussions of technical issues is that engineers tend to concentrate on their side of the argument without recognizing the valid issues contradicting their opinions. Managed code has many advantages over unmanaged code, but also some significant disadvantages. In an embedded environment, the balance of the arguments differs somewhat from the evaluations of the desktop and server spaces. My advice is to use what works best for a particular situation.
To .NET or Not to .NET
There are a number of advantages of managed code in the embedded environment. First and foremost, managed applications don't care about the type of CPU on the system, so only one executable needs to be distributed for customers instead of separate versions for ARM, x86, SHx, and MIPS. This abstraction greatly simplifies both distribution and support of your applications. CPU independence is much more important for us in the embedded world. Everyone on the desktop, with the exception of a handful of Macintosh systems, executes the true universal byte code set, x86 machine code.The managed runtime also enforces a number of requirements with respect to the application, which makes the managed code much more robust. The runtime enforces type safety, which helps in reducing bugs introduced by the programmer as well as avoiding the execution of malicious code that takes advantage of data type mismanagement and unverified data to hack into systems.Another advantage touted by advocates of managed code is the simplicity and speed in development of managed applications. It's quite true that the latest tools provide a productive environment for producing amazingly powerful applications in shorter time than is typical with unmanaged code. I personally don't feel that this increased productivity is as much a credit to the concept of managed code as to the quality of the tools, including the new languages, producing the managed code. Regardless of the core reason, the process of generating managed applications is both easier and quicker than that of generating unmanaged applications with the previous generation of tools.
The disadvantage of managed code is chiefly speed and responsiveness. Here again, this is not so much of an issue on the desktop, where the latest x86-compatible CPUs are so powerful that they don't even break a sweat running typical business software. That said, managed code executes more slowly than unmanaged code. This difference can either have an impact or not depending on the application and the hardware. Managed code can also be nonresponsive if an ill-timed garbage collection happens. During garbage collection, all threads in a managed application are suspended. In worst-case situations, these garbage collections can take seconds to complete. Not a comforting thought for applications that are supporting some commercial task in front of an impatient customer.Should you develop your new applications in managed code? There are many reasons to say yes. So are the previous 22 chapters of this book a waste of time? Even if you decide to write your embedded applications in managed code, the answer is no. The current implementation of the .NET Compact Frameworks, although quite functional, is anything but complete. There are significant gaps in the functionality of the runtime that will require all but the most platform-agnostic application to access the underlying operating system to accomplish some task or another. Actions as simple as saving configuration information in the registry or integrating as tightly with the shell as a native application require calling outside the managed environment into the underlying unmanaged operating system.In this single chapter, I can't hope to describe everything about the .NET Compact Framework. Even single books have trouble being complete, which is why there are entire series of books from publishers describing the .NET initiative from Microsoft. Microsoft Press, the publisher of this book, alone has more than 50 books dedicated to .NET. Instead, I'll use this chapter to introduce the .NET Compact Frameworks as they are implemented on Windows CE devices. After that introduction, this chapter walks through the architecture of a Windows Forms application. Then the handful of classes not on the desktop but supported by Compact Framework are covered. The remaining sections of this chapter concentrate on providing information to enable applications that run as fast and are as tightly integrated with the underlying operating system as their unmanaged counterparts. Let's start with the basics.[1] The initial release of the .NET Compact Framework runtime doesn’t perform run-time type verification.