- Introducing the Framework Class Library
- Enhancing Developer Productivity
- The Elements of a Namespace
- Programming with the Framework Class Library
- Summary
The Elements of a Namespace
Each namespace can define its own set of classes, structures, delegates, interfaces, and enumerations. And, as we have seen with the System namespace, they can also sometimes contain value types. Let's examine each one of these in turn.
Classes
As we discussed in Chapter 3, a class is a template or blueprint for an object. It defines how an object should look and behave. It does this principally through methods, properties, and events.
If you have read on from the last chapter or have some experience with object-oriented programming, you should be familiar by now with the concepts of classes. You should note, however, that the .NET runtime supports some class attributes that you may not be familiar with. These attributes are summarized in Table 4.2.
TABLE 4.2 .NET Class Attributes
Class Attribute |
Description |
Sealed |
Specifies that you cannot inherit from this class. A good example of a sealed class in the Framework Class Library is the String class. In Visual Basic .NET you can create your own sealed classes by using the NotInheritable keyword. |
Implements |
Specifies the interfaces implemented by a particular class. For instance, the Array Class implements the Ilist interface, imbuing Arrays with the capability to add members and retrieve the index of a member. |
Abstract |
Indicates that the class cannot be directly instantiated. They typically exist as a means of organizing lower-level derived classes, or as a convenient virtual class that is used solely as a template for other classes instead of instances. Examples of abstract classes include the XMLWriter class in the System.XML name-space, and the Image class in the System.Drawing namespace. |
Inherits |
Identifies the base class that the current class inherits from. As an example, the ColorDialog Class inherits from the CommonDialog classan acknowledgment of the fact that it is a type of common dialog. |
Exported/Not Exported |
Indicates whether a class is visible outside of its defining assembly. Exported classes are those visible outside of the assembly in which they are defined. |
Classes typically define a constructor; this is a specialized behavior of a class that is called whenever a new instance is created from that class. In Visual Basic .NET, you will define your constructors using the Sub New routine. Class_Initialize and Class_Terminate events are no longer supported. Classes may also implement destructors that will be called when the object is being destroyed.
Object destruction in .NET works a little bit differently than you have come to expect. .NET implements something called a garbage collector. The garbage collector continually examines a "reference tree;" if it finds an object that doesn't have any more branches on the reference tree, it calls the destructor of that object. It is no longer necessary to explicitly destroy managed objects; the garbage collector will take care of it for you.
NOTE
If your class uses resources that are unmanaged in nature, you should implement a Finalize method. This method, which is not public, will be called by the garbage collector as it destroys unneeded objects. If you need to provide a public method for freeing resources (such as a Close method for your class), you should implement the IDisposable interface.
All objects in the .NET Framework inherit from the System.Object class. System.Object is the ultimate superclass in the Framework Class Library.
Structures
Structures are the .NET version of user-defined types from prior versions of Visual Basic. User Defined Type (or UDT) syntax in Visual Basic, versions 6 and earlier, looked something like this:
Type InventoryItem SKU As String * 50 Price As Single Name As String * 25 Count As Integer End Type
The metamorphosis into structures means the Type...End Type syntax is no longer supported. It has been replaced with Structure...End Structure:
Structure InventoryItem Public SKU As String Private Price As Single Public Name As String Private Count As Integer End Structure
Note that with structures, each structure element can have its own scope modifier (for example, can be public, private, and so on). This was not previously possible with UDTs.
And that's not all that has changed. Structures in .NET behave a lot like classes. They support most of the constructs of a class including properties, methods, and events. Table 4.3 summarizes some of the key similarities and differences between classes and structures.
TABLE 4.3 Structures versus Classes
|
Class |
Structure |
Allows parameter-less constructors? |
Yes |
No |
Supports properties, methods, and events? |
Yes |
Yes |
Can be inherited from? |
Yes |
No |
Can implement interfaces? |
Yes |
Yes |
Support for destructors? |
Yes |
No |
In the class library, structures are used to represent value types such as integers (Int16, Int32, Int64). In fact, the actual structure object inherits directly from the class ValueType in the root System namespace.
Delegates
Delegates may be an unfamiliar concept to the average Visual Basic developer. In essence, delegates are function pointers: They encapsulate method calls to other objects. Delegates are described by the parameters they accept and the value type they return. In other words, you can declare a delegate that will map to a method call that takes an integer and a single and returns a string:
public delegate myDelegate(value1 As Integer, value2 As Single) As String
To use the delegate, you would declare a variable that references the delegate like this:
Dim myCallback As myDelegate = New myDelegate(obj.SomeMethod)
If the SomeMethod method that you reference has a function signature that matches the definition of myDelegate, you are home free, otherwise an error will be raised.
One of the powerful capabilities of a delegate is its ability to perform its function pointing in a late bound fashion. You can use the preceding delegate to map to any method that follows the parameter and return type signature; you don't need to explicitly make a tie between the delegate and a specific function at design time.
Delegates are defined throughout the Framework Class Library namespaces and fulfill a variety of different tasks, most associated with implementing designs regarding callbacks and event processing.
Interfaces
An interface is most commonly described as a contract. If you implement an interface, you are essentially entering into a contract with all other components that exist that says, "I agree to provide the following functionality in the following manner forever and ever...." Interfaces can have methods and properties just like classes.
You can implement interfaces defined in the Framework Class Library by using the Implements keyword:
Public Class Class1 Implements IDisposable Public Sub Finalize() Implements IDisposable.Dispose . . . End Sub End Class
This code snippet shows a class implementing the IDisposable interface.
Back when we talked about inheritance and code reuse in Chapter 3, we said that interfaces provide a good structure for implementing code belonging to a class that isn't necessarily "logically" related to our core class.
This kind of code reuse keeps our class hierarchies from becoming cluttered with seemingly random inheritance relationships.
NOTE
There are some design considerations to think about when deciding between class inheritance and interface implementation. For instance, because interfaces are meant to be binding and perpetual contracts, they can't (or shouldn't) be changed. Implementing code in an interface that is likely to change, such as business rules, leads to a very brittle architecture. You don't have this concern with class inheritance because methods and properties can always be added to a base class without "breaking" its descendant classes.
Enumerations
An enumeration is essentially a named constantit is an aid to developer productivity because it allows you to reference values using a recognizable name. Using enumerations greatly improves code readability and speeds up coding because they provide a way to name or reference a value that maps to one of the underlying data types defined by the CTS. Visual Basic developers should be familiar with the concept of "enums"the syntax has not changed moving into Visual Basic .NET. The .NET runtime allows enumerations to evaluate to any of the signed or unsigned integer data types that are defined (such as Int32, Int64, and so on).
As far as the Framework class library is concerned, enumerations are in many of the name-spaces. One example of an enumeration in the class library is Appearance, contained in the System.Windows.Forms namespace.
To use an enumeration from your code, simply reference the enumeration's name and the value name that you want to use:
myButton.Appearance=Appearance.Button
In the preceding code, we use the Appearance enumeration to specify that the button control we are using should take on the "Button" appearance.
Enumerations are derived from the System.Enum class, which means you can reference enumerations in some very cool ways. For instance, you can call the GetValues() method to get an array of all values defined by an enumeration. You can also call the GetNames() method to get an array of all names for the values defined by an enumeration.