A significant part of the power of the .NET framework comes from the base classes supplied by Microsoft as part of the .NET framework. These classes are all callable from C# and provide the kind of basic functionality that is needed by many applications to perform, amongst other things, basic system, Windows, and file handling tasks. To a large extent the .NET base classes can be seen as replacing the previous Win32 API and a large number of MS-supplied COM components. The base classes are simpler to use, and you can easily derive from them to provide your own specialist classes. You can also use the base classes from any .NET-aware language (calling Win32 API functions from VB was possible but not easy). The types of purposes you can use the base classes to do include:
- String handling
- Arrays, lists, maps etc.
- Accessing files and the file system
- Accessing the registry
- Security
- Windowing
- Windows messages
- Connecting to other computers and to the Internet
- Drawing
- Directory Access
- Database Access
You can see from the above list that besides giving access to basic Windows operations, the base classes define many useful data types, including strings and collections of data.
The base classes are not, of course, only available to C# programs - they can equally well be accessed from VB, C++ or any other .NET-compliant or (by use of some wrapper objects) COM-aware language, but we will concentrate on C# here.
The aim of this chapter is to give you an overview of the kinds of things you can do using the base classes and how to perform certain common operations. Clearly the scope of the base classes is so vast that we cannot give any kind of comprehensive guide in one chapter - instead we are going to pick on a few common programming tasks and present sample code to demonstrate how you can easily execute those tasks. However we will also show you how you can use the WinCV tool which is supplied with the .NET SDK to explore the base classes for yourself.
The tasks we're going to cover in this chapter include:
- Manipulating dates and times
- Navigating the file system
- Reading and writing to files
- Copying, Moving and Deleting files
- Connecting to the Internet
- Accessing the registry
- Mathematical functions
Note that we are not covering windowing or data access in this chapter. These areas are important enough to warrant chapters in their own right and are respectively covered in Chapters 8 and 9.
Before we do that though, we need to switch topics for a while and understand how namespaces work in C#, since you need to be able to use and reference namespaces in order to be able to access the base classes.
Namespaces
A namespace can be seen as a container for some classes in much the same way that a folder on your file system contains files. Namespaces are needed because there are a lot of .NET classes. Microsoft has written many thousands of base classes, and any reasonably large application will define many more. By putting the classes into namespaces we can group related classes together, and also avoid the risk of name collisions: If your company happens to define a class that has the same name as the class written by another organization, and there were no namespaces, there would be no way for a compiler to figure out which class a program is actually referring to. With namespaces, there isn't a problem because the two classes will be placed in different namespaces, which compares with, say, the Windows files system where files with the same name can be contained in different folders.
It is also possible for namespaces to contain other namespaces, just as folders on your file system can contain other folders as well as files.
When Visual Studio generates your projects, it automatically puts your classes in a namespace. Say for example you use the developer environment to create a C# Windows Application project called MyProject. If you do this and look at the code generated for you, you'll see something like this.
namespace MyProject
{
using System;
using System.Drawing;
using System.Collections;
using System.ComponentModel;
using System.WinForms;
using System.Data;
There's two C# keywords here that we need to understand: namespace and using. We'll look at namespace first then examine what using does.
The initial namespace command indicates that everything following the opening curly brace is part of a namespace called MyProject. Later on in the file, a class called Form1 is declared.
public class Form1 : System.WinForms.Form
Because this class has been declared inside the namespace, its 'real' name is not Form1 but MyProject.Form1, and any other code outside this namespace must refer to it as such. This name is correctly known as its fully-qualified name. Notice that in the above line, Form1 is derived from a class called Form. This class is defined inside the namespace WinForms, which in turn is defined inside the namespace System (recall we mentioned earlier that it is possible for namespaces to contain other namespaces). This code sample refers to the Form class using its fully qualified name.
Now we'll have a look at the purpose of the using command in the above code. It's basically a way of avoiding having to write fully-qualified names everywhere, since the fully-qualified names can get quite long and make your code hard to read. For example if we consider the line
using System.WinForms;
This line declares that I may later in the code use classes from the System.WinForms namespace, without indicating the fully-qualified name - and the same applied for every other namespace mentioned in a using command. For example consider the line of code, also generated by the developer environment
public class Form1 : System.WinForms.Form
Because of the earlier using command, we could equally well write this as
public class Form1 : Form
In this latter case the compiler will locate the class by searching all the namespaces that have been mentioned in a using command. If it finds a class named Form in more than one of these namespaces, it will generate a compilation error - in that case you would need to use the fully-qualified name in your source code.
Note that the only purpose of the using command in this context is to save you typing and make your code simpler. It doesn't, for example, cause any other code or libraries to be added to your project. If your code uses base classes or any other classes that are defined in libraries (recall in .NET these are stored in assemblies), you need to ensure separately that the compiler knows which assemblies to look in for the classes. If you are compiling from the Visual Studio developer environment, this is done through the project references, which are listed in the Solution Explorer window, as shown in this screenshot:

Some references are inserted automatically when your project is created - which ones depends on the type of project, and you can add others using the Project | Add Reference menu. The screenshot shows the situation for a newly created C# Windows Application. (Note that although it is assemblies rather than namespaces that are referenced, the solution explorer shows the namespaces that are found in these assemblies. A given assembly can contain more than one namespace and vice versa.)
If you are compiling from the command line then the assembly mscorlib.dll, which contains some of the most important base classes, is referenced implicitly. You will need to indicate any other assemblies to be referenced with the command line parameter /r, supplying the full file system path to the assembly. For example for the above project, the appropriate command is:
csc ReadFile.cs /r:c:\WinNT\Microsoft.NET\Framework\v1.0.2204\System.Drawing.dll
/r:c:\WinNT\Microsoft.NET\Framework\v1.0.2204\System.WinForms.dll
/r:c:\WinNT\Microsoft.NET\Framework\v1.0.2204\System.Data.dll
/r:c:\WinNT\Microsoft.NET\Framework\v1.0.2204\System.Diagnostics.dll
/r:c:\WinNT\Microsoft.NET\Framework\v1.0.2204\System.dll
/r:c:\WinNT\Microsoft.NET\Framework\v1.0.2204\Microsoft.Win32.Interop.dll
Now we've understood the concept of a namespace we can go on to look at the namespaces that contain the various base classes.
Using Aliases
If you have a very long namespace and you want to use it several times in your code, then you can substitute a short word for the long namespace name which you can refer to in the code as often as you want. The advantages of doing this are that the code becomes easier to read and maintain and it saves you typing out very long strings.
The syntax for declaring an alias is:
using Alias = Wrox.SampleCode.CSharpPreview.Examples;
and this sample code illustrates how you can use an alias:
namespace Wrox.SampleCode.CSharpPreview
{
using System;
using MathEx = Wrox.SampleCode.CSharpPreview.Examples;
namespace ChBaseClasses
{
public class clsExample1
{
public static void Main()
{
MathEx.clsMath MyMathClass = new MathEx.clsMath();
Console.WriteLine(MyMathClass.Add(3,4));
}
}
}
// The alias MathEx refers to this namespace
namespace Examples
{
public class clsMath
{
public int Add(int x, int y)
{
int z = x + y;
return (z);
}
}
}
}
The Base Classes