The Anatomy of a Visual Basic Project
- Brief Overview of Types and Members
- Visual Basic 2010 Reserved Keywords
- Understanding Project Files
- Understanding References
- Summary
IN THIS CHAPTER
- Brief Overview of Types and Members
- Visual Basic 2010 Reserved Keywords
- Understanding Project Files
- Understanding References
Brief Overview of Types and Members
In the second part of this book, we discuss important topics related to the object-oriented programming with Visual Basic 2010, and we explore features such as types, classes, modules, namespaces, interfaces, and class members. Before going into this, it would be a good idea to have at least an overview of classes, modules, namespaces, and class members because you will find these objects in code examples or in Visual Basic features that are shown prior to Chapter 7, "Class Fundamentals."
Classes
Classes in .NET development represent objects whose declaration is enclosed within Class..End Class blocks. The following is an example of class declaration:
Class Person End Class
Classes are reference types (explained more in Chapter 4) and can expose members that influence the object's behavior, such as properties and methods. Classes can implement interfaces and they can also be static (or Shared according to the VB terminology) and can provide support for inheritance.
Properties
Properties are characteristics of a type. For example, the previously shown class Person could have two properties, such as the first name and the last name:
Class Person Property FirstName As String Property LastName As String End Class
Methods
Methods are the .NET representation of what in other programming environments you define as functions and procedures. A method can be a member of classes, structures, and modules. Methods that return a value are represented by Function..End Function blocks, such as the following:
Function DoSomething() As String Return "A text message" End Function
Methods that do not return a value are represented by Sub..End Sub blocks, such as the following:
Sub DoSomething() 'write your code here End Sub
Methods can receive parameters that can be processed within code blocks. Such parameters are called, using .NET terminology, arguments. The following code block shows an example of an argument named message:
Sub DoSomething(ByVal message As String) Console.Writeline(message) End Sub
Modules
Modules are defined within a Module..End Module code block. Modules are basically Shared classes but, unlike classes, they cannot implement interfaces. The following is an example of a module:
Module Module1 Sub DoSomething() 'Code goes here End Sub End Module
Members defined inside modules don't require the name of the module when invoked.
Structures
Structures are .NET objects represented by a Structure..End Structure code block. Structures are value types, which are described more in Chapter 4, and for classes, can expose properties, methods, and so on. The following is an example of a structure declaration:
Structure SomeValues Property FirstValue As Boolean Property SecondValue As Integer Sub DoSomething() End Sub End Structure
Inheritance
Inheritance is one of the most important features of the .NET Framework. A class can inherit or derive from another class, meaning that the new class can have all properties, methods, and members exposed by the first class, which is called base class, and can then define its own members. Inherited members can then be overridden to adapt their behavior to the new class' context. The .NET Framework provides one-level inheritance, meaning that a class can inherit from one other class per time. Each class derives implicitly from System.Object. The Inherits keyword is used to inherit classes. The following code provides an example of a base class named Person and of a derived class named Customer:
Public Class Person Public Property FirstName As String Public Property LastName As String 'A new definition of System.Object.ToString Public Overrides Function ToString() As String Return String.Concat(FirstName, " ", LastName) End Function End Class Public Class Customer Inherits Person Public Property CompanyName As String Public Overrides Function ToString() As String Return CompanyName End Function End Class
In the preceding example the Person class overrides (that is, provides a new definition of) the System.Object.ToString method. The Customer class exposes a new CompanyName property whereas, via inheritance, it exposes the FirstName and LastName properties. Finally, the class also overrides the Person.ToString method. Inheritance is discussed in Chapter 12. "Inheritance."
Namespaces
A namespace is basically a container of types. This means that one namespace can contain multiple classes, multiple modules, multiple interfaces, multiple structures, and so on. The following is an example of a namespace exposing two classes, one module, one structure, and one interface:
Namespace Test Class Person Property FirstName As String Property LastName As String End Class Class Employee Inherits Person Property EmployeeID As Integer End Class Module Module1 Sub DoSomething() End Sub End Module Interface ITest Sub TakeATest() End Interface Structure SomeValues Property FirstValue As Boolean Property SecondValue As Integer End Structure End Namespace
Namespaces are important for a better organization of types, but there is another reason. You could have two classes with the same name (for example, Employee) but with different properties. Namespaces enable you to avoid conflicts in such scenarios. You can access types exposed by a namespace by simply writing its identifier followed by a dot and then by the type name. For example, if you want to invoke the method DoSomething in Module1 you could write the following line of code:
Test.Module1.DoSomething()
Namespaces are described in detail in Chapter 9, "Organizing Types Within Namespaces."
Accessing Members
Unless you declare shared objects, you need to instantiate classes and structures before you can use members and store information within those objects. You instantiate a class declaring a variable and using the New keyword as in the following line of code:
Dim testPerson As New Person
Then you can set properties for the new instance or eventually invoke other members such as methods. For example, you could initialize testPerson's properties as follows:
testPerson.FirstName = "Alessandro" testPerson.LastName = "Del Sole"
Basically when you need to invoke a member of a class, you type the name of the instance (in this example testPerson) followed by a dot and by the name of the member. For shared members, you just write the name of the class or structure followed by a dot and by the name of the member.
Imports Directives
As we saw before, namespaces can expose objects that expose members. Moreover, namespaces can expose nested namespaces, exposing objects and so on. You often need to access members of objects exposed by nested namespaces. To avoid the need of typing the entire name of long (or nested) namespaces and writing long lines of code, the Visual Basic language offers the Imports directive. For example, consider the following lines of code that open a file on disk:
Dim myFile As New System.IO.FileStream("C:\test.bin", IO.FileMode.Open) myFile.Close()
The FileStream class is exposed by the IO namespace that is exposed by the System namespace. You could place the following directive at the beginning of the code:
Imports System.IO
At this point the first line of code could be rewritten as follows:
Dim myFile As New FileStream("C:\test.bin", FileMode.Open)
Imports directives are useful because they help to handle a much clearer code. Just remember that such directives must be the first lines of each code file. The only exception is constituted by the Option clause that must precede the Imports directives.
#Region..#End Region Directives
Visual Basic provides an efficient way for organizing your code within regions. A region represents a collapsible area of the code editor that can contain any code and that takes the advantage of the outlining feature of the Visual Studio 2010 code editor. Regions are defined with #Region..#End Region directives. The following code snippet shows how to define a region:
#Region "Private Members" Private firstItem As String Private secondItem As Integer #End Region
The #Region directive requires the specification of a descriptive caption. When you declare regions, you can then collapse regions by clicking on the - (minus) symbol on the left of the #Region directive. When collapsed, the region shows just the descriptive caption and can then be expanded again by clicking on the + (plus) symbol. Also notice that the Visual Studio 2010 IDE allows collapsing a region by double-clicking anywhere on the #Region..#End Region connector line on the left side of the code window. Such directives will not be compiled and will not affect performances at all.
Attributes
Attributes are classes deriving from the System.Attribute class and provide declarative information to objects or members they are applied to, providing also the ability to change their behavior. As a convention, applying an attribute is also known as decorating or marking a member. Attributes are basically class instances; you can apply attributes enclosing their names within < > symbols; moreover they can receive arguments. The following are examples of decorating members with attributes:
<Serializable()> Class Test End Class <CLSCompliant(True)> Class Test End Class
In the preceding snippets, the Serializable attribute creates a new instance of the System.SerializableAttribute class that indicates to the compiler that the decorated class can take advantage of the serialization process. The CLSCompliant attribute, whose value is True, means that the decorated class is compliant to Microsoft's Common Language Specifications. Attributes are discussed in Chapter 48, "Coding Attributes," and you often find examples in this book that require code to be decorated with attributes.
A New Feature: Implicit Line Continuation
Visual Basic 2010 introduces an important new feature when writing code (which is a historical change in the language) known as implicit line continuation. Back in older versions, if you needed to split a long line of code into more brief and readable lines of code in the editor, you needed to add an underscore ( _ ) character. With Visual Basic 2010 this is no longer necessary, with a few exceptions. You can simply press Enter when you need to split a line of code, and the compiler will automatically recognize a line continuation, depending on what kind of code you are writing.
The following are situations in which the implicit line continuation is allowed:
- Within LINQ queries
- Within embedded expressions in LINQ to XML queries
- After dots
- After commas
- After brackets
- When decorating members with attributes
- Before an assignment
Let's see how implicit line continuation works. The first code snippet shows a LINQ query:
Dim query = From proc In Process.GetProcesses.AsEnumerable Where (proc.ProcessName.StartsWith("A")) Select proc
In Visual Basic 2008 you needed to add an underscore after the first and second line of code. Now this is no longer necessary. The second code snippet shows a LINQ to Xml query with embedded expressions without underscores:
Dim doc = <?xml version="1.0"?> <Processes> <%= From proc In query Select <Process> <Name <%= proc.ProcessName %>/> </Process> %> </Processes>
The third code snippet shows both commas and brackets without underscores:
Dim p As New List(Of Integer) From { 1, 2, 3, 4}
The fourth code snippet is about dots. In this case implicit line continuation can be useful when invoking methods or properties:
Dim appDataDir As String = My.Computer.FileSystem. SpecialDirectories.AllUsersApplicationData()
The fifth code snippet shows implicit line continuation with attributes:
<CLSCompliant(True)> Class Test End Class
The sixth and last code snippet demonstrates how you can use implicit line continuation before an assignment:
Dim aValue As Integer aValue = 10
All the preceding code snippets are now perfectly legal. In all cases of the preceding examples, implicit line continuation is not allowed. For example, you still must add an underscore after the Handles clause when handling events:
Private Sub AnEventHandler(ByVal sender As Object, ByVal e As EventArgs) _ Handles anObject.Disposed End Sub
Although you might expect such discussion in Chapter 2, "Getting Started with the Visual Studio 2010 IDE," about the code editor, you first need to get an overview of concepts that help you understand where implicit line continuation is allowed or disallowed.