More on .NET Namespaces


I remember programming Windows version 2.0, scanning the alphabetical list of operating system functions (on paper, that’s how long ago this was) until I found the one whose name seemed to promise that it would do what I wanted. I’d try it, and sometimes it would work and sometimes it wouldn’t. If it didn’t, I’d go back to scanning the list again. Listing the functions alphabetically worked reasonably well on Windows 2.0, which contained only a few hundred different functions. I could see at a glance (or two or three) everything that the operating system could do for me, which gave me a fighting chance at writing some decent, albeit limited, code.

Selecting items from a short alphabetical list is easy. It’s much harder when the list gets longer.

Organizing operating system functions into one alphabetical list won’t work with today’s 32-bit Windows. It’s enormous—over 5000 functions and growing. I can’t scan through a list that long to find, for example, console output functions; they’re scattered among far too many unrelated functions for me to pick them out. It’s a problem for operating system designers, too. When they want to add a new function, they have to choose a name for it that is descriptive but that doesn’t conflict with any of the other function names already implemented. Application programmers also need to make sure that their global function names don’t conflict with operating system functions. The signal-to-noise ratio of this approach gets lower as the list of functions gets longer, and it’s approaching absolute zero today. We say that the namespace, the set of names within which a particular name needs to be unique, has gotten too large.

The way to handle large lists is to break them down into smaller sublists that you can more easily digest. The classic example of this is the Start menu in Windows. If every application on your entire computer were listed on one gigantic menu, you’d never be able to find the one that you wanted. Instead, the Start menu provides a relatively short (10 or so) list of groups, easy to scan and pick from. Each group contains a list of logical subgroups, nested as deeply as you feel is cost-effective, eventually terminating in a short list of actual applications. By the time you pick the application you want, you’ve looked at maybe 50 different choices, rarely more than a dozen or so at a time. Think how much easier this is compared to selecting the one application you want out of the thousand or so installed on most computers.

The best way to handle large lists is to break them down into smaller logical groups.

The .NET Framework provides a better way of organizing operating system functions and objects. This same mechanism keeps the names of functions and objects that you write from interfering with the names of objects and functions written by other developers. It uses the concept of a namespace, which is a logical subdivision of software functionality within which all names must be unique. It’s not a new concept; object-oriented languages have used it for decades. But its use in .NET is the first time I know of that an entire operating system’s functionality has been organized in this way.

.NET provides the concept of a namespace, a logical division within which a name needs to be unique.

All .NET common language runtime objects and functions are part of a namespace called System. When you look them up in the documentation, you’ll find that all names begin with the characters “System.” We say that all the objects and functions whose names begin this way “belong to the System namespace.” The System namespace is naturally quite large, as it contains the names of all functional elements of a rich operating system. It is therefore subdivided into a number of subordinate namespaces—for example, System.Console, which contains all the functions dealing with input and output on a console window. Some of these subnamespaces contain their own sub- subnamespaces, and so on down the line until the developers got tired of it. The fully qualified name of a function, sometimes called the qualified name or q-name, is the name of the function preceded by its full namespace location, also known as a qualifier. For example, System.Console.Write is the fully qualified name of the system function that writes output to a console window. You can call a function by means of its fully qualified name from anywhere in your code.

All.NET common language runtime objects and functions live within the System namespace.

The System namespace is very large. Consequently, it is implemented in several separate DLLs. Just because a function or an object is part of the System namespace does not necessarily mean that your editor, compiler, and linker will automatically be able to find it. You generally have to tell your development tools which of the System namespace DLLs you want to include when building a project. For example, when I build .NET components in Visual Studio, I often like them to pop up message boxes during debugging. The MessageBox object is part of the System.Windows.Forms namespace, which is implemented in System.Windows.Forms.dll. Visual Studio does not automatically include this DLL in its reference list when I create a component library project, probably because its authors figured that components would work behind the scenes and not interact with the user. That’s generally true in production. To gain access to the MessageBox object during debugging, I have to explicitly add that reference to my project.

The System namespace is implemented in several separate DLLs. You have to be sure that your development tools know to include all the ones you need.

This organization of functions into logical groups is very handy for finding the one you want with a minimum of fuss. The only drawback is that fully qualified names can get very long. For example, the function System.Runtime.InteropServices.Marshal.ReleaseComObject is used for releasing a specified COM object immediately without performing a full garbage collection. (See the section “.NET Memory Management” for an explanation of the latter.) Most .NET applications won’t use this function at all, but the ones that do will probably use it in many places. Typing this whole thing in every time you call it could get very tedious very quickly. You can see that it barely fits on one line of this book. My wife does not address me as “David Samuel Platt, son of Benjamin, son of Joseph” unless she is exceptionally angry, a state she is incapable of occupying for very long. Therefore, just as people address their most intimate relations by their first names, the common language runtime allows you to import a namespace, as shown earlier in the programming examples in Listings 2-1 and 2-2. When you import a namespace, you’re telling your compiler that you use the functions in that namespace so often that you want to be on a first-name basis with them. Importing a namespace is done in Visual Basic by using the keyword Imports, and in C# via the keyword using. For example, in Listing 2-2, I imported the namespace System, which allowed me to write to the console by calling Console.Write. If I hadn’t imported the System namespace, I would have had to use the fully qualified name System.Console.Write. Choosing which namespaces to import is entirely a matter of your own convenience and has no effect on the final product (IL always uses full names) other than allowing you to organize your own thought processes so as to produce your best output. Since the whole point of using separate namespaces is to separate functions with the same name to prevent conflicts, I’d suggest that you not import them all at the same time. Instead, I strongly urge you to pick a consistent set of rules for choosing which namespaces to import and follow it throughout your entire project.

Importing a namespace allows you to use short names when calling a function within that namespace.

When you write a .NET object server, you specify the name of the namespace in which your code lives. This is done via the Namespace directive, as shown in Listing 2-1. The namespace will often be the same as the name of the file in which the code lives, but it doesn’t have to be. You can put more than one namespace in the same file, or you can spread one namespace among multiple files. Visual Studio .NET or other development environments will often automatically assign a namespace to your project. But how do you know that your namespace won’t conflict with the namespace chosen by another vendor for a different component? That’s what assemblies are for, which is our next topic of conversation.

Your own code will also live in a namespace, with a name you define.

start sidebar
Tips from the Trenches

A number of my customers report that they’re happy using the following rule: If you refer to a namespace three or more times within a source code file, import that namespace. They find it easy to remember and follow, and they like the familiarity it engenders. On the other hand, when I’m writing sample code, I often don’t import any namespaces other than System, using fully qualified names at all times to emphasize exactly which part of the .NET system a particular object belongs to.

end sidebar




Introducing Microsoft. NET
Introducing Microsoft .NET (Pro-Developer)
ISBN: 0735619182
EAN: 2147483647
Year: 2003
Pages: 110

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net