Ways to Implement Component Functionality
You will frequently find it useful to create utility functions and small "helper" objects for your components. You can implement such utility objects and functions using classes and structures. Additionally, in Visual Basic you can implement modules.
Visual Basic Note In previous versions of Visual Basic, classes were the only way to expose component functionality. Standard modules were useful receptacles for internal data and utility functions, but could not be exposed outside the project. User-defined types could be exposed, but had no functionality other than providing complex data types. These restrictions have been removed.
Classes have the advantage of being reference types — passing a reference is more efficient than passing a structure variable with all its data. On the other hand, structures do not require allocation of memory on the global heap.
The following table summarizes the differences between the ways of implementing component functionality. In C# the access modifiers (Public, for example) are lowercase (public).
|Class||Structure (struct)||Module (Visual Basic only)|
|Default access level for the type||Friend/internal||Friend/internal||Friend|
|Default access level for data members||Private||Public (Visual Basic .NET)
private (Visual C#)
|Default access level for properties and methods||Public (Visual Basic)
private (Visual C#)
|Public (Visual Basic .NET)
Private (Visual C#)
|Value or reference type?||Reference||Value||Neither|
|Can be a base for new types?||Yes||No||No|
|Can implement interfaces?||Yes||Yes||No|
|Can raise and handle events?||Yes||Yes||Yes|
|Scope of members||Class||Structure||Module and containing Namespace|
|Instance creation?||New operator (Visual Basic)
|New operator (Visual Basic)
|Type initialization||Shared constructor, shared initializers||Shared constructor, shared initializers||Shared initializer|
|Instance initialization||Parameterized constructor, parameterless constructor||Parameterized constructor, parameterless constructor||Not instanced|
|Can contain nested types?||Yes||Yes||Yes|
|Can be a nested type?||Yes||Yes||No|
Structures are value types — that is, a variable of a structure type contains the structure's data, rather than containing a reference to the data as a class type does. Structures can have properties and methods, can raise and handle events, and can implement interfaces.
Visual Basic Note Previous versions of Visual Basic provided a Type statement for defining structures. The Structure statement adds many new capabilities. For details, see Structure Statement.
- A structure has an implicit parameterless constructor, which initializes each data member of the structure to the default value for its type.
Note This means that you cannot declare your own parameterless constructor for a structure.
- In addition to its defined members, a structure includes the members of System.ValueType.
- Because you cannot inherit from a structure, Protected access is prohibited on structure members.
- Unlike a class, a structure does not have a finalizer (Sub Finalize in Visual Basic).
- You can use Public Shared (public static in C#) members to provide utility functions related to a type. Shared (static) members can be called using the type name; no instance of the type is required.
Visual Basic Note Data members in structures must be declared with the Dim statement, or with Public, Private, or Friend. This is a change from the user-defined types in earlier versions of Visual Basic.
Although a structure can have properties, methods, and shared data, these do not affect the space occupied by a variable of the structure type. The space allocated for a structure is only as large as the structure's instance data.
When Should You Use a Structure Instead of a Class?
Because you cannot inherit from a structure, structures should be used only for objects that do not need to be extended. Use structures when the object you wish to create has a small instance size, and take into account the performance characteristics of classes versus structures. In general, objects requiring a larger instance size should be created as a class. Structures with large instance sizes cause degradation in performance as the instance data is passed from method to method. Depending on how the structure is allocated and used, however, a structure may be more efficient even with a larger instance size. For example, a structure allocated and passed around inside an array can be efficient.
In addition to providing all the capabilities of structures, classes can be extended and they have finalizers.
Classes Can Be Extended
By default, your component can be a base class for new components. If you do not want to invest the additional development and testing time to ensure that your component can function as a robust base class, you can mark your class NotInheritable (Visual Basic) or sealed (C#) to prevent users from extending its functionality.
You can also author a component whose sole purpose is to be a base class for other components, by marking it MustInherit (Visual Basic) or abstract (C#). Users of your assembly cannot create instances of an abstract (MustInherit) class; they must derive new component classes from it. For details, see Abstract Classes.
Note When you include an abstract component in your assembly, or any component you intend users to inherit from, you should provide documentation for your component.
Before garbage collection frees the memory used by an object, the class finalizer is called. This gives you the opportunity to do any necessary cleanup. However, because of the indeterminate nature of garbage collection, you have no way of knowing when your finalizer will be called. If you want to be able to control when your component terminates, you should implement a Dispose method for it. For details, see Initialization and Termination of Components.
Importing Shared Class Members (Visual Basic Only)
Users can import the Public Shared members of a class so that they can be accessed without qualification. The following example makes the public shared members of the Mortgage class available without qualification.
' Visual Basic Imports MyCorp.Financials.Mortgage
Modules (Visual Basic Only)
Modules provide a simple way to organize utility functions and global data used by the components in your assembly.
- A member of a module can be accessed without qualification within the namespace that contains the definition of the module and within any file that has imported that namespace. If members with duplicate names exist in two modules, you can qualify them with the module names to resolve the ambiguity.
- A module must be a member of a namespace. It cannot be a member of another type, such as a class.
- Modules are not instanced and are functionally equivalent to classes containing only shared members.
- A module cannot have an instance constructor.
If a module is declared Public, its public members are visible outside your assembly. In order to access these members, a user of your assembly must qualify them with the name of the module.