In early 2002, Microsoft shipped .NET, a suite of new technologies for Windows first announced in the summer of 2000. The attendant media frenzy concentrated on its support for web services, but .NET has far greater scope than that—it could change the way all Windows programs are written. .NET offers greatly improved productivity to developers by replacing swathes of the Win32 API with new, much higher level object-oriented APIs, allowing you to focus on the task at hand without being distracted by myriad petty details.
This book is about the technology behind Windows applications that run on this new .NET platform. In particular, it focuses on rich client applications—i.e., traditional interactive programs with a graphical user interface (GUI) that run locally on your computer. Although web applications have become very popular in recent years, experience with these thin clients has taught us that there is still very much a place for the more traditional style of Windows application. If you’ve ever had to switch from Outlook to a web mail service when working away from the office, you know just how much web applications leave to be desired.
The new programming interface for writing Windows applications with GUIs is called Windows Forms. This replaces all the old programming models, and not just the C++ favorites, such as MFC or raw Win32, but also the Forms package used in Visual Basic 6.0 and earlier. Windows Forms combines the best features from all these models, and it is the long term future of Windows development.
It is important to understand why Microsoft decided to make such sweeping changes to Windows software development. Deprecating all the APIs used by the vast majority of programs seems like a wildly irresponsible move calculated to alienate anyone who ever wrote a Windows application. And yet, the majority of developers who look at .NET in any detail soon become big fans, especially those from a C++ background.
.NET raises the level of abstraction that developers work with—almost every service provided by the platform is now exposed through a higher-level programming interface than before. In Win32, the API was procedural in that all services were accessed through C function calls, using opaque handles to represent entities that outlived single function calls (e.g., windows or files). Developers had to expend a lot of effort dealing with low-level details such as memory management, which as the lucrative market in memory leak detection tools illustrates, was a source of much grief. By contrast, .NET provides all its services through a class library, and many low-level programming details are now dealt with by the platform (for example, the .NET runtime manages memory with a garbage collection scheme).
Veteran MFC or WTL developers might well point out that they have always used object-oriented abstractions for constructs such as windows and files. And Visual Basic developers can equally remind us that they have never had to deal with low-level minutiae. However, all these programming systems suffer from being wrappers on top of the “real” API, Win32. This is problematic because none of them provides a watertight abstraction—the underlying API is forever making its presence felt. This is particularly intrusive with the C++ class libraries: it’s just not possible to write a nontrivial C++ Windows application without having to deal with some Win32 construct sooner or later.
Visual Basic does slightly better—it has enabled many people to become productive developers without ever understanding how Windows really works at the lowest levels. But Visual Basic runs into trouble as soon as you need to do something that it wasn’t designed to support. It relies on ActiveX controls or COM components to exploit certain platform services, which is fine when such a component exists, but it means that support for the latest features of the OS can be somewhat late in arriving. While C++ developers can use new features as soon as they appear, Visual Basic developers must wait for a C++ developer to write them an ActiveX control. Visual Basic also suffers from a slightly more insidious problem. The high-level model it presents is a simplification of the Win32 model, and as such it differs in certain respects. If you write nothing but data entry forms this will almost certainly never cause you any problems, but if you need to exercise fine control over an application’s behavior, Visual Basic’s supposedly helpful model can sometimes be extremely frustrating.
So why is .NET any better? The crucial difference is that with .NET, all languages use the same API: Windows Forms. Of course, to provide its services, the current .NET Framework still relies on Win32 (or, in the case of the .NET Compact Framework, either Pocket PC or Windows CE.NET), but developers are strongly discouraged from bypassing the class libraries to call the underlying platform. Windows Forms has been designed to be a comprehensive abstraction rather than a thin wrapper, and it is entirely possible to write nontrivial GUI applications without ever needing to resort to calling into Win32 directly. This is very unlike MFC, which was effectively impossible to use without being exposed to Win32. Furthermore, because all languages use the same API, any new features added to the .NET Framework are instantly available to everyone—Visual Basic developers are no longer beholden to third parties to write them wrappers for new functionality.
There are two elements of .NET that allow this to work where the previous technologies, such as MFC and Visual Basic 6.0, have had only partial success. One is the new runtime—all languages share a single runtime, the Common Language Runtime (CLR), which means that all languages have the same type system and runtime semantics. This crucial development enables the platform’s services to be exposed through a single API that is accessible to all languages. And this API itself is the second element—the platform’s services are exposed through an object-oriented programming interface called the .NET Framework Class Library. We will spend the rest of this chapter looking at these two new features.