Every few years or so, the modern-day programmer must be willing to perform a self-inflicted knowledge transplant to stay current with the new technologies of the day. The languages (C++, Visual Basic 6.0, Java), frameworks (OWL, MFC, ATL, STL), architectures (COM, CORBA, EJB), and APIs (including .NET's Windows Forms and GDI+ libraries) that were touted as the silver bullets of software development eventually become overshadowed by something better or at the very least something new. Regardless of the frustration you can feel when upgrading your internal knowledge base, it is frankly unavoidable. To this end, this book will examine the details of Microsoft's current offering within the landscape of software engineering: the .NET platform and the latest version of the Visual Basic programming language.
The point of this chapter is to lay the conceptual groundwork for the remainder of the book. It begins with a high-level discussion of a number of .NET-related topics such as assemblies, the common intermediate language (CIL), and just-in-time (JIT) compilation. In addition to previewing some key features of the Visual Basic 2008 programming language, you will also come to understand the relationship between various aspects of the .NET Framework, such as the common language runtime (CLR), the Common Type System (CTS), and the Common Language Specification (CLS).
This chapter also provides you with an overview of the functionality supplied by the .NET base class libraries, sometimes abbreviated as the BCL or alternatively as the FCL (being the Framework class libraries). Finally, this chapter investigates the language-agnostic and platform-independent nature of the .NET platform (yes it's true! .NET is not confined to the Windows family of operating systems). As you would hope, a majority of these topics are explored in much more detail throughout the remainder of this text.
Before examining the specifics of the .NET universe, it's helpful to consider some of the issues that motivated the genesis of Microsoft's current platform. To get in the proper mind-set, let's begin this chapter with a brief and painless history lesson to remember our roots and understand the limitations of the previous state of affairs. After completing this quick tour of life as we knew it, we turn our attention to the numerous benefits provided by Visual Basic 2008 and the .NET platform.
Life As a C/Win32 API Programmer
Traditionally speaking, developing software for the Windows family of operating systems involved using the C programming language in conjunction with the Windows application programming interface (API) and the Windows Software Development Kit (SDK). While it is true that numerous applications have been successfully created using this time-honored approach, few of us would disagree that building applications using the raw API/SDK is a complex undertaking.
The first obvious problem is that C is a very terse language. C developers are forced to contend with manual memory management, complex pointer arithmetic, and ugly syntactical constructs. Furthermore, given that C is a procedural language, it lacks the benefits provided by the object-oriented approach. When you combine the thousands of global functions and data types defined by the Windows API to an already formidable language, it is little wonder that there are so many buggy applications floating around today.
Life As a C++/MFC Programmer
One vast improvement over raw C/API development is the use of the C++ programming language. In many ways, C++ can be thought of as an object-oriented layer on top of C. Thus, even though C++ programmers benefit from the famed "pillars of OOP" (encapsulation, inheritance, and polymorphism), they are still at the mercy of the painful aspects of the C language (e.g., manual memory management, complex pointer arithmetic, and ugly syntactical constructs).
Despite its complexity, many C++ frameworks exist today. For example, the Microsoft Foundation Classes (MFC) provides the developer with a set of C++ classes that simplifies the construction of Windows applications. The main role of MFC is to wrap a "sane subset" of the raw Windows API behind a number of classes and numerous code-generation tools (aka wizards). Regardless of the helpful assistance offered by the MFC framework (as well as many other C++-based toolkits), the fact of the matter is that C++ programming remains a difficult and error-prone experience, given its historical roots in C.
Due to a heartfelt desire to enjoy a simpler lifestyle, many programmers avoided the world of C(++)-based frameworks altogether in favor of kinder, gentler languages such as Visual Basic 6.0 (VB6). VB6 is popular due to its ability to build sophisticated graphical user interfaces (GUIs), code libraries (e.g., ActiveX servers), and data access logic with minimal fuss and bother. Much more than MFC, VB6 hides the complexities of the raw Windows API from view using a number of integrated programming wizards, intrinsic data types, classes, and VB6-specific functions.
The major limitation of VB6 (which has been rectified given the advent of the .NET platform) is that it is not a fully object-oriented language; rather, it is "object aware." For example, VB6 does not allow the programmer to establish "is-a" relationships between types (i.e., no classical inheritance) and has no intrinsic support for parameterized class construction. Moreover, VB6 doesn't provide the ability to build multithreaded applications unless you are willing to drop down to low-level Windows API calls (which is complex at best and dangerous at worst).
Life As a Java/J2EE Programmer
Enter Java. Java is an object-oriented programming language that has its syntactic roots in C++. As many of you are aware, Java's strengths are far greater than its support for platform independence. Java (as a language) cleans up many unsavory syntactical aspects of C++. Java (as a platform) provides programmers with a large number of predefined "packages" that contain various type definitions. Using these types, Java programmers are able to build "100% Pure Java" applications complete with database connectivity, messaging support, web-enabled front ends, and a rich desktop user interface (UI).
Although Java is a very elegant language, one potential problem is that using Java typically means that you must use Java front-to-back during the development cycle. In effect, Java offers little hope of language integration, as this goes against the grain of Java's primary goal (a single programming language for every need). In reality, however, there are millions of lines of existing code out there in the world that would ideally like to commingle with newer Java code. Sadly, Java makes this task problematic.
Pure Java is often not appropriate for many graphically or numerically intensive applications (in these cases, you may find Java's execution speed leaves something to be desired). A better approach for such programs would be to use a lower-level language (such as C++) where appropriate. Again, while Java does provide a limited ability to access non-Java APIs, there is little support for true cross-language integration.
The Component Object Model (COM) was Microsoft's first attempt at a unified component framework. COM is an architecture that says in effect, "If you build your classes in accordance with the rules of COM, you end up with a block of reusable binary code."
The beauty of a binary COM server is that it can be accessed in a language-independent manner. Thus, VB6 programmers can build COM classes that can be used by C++ programs. Delphi programmers can use COM classes built using C, and so forth. However, as you may be aware, COM's language independence is somewhat limited. For example, there is no way to derive a new COM class using an existing COM class (as COM has no support for classical inheritance).
Another benefit of COM is its location-transparent nature. Using constructs such as application identifiers (ApplDs), stubs, proxies, and the COM runtime environment, programmers can avoid the need to work with raw sockets, manual remote procedure calls, and other low-level details. For example, consider the following VB6 COM client code:
' The MyCOMClass type could be written in ' any COM-aware language, and may be located anywhere ' on the network (including your local machine). Dim myObj As MyCOMClass
Set myObj = New MyCOMClass ' Location resolved using AppID. myObj.DoSomeWork
Although COM can be considered a very successful object model, it is extremely complex under the hood. To help simplify the development of COM binaries, numerous COM-aware frameworks have come into existence (most notably VB6). However, framework support alone is not enough to hide the complexity of COM. Even when you choose a relatively simply COM-aware language such as VB6, you are still forced to contend with fragile registration entries and numerous deployment-related issues (collectively termed DLL hell).
To further complicate matters, there is a little thing called the Internet. Over the last several years, Microsoft has been adding more Internet-aware features into its family of operating systems and products. Sadly, building a web application using COM-based Windows Distributed interNet Applications Architecture (DNA) is also quite complex.
Furthermore, and perhaps more important, each language and/or technology has its own type system (that may look nothing like another's type system). Beyond the fact that each API ships with its own collection of prefabricated code, even basic data types cannot always be treated identically. A BSTR in C++ is not quite the same as a String in VB6, both of which have very little to do with a char* in C.
So much for the brief history lesson. The bottom line is that life as a Windows programmer has been less than perfect. The .NET Framework is a rather radical and brute-force approach to streamlining the application development process. The solution proposed by .NET is "Change everything" (sorry, you can't blame the messenger for the message). As you will see during the remainder of this book, the .NET Framework is a completely new model for building systems on the Windows family of operating systems, as well as on numerous non-Microsoft operating systems such as Mac OS X and various Unix/Linux distributions. To set the stage, here is a quick rundown of some core features provided courtesy of .NET:
• Comprehensive interoperability with existing code: This is (of course) a good thing. ActiveX components can commingle (i.e., interop) with newer .NET applications and vice versa. Also, Platform Invocation Services (PInvoke) allows you to call C-based libraries (including the underlying API of the operating system) from .NET code.
• Integration among .NET programming languages: .NET supports cross-language inheritance, cross-language error handling, and cross-language debugging of code.
• A common runtime engine shared by all .NET-aware languages: One aspect of this engine is a well-defined type system that each .NET-aware language "understands."
• A comprehensive base class library: This library provides shelter from the complexities of raw Windows API calls and offers a consistent object model used by all .NET-aware languages.
• No more COM plumbing: Legacy COM interfaces (such as IUnknown and IDispatch), COM type libraries, and the COM-centric Variant data type have no place in a native .NET binary.
• A truly simplified deployment model: Under .NET, there is no need to register a binary unit into the system registry. Furthermore, .NET allows multiple versions of the same *.dll to exist in harmony on a single machine.
As you can most likely gather from the previous bullet points, the .NET platform has nothing to do with COM (beyond the fact that both frameworks originated from Microsoft). In fact, the only way .NET and COM types can interact with each other is using the interoperability layer.
Note Coverage of the .NET interoperability layer can be found in Chapter 19.
Introducing the Building Blocks of the .NET Platform (the CLR, CTS, and CLS)
Now that you know some of the benefits provided by .NET, let's preview three key (and interrelated) entities that make it all possible: the CLR, CTS, and CLS. From a programmer's point of view, .NET can be understood as a new runtime environment and a comprehensive base class library. The runtime layer is properly referred to as the common language runtime, or CLR. The primary role of the CLR is to locate, load, and manage .NET types on your behalf. The CLR also takes care of a number of low-level details such as memory management, loading external libraries, and performing security checks.
Another building block of the .NET platform is the Common Type System, or CTS. The CTS specification fully describes the underlying type system and programming constructs supported by the runtime, specifies how these entities can interact with each other, and details how they are represented in the .NET metadata format (more information on metadata later in this chapter).
Understand that a given .NET-aware language might not support each and every feature defined by the CTS. The Common Language Specification (CLS) is a related specification that defines a subset of common types and programming constructs that all .NET programming languages can agree on. Thus, if you build .NET types that only expose CLS-compliant features, you can rest assured that all .NET-aware languages can consume them. Conversely, if you make use of a data type or programming construct that is outside of the bounds of the CLS, you cannot guarantee that every .NET programming language can interact with your .NET code library.
In addition to the CLR and CTS/CLS specifications, the .NET platform provides a base class library that is available to all .NET programming languages. Not only does this base class library encapsulate various primitives such as threads, file input/output (I/O), graphical rendering, and interaction with various external hardware devices, but it also provides support for a number of services required by most real-world applications.
For example, the base class libraries define types that facilitate database access, XML document manipulation, programmatic security, and the construction of web-enabled (as well as traditional desktop and console-based) front ends. From a high level, you can visualize the relationship between the CLR, CTS, CLS, and the base class library, as shown in Figure 1-1.
Was this article helpful?