In my previous article, I mentioned that VB.NET has brought numerous changes to the way classes worked with VB6. Let's jump into some of these changes now and take a more detailed look at what's going on. We'll start with a quick definition of what it means to be a class.
If I were to take you back to college, walk you into a classroom, and ask you to explain what a class is, you would probably say something along the lines of, "A class is a group of students." If so, you would have said exactly what I wanted: a group. That one word is the key. Think of classes in object-oriented programming as a way to store data and give coherent functional abilities to a group of related code. Classes are the nucleus of object-oriented programming.
Pruning source trees with .NET
One of the first noticeable differences between classes in VB6 and VB.NET has to do with syntax: There is no Set keyword. Beyond this, the way you define a class in code has changed. This will affect the way you organize your source tree more than it will directly affect the code you write.
In VB6, each class had to be added and defined within the context of an individual source file. With VB.NET, this is no longer the case. Instead, a class is defined by a code block, as you can see here:
Public Class MyClass
'Class Members go in here!
While a few of you may be on the floor frothing at the mouth at such a revolutionary change, most of you probably either don’t care or simply wonder where and how classes defined as code blocks would be useful. Truth be told, it's all about preferences. Some people like and expect each class to be in a separate file (and it can still be that way), while others like to logically group their classes. For instance, if you had a product class that had a corresponding products collection class, you might put them in the same file to better organize your source tree.
"'Structors"—everything old is finally "New"
When a class instance is created in your code, a special method of that class, called the constructor, is called. Likewise, when the class is destroyed, the destructor method is called. These are general terms and usually not the actual member names in most object-oriented languages. I like to collectively refer to both of these using the term 'structors. In VB6, you probably knew these 'structors by the names Class_Initialize and Class_Terminate. In VB.NET, the Class_Initialize method has been renamed New, and Class_Terminate is now Finalize.
VB6's implementation of class constructors was limiting in that it did not allow you to add parameters to this method. However, VB.NET brings support for parameters in the constructor method. In VB.NET, you are now free to add parameters to this method and even use method overloading on it.
For an example of how flexible parameterized constructors can make a class, think about the ADO Connection class. In VB6, you would instantiate the class and then define the connection using the ConnectionString property separately in your code. In VB.NET, the constructor for this class is parameterized and overloaded, allowing you to pass in a connection string when you instantiate the object, so you do not have to worry about setting it later in your code. You could also do things the old-fashioned way: Pass no parameters and set the connection string value later in your code.
Don't tread on that field; it's my property
While doing peer reviews, one place I consistently see a lot of confusion is with properties. Their appropriate use seems to evade far more smart people than seems justifiable, considering how simple they really are. The easiest way to talk about properties is to get back to the basics: A property is a piece of data contained within a class that has an exposed interface for reading/writing. Looking at that definition, you might think you could declare a public variable in a class and call it a property. While this assumption is somewhat valid, the true technical term for a public variable in a class is a field. The key difference between a field and a property is in the inclusion of an interface. I'll hold off on explaining why that's desirable for the time being and instead address syntax.
In VB6, properties were defined and manipulated with individual Let, Get, and Set procedures. In VB.NET, the syntax has changed. Properties are grouped into a single Property code block with individual code subblocks for the writing (Set) and reading (Get) of the property. These routines act as an abstraction layer above a private variable in your class. Most people tend to name these private variables the same as the public property, prefixing them with a lowercase m or with an underscore to differentiate them from their associated properties. (The m prefix is a holdover from VB6, meaning "module-level variable.") Here's an example:
Private _ContactName As String
Public Property ContactName()
_ContactName = Value
I've created a property in a hypothetical class called ContactName. To support this property, I need a variable that will store its actual value somewhere in my class. The _ContactName private variable does this. Whenever I retrieve or set the property, I am indirectly working with this value.
So why is this better than using fields? The big reason is that with a field, you have no control over the data written to the variable. Someone could try to place a string in your integer field or try to set the value of the field when you intend it only to be read. With properties, you can add logic to the Set routine that will ensure that the value given is valid. You can even omit the Set code block entirely and make the property read-only.
You have such wonderful attributes
Finally, .NET provides us with something called an attribute. If a class is marked with an attribute, it is granted certain abilities that are not otherwise allowed. One of my favorites is the Serializable attribute:
Public Class MyClass
'This class can be serialized!
By marking my class with this attribute, I can take an instance of my class in whatever state it is in and write it out to disk. At some later time, I can then deserialize the class, and it will act as if it were simply stored in memory the whole time. The .NET Framework offers numerous attributes, and you can even create them yourself in VB.NET.
Expect an inheritance
As you can see, there are significant changes in the way classes work in VB.NET. In the next article, I will continue to look at these changes, focusing on the issue of inheritance. Most VB programmers probably know about inheritance, but they may never have had to use it. I will explain how—and more importantly, when—to do so.