Enhancing Developer Productivity
An important design goal of the Framework Class Library is to enhance developer productivity.
It may surprise you to know that the class library primarily targets the goal of enhanced productivity not by introducing new functionality but by repackaging functionality in an object-oriented way. That is to say that, while the Framework Class Library does introduce some new features, much of the functionality exposed by the namespaces was previously available to us through the Win32 API, ActiveX controls, COM-based DLLs, and so on. Now, however, it is wrapped in a way that allows us to program at an abstracted level where we don't have to deal with the complexities and granular pieces of data required by the Win32 API. As a direct result, we only have to deal with one over-arching design pattern in our applications: one that uses and promotes components in an object-oriented environment. Moreover, the functionality is available across all of the CLR-targeted languages!
In case you were wondering, the Framework Class Library does not replace the Win32 API. The class library still relies on the actual Win32 API classes to talk directly to the Win32 API to execute code through something called a P/invoke (platform invoke). We'll talk more about this process when we dig into the details of calling the Win32 API from your code in Appendix A, "Calling the Win32 API from Managed Code." Of course, if the .NET Framework is ported to another environment, the P/invoke code will be calling into that environment's native API.
Finding the Code That You Need
If we start to examine the ways that the class library helps to make for a more productive development experience, we can see a few things immediately. For one, the class library allows you to easily find the functionality for which you are looking. While the size of the class library may seem daunting at first, its logical presentation inside of the namespaces allows functionality to be discovered in a straightforward fashion. For instance, the System.Drawing namespace contains classes that will provide you with drawing functions. The System.IO namespace exposes classes for basic input/output operations, and so on. And inside the System.Drawing namespace, we find objects that would be familiar to any Windows graphics programmer: the Pen object, the Brush object, and so on.
With any sufficiently sized API, the task of actually locating the code or function that you need for a given task is not an inconsiderable issue. Contrast the organization of the namespaces that we have talked about thus far with the organization of the flat, monolithic namespace offered up by the Win32 API. The Win32 API has given us such gems as FindClosePrinterChangeNotification (which doesn't find anything; it closes a resource). The problem is that, as the Win32 API has grown at its core, its developers have had to be more and more creative with their function names. The ability to look at a function name and know without some research what its purpose is has started to deteriorate. To be fair, it is possible to be productive using the Win32 API from Visual Basic. It just takes some determination and a lot of reference information. The Framework Class Library is a more approachable API: Things are where you expect them to be. It appeals to the OO programmer in all of us who, after all, is just interested in simplifying software by using objects.
We call any code that runs under the control of the .NET runtime managed code. Unmanaged code is any code that runs outside of the .NET runtime, such as the Win32 API, COM components, and ActiveX controls. Currently, the only development tool available from Microsoft for writing unmanaged code is Visual C++.
Using the Class Library
Finding the class you need is the first step; after you have found it, the Framework Class Library also makes utilizing it easy. By exposing functionality through properties and methods, we have straightforward access to features that are extremely complicated under the hood. In the true spirit of data hiding and encapsulation, we are dealing with black boxeswe neither know nor care what takes place in the box. What we do care about is that we talk to the black box in a standard and predictable way.
This element of productivity is not insignificant. Again consider the effort required to work directly with the Win32 API. Because Visual Basic was talking to an API that had a different type system, there was not a clear, one-to-one mapping between API calls and actual Visual Basic syntax. Now, due to the integral role that the Common Type System plays, all languages talk to runtime components through the same data types. This ensures that the classes in the Framework Class Library can be consumed evenly by any of the .NET languages. For the first time, Visual Basic developers have the full range of framework functionality open to them with no corresponding drop in productivity.
There is little to no disjoint when a programmer hops between language-intrinsic functions and the class library. In other words, Visual Basic developers are finally free to accomplish their application programming without jumping in and out of different coding paradigms (such as moving from procedural Win32API patterns to VB component patterns). Design patterns can remain consistent throughout your code regardless of the actual type of component being consumed. This is because the entire library was built to support object and component-based programming intrinsicallythese concepts are "built-in" and not bolted on. What's more, the class library usage follows familiar design patterns for VB developers. There is no esoteric syntax required; instead, you reference the component, instantiate it, and then use its methods and properties.
Because the Framework Class Library is written in managed code that runs on top of the .NET Common Language Runtime, it reaps all of the benefits of any other piece of managed code, such as:
Freedom from GUIDS, hResults, and so on
Automatic garbage collection of unused resources and memory
Support for structured exception handling
The holy grail of all object-oriented development, code reuse is a large part of the value of the Framework Class Library. As all code libraries are intended to do, the intent with the class library is to provide developers with a foundation for application development. If you recall the concepts of inheritance that we talked about in Chapter 3, "Object-Oriented Concepts in .NET," VB .NET programmers are free to derive any of their classes from a base class defined in one of the system namespaces (assuming, of course, that the class has not been marked as sealedsee our note on sealed classes later). These classes don't behave any differently than a class that you would write in Visual Basic .NET. In VB .NET, the Inherits keyword is all that is needed. The following code snippet shows a program inheriting from the XMLDocument class in the System.Xml namespace:
Public Class MyDOM Inherits System.Xml.XmlDocument . . . End Class
In addition to using the Framework classes for inheritance, you can also simply instantiate an object directly from one of these classes, and use ityou simply reference the namespace that you need, and then dimension and instantiate an object from one of the classes in that name-space. Object instantiation will look familiar to VB developers, because this is similar to what you have done with type libraries and COM DLLs.
This code snippet shows how you can use the Imports keyword to reference a specific name-space in the class library. The DNS class contained in the System.Net.Sockets namespace is then used to instantiate an object. The code is clear and simple to read.
Imports System.Net.Sockets Public Class TargetServer Sub Main() Dim resolver As DNS = New DNS() . . . End Sub End Class
You should know that there are classes that don't allow you to inherit from them. Conversely, there are also classes that require you to inherit from them. These classes are called sealed and abstract, respectively, and are discussed in more detail in the following section.
The end result is a universal, free, logical, and component-based API that can be easily consumed by any of the .NET languages without loss of functionality.