1
1
Frequently, example code contains lines in bold text. These lines are in
bold to draw the reader’s attention to them. The reason for this is because
the focus of the example and the corresponding explanation is centered
around these lines. As you go through the book and the examples, pay
particular attention to reviewing the highlighted lines of code in order to
understand and absorb the meaning of each of the examples.
The output of an example is indentified by the icon shown at left of this
sentence.
OUTPUT
NOTE
Notes add more information about the material just presented. These notes clarify con-
cepts and procedures.
TIP
Tips provide shortcuts or workarounds to a particular problem.
CAUTION
Cautions provide warnings regarding things to watch out for. These should save you
time and trouble.
What’s Next
The book starts with an overview of Microsoft .NET and what it is all
about. Then you take a tour of the Visual Studio .NET environment so that
you can become familiar with the development environment used through-
out the book.
Part I
Introduction
Visual Basic 6 users will see that Visual Basic .NET is not just an upgrade
from Visual Basic 6. Instead, it catapults the Visual Basic language into a
much broader arena that allows you to create many types of applications
previously too difficult (if at all possible) to implement using previous
versions of Visual Basic. If this is your first introduction to Visual Basic,
welcome aboard and enjoy the ride. Hopefully you will find Visual Basic
.NET to be a powerful language that will empower you to build world class
applications.
Visual Basic has come a long way since its infancy. Visual Basic (or VB for
short) has traditionally been a language that simplifies the development
of software applications that run on Microsoft Windows. This includes
Windows 3.1, Windows 95, Windows 98, Windows NT, and most recently
Windows 2000. The most common types of applications written in Visual
Basic have been standalone applications that run on a single computer. An
example of a simple application is the Calculator program, as shown in
Figure 1.1, that comes with Microsoft Windows. Using VB, you were able to
develop applications in a very short amount of time. Before VB, one would
need to write an application using a more complicated language, such as C
or C++, which would require a steeper learning curve and more develop-
ment time. A new VB developer could write a simple application faster than
a moderate C developer. As a result of VB’s productivity enhancement bene-
fits, VB became a very popular language.
a single database could be used by many users, which meant the data could
also be shared by those users. These types of applications are called client-
server applications. The program itself is the client and the database is the
server. Figure 1.2 depicts a client-server application where an application
running on one computer communicates with a database running on
another computer.
Network
Database
User’s Computer
Network
Database
COM started out with the goal of supporting the development of compo-
nents that can easily be shared among different applications. These compo-
nents can be built and installed on computers as basic building blocks that
are used by applications. A simple example of a component is a credit card
number verifier. By writing code to verify credit card numbers and placing
this code in a component, applications then are able to share this compo-
nent and reduce complexity and maintenance costs along the way.
As the paradigm of building applications changed from applications
running on a single computer to client-server and then to n-tiered (or
multi-tiered) computing, COM has been trying to keep up. Microsoft has
recognized that in order to facilitate the development of n-tiered applica-
tions, Web applications, and beyond, it had to redesign some of its architec-
ture and way of building applications. To that end came Microsoft .NET,
which is a new platform for building distributed Web applications. Visual
Basic .NET is the successor to Visual Basic 6.0 that allows you to build
applications that support Microsoft .NET.
I am assuming you have heard something about Visual Basic .NET by now
(based on the fact that you bought this book), but what exactly is it? What
does it really mean? And, most importantly, what does it mean to you?
The Visual Basic language has undergone some major structural changes in
order to address some of the deficiencies of the previous Visual Basic ver-
sions. With Visual Basic .NET, you are now able to develop standalone
applications like before plus you can now create Web applications and Web
services. The specifics of these are explained throughout the book. Before
getting deeper in Visual Basic .NET, you need to better understand where
Visual Basic .NET fits into Microsoft’s .NET strategy as this will be impor-
tant when you start writing .NET applications.
Introduction 11
Let’s start by defining these three Microsoft terms: Microsoft .NET, Visual
Studio .NET, and Visual Basic .NET.
(CLR), which has automatic support for safe, secure (otherwise referred to
as “managed”) code and garbage collection.
The .NET Enterprise Servers are designed to be very scalable and suitable
for Enterprise applications, which tend to have very strict requirements for
stability. The .NET Framework includes a common library of services that
can be leveraged independent of the device the software is running on. This
allows you to develop software using the .NET Framework and have it run
on a device that supports the .NET Framework. This includes a PC, cellu-
lar phone, pager, PDA, and other Internet-ready devices.
The XML Web Services are a set of building block services that can be con-
sumed by applications built on Microsoft .NET technology. Microsoft will
provide many services and other vendors will provide even more. At some
point there will be a wealth of services to choose from that can be brought
together as part of a Web solution, a solution that would be too complex
and unwieldy if it were based on the current Microsoft technology. Microsoft
.NET greatly simplifies the development and deployment of these services.
The .NET device software enables new kinds of Internet devices to use Web
services. This allows the development of new solutions using additional
types of devices beyond that of the PC. Microsoft is currently engaging in
writing software that supports many types of devices. This includes any-
thing from cellular phones to PDAs.
The .NET User Experience will be much different than today’s user staring
at a computer screen. The applications built on Microsoft .NET can provide
a user experience that transcends computer boundaries by providing differ-
ent application views on a variety of different devices. For example, you
may trade stock on your computer at home, view email from your cellular
phone, transfer funds from your Personal Digital Assistant (PDA), and get
a meeting reminder on your pager. All of these services can be part of the
same overall solution built on .NET.
The complete .NET package means that you can easily create a much
richer solution for your users, and deploy that solution in a scalable and
reliable environment. It also means you can leverage existing services or
provide new services. And, you will start to see a wider variety of devices in
conjunction with Web solutions. This allows for the construction of new
types of applications not dreamt of before.
The purpose of this chapter is to give you a basic idea of the big picture of
.NET. However, the purpose of this book is to teach the reader Visual Basic
.NET. If you require more information on other aspects of .NET please refer
to www.microsoft.com/net.
Tour of Visual Studio .NET 13
Studio .NET opens for the first time, you are presented with the default
Start Page, which looks similar to the one in Figure 1.4.
Solution Explorer
Main menu
Toolbar
Start Page
At first sight, Visual Studio .NET looks very much like other software
development tools in that it has menus, toolbars, and a variety of windows
for handling specific tasks. However, the more I use it the more I appreci-
ate the power of this tool.
TIP
If the Start Page is not immediately visible to you, it can be opened again using the
Help menu. Select Help, Show Start Page.
Menus
As with most software applications, Visual Studio .NET has a set of menus
and toolbars to help you in your work. Take a minute to scan the menus by
clicking on the word File to display the File menu. Then move the mouse
left to right to view the submenus. Each of the menus and their functions
are explained throughout the book. That way their meaning can be intro-
duced and explained in the context of relevant examples.
Tour of Visual Studio .NET 15
Notice some of the menu items are grayed out. This is because those menu
items are not currently available. Menu items are available or unavailable
based on the current state of your work and based on the type of work you
are currently doing. For example, the menu item Close Solution is grayed
out because you have not opened a solution yet. Keep this in mind if you
run into other menu items that are grayed out. Figure 1.5 shows the File
menu.
non-grayed
grayed out items out items
Toolbars
Toolbars contain a group of related buttons that each perform a specific
task when clicked with the mouse. Figure 1.4 shows the standard toolbar
that is visible when you first open Visual Studio .NET. It is displayed
immediately below the Visual Studio menus.
You can rearrange the toolbars by clicking and holding the mouse button
down on the grab bar at the left of the toolbar. To locate the grab bar, hover
your mouse at the left end of the toolbars until the cursor changes to a
cross. While holding down the mouse button, you can move the toolbar to a
new location. If you drag the toolbar off the toolbar area, the toolbar will
stay floating over the application. Whether you want the toolbar fixed at
the top of the main window or floating is strictly a user preference.
You also have the capability to specify which toolbars are displayed and
which are not. If you right-click the mouse in the toolbar area you will see
a list of available toolbars as shown in Figure 1.6. You can get the same
list by clicking on the View, Toolbars menu item. The ones with the check
marks on them are currently visible. The remaining ones are not visible.
16 Chapter 1: Overview of the Environment
If you want to make one visible, simply click the one on the list you wish to
make visible. We recommend that you leave enabled the toolbars that are
visible by default (when you opened Visual Studio .NET for the first time),
until you get more familiar with the environment. The same idea applies to
all the other customizable settings for the environment—stay with the “fac-
tory” defaults until you have a better understanding of what the specific
settings mean.
VS Start Page
The VS Start Page is your main starting page when working with Visual
Studio .NET. The left side of the VS Start Page window contains a list of
sections as shown in Figure 1.4. You can click on each of these sections to
display relevant information on the right side of the window pertaining to
the selected section.
The Get Started section allows you to open recently used projects, open
existing projects (any project that you can navigate to using the File
Explorer), or create a new project. The recently used projects are shown
directly on the window so that you can quickly open the project (or projects)
you have been working on. This saves time by not having to keep searching
for the project and its location every time you open Visual Studio .NET.
Tour of Visual Studio .NET 17
The What’s New section shows a list of help topics describing new features
and changes in Visual Studio .NET. If you are currently a Visual Basic 6
user this may be helpful if you want to jump right in and find out only
what’s new without having to read the entire documentation first. If you
click on an item in the What’s New topic the relevant Web page is opened.
The Online Community section is quite nice because it shows you a list of
public newsgroups related to Visual Studio .NET. You can communicate to
other developers like yourself in the event you need answers to specific
technical questions or you can just browse the messages as a supplemental
learning exercise.
The Headlines section shows the latest MSDN (Microsoft Developer
Network) news and information. You may want to periodically view this to
keep abreast of the information and changes released by Microsoft.
The Search Online section allows you to search Microsoft’s online MSDN
database. This can be very useful when you start to develop your own soft-
ware. The database contains a wealth of information including articles and
code examples. If you come across something that you need more informa-
tion on you can type a few keywords into the text box and click the Go but-
ton. If there is any help available for the keywords you entered the results
will show in this window sorted by relevance.
The Downloads section provides a central place for obtaining the latest
add-ons, service packs, and product upgrades. This also includes sample
code and other various Microsoft SDKs.
The Xml Web Services section provides a convenient way for finding and
registering services that can be used in your applications. Web Services is
discussed in more detail later in the book.
The My Profile section allows you to customize Visual Studio .NET for your
use. You can specify the type of developer you are. The main benefit of this
is for the help system. When you use the help system, only information rel-
evant to your profile will show up. For example, if you are a Visual Basic
Developer and you click for help on a topic you should not see help informa-
tion pertaining to Visual FoxPro. This is a major improvement as previous
versions of Visual Basic and Visual Studio gave you mounds of help on any
given topic. This required you to weed through the results, wasting your
time.
At this point, you might want to set your profile to be Visual Basic
Developer. This basically tells Visual Studio that you are going to use
Visual Basic as your primary development language. This allows Visual
Studio to display help in the context of Visual Basic as well as laying out
the windows in a fashion that is familiar to most Visual Basic developers.
18 Chapter 1: Overview of the Environment
You also can specify the keyboard scheme. This is similar to the Profile set-
ting but instead of laying out the windows differently the keyboard map-
ping is different. If you press the F10 key, the resulting action for this key
depends entirely on the keyboard scheme you have. You can change the
window layout. If you have previously used Visual Studio or Visual Basic 6
you can specify your profile accordingly so that Visual Studio .NET lays out
its windows similar to those other tools. For example, if you set your profile
to Visual Basic 6.0 the windows are initially laid out as you would see them
in Visual Basic 6.0. The goal with this feature is so that you can continue to
use a development tool that is familiar to you. If you have not used any pre-
vious development tool from Microsoft or if you do not have any strong pref-
erence, just leave the Window Layout set to Visual Studio Default, which is
what you are going to use through this book.
Solution Explorer
Click View, Solution Explorer or press Ctrl+R to open the Solution Explorer.
This displays all the different types of elements that are part of the solu-
tion. In Figure 1.4, the Solution Explorer is empty because you have not
opened a Solution yet. In the next chapter, you will create a new Solution
and explorer the types of elements then.
There are two important icons to note in the title bar of the Output win-
dow. The icon with the “X” should be familiar to you already. It allows you
to close that particular window which makes it no longer visible. The other
icon that looks like a push pin puts the window in Auto Hide mode. This
is a very nice feature that you may find useful the more you use Visual
Studio .NET. If a window is in Auto Hide mode, the window tab is dis-
played on the outer edges of the Visual Studio environment or workspace.
20 Chapter 1: Overview of the Environment
If you move the mouse over the tab and wait a second or so (also know as
hovering) you will notice the window becomes completely visible in order for
you to interact with it. If you then move the mouse off the window, it auto-
matically hides itself again. This way you can maximize the screen real
estate as you are developing software and quickly show particular windows
when you need them.
Using Help
You will surely come across something in Visual Studio .NET in which you
need help or more information. Like any good development tool, Visual
Studio .NET comes with online help to assist you in the process of learning
the tool and developing your solution. You can access the help information
using the Help menu. This menu has four important ways of looking at the
help information. They are Contents, Index, Search, and Dynamic Help.
Contents
Click Help, Contents to open the Contents window. This shows the table of
contents for the help. The information is presented using a table of contents
approach. The information is grouped into a hierarchy list of related topics.
You can view the high-level topics and drill down to learn more. You click
on a topic to display the detailed information in the main window for the
topic. Figure 1.9 shows the Contents help window.
Index
Click Help, Index to open the Index window. This contains the same infor-
mation as the Contents window except it displays it in a different way.
Instead of showing the table of contents, it displays an alphabetical list of
detailed topics. As in the Contents window, you would click on the topic to
display the detailed information in the main window. Figure 1.10 shows the
Index window.
If you have set the Profile option in My Profile (on the VS Start Page) to
indicate the type of developer you are the help system will use this to only
display the help index relevant to you. Since this book focuses on Visual
Basic .NET you may want to set your profile to Visual Basic Developer.
This way you will only be presented with help information that is relevant
to Visual Basic.
Search
Click Help, Search to open the Search window. The Search Help window
allows you to find help about something using one word or a set of words.
Figure 1.11 shows the Search window.
22 Chapter 1: Overview of the Environment
You can search this list by typing in words in the Look For field. Press
Enter after you type in the word(s) you want to search for and the results
are displayed in the bottom section of the Index window. You would click on
an item in the results window to display the detailed information in the
main window.
Dynamic Help
Dynamic Help is new to Visual Studio .NET. If you click on Help, Dynamic
Help, this displays the Dynamic Help window. While this help window is
visible, any relevant help information is displayed for anything you click.
Figure 1.12 shows the Dynamic Help window.
It’s that simple but keep in mind that using Dynamic Help can be an inten-
sive operation for your computer. Try it out on your computer and if it
helps you then keep using it. Otherwise, do not display the Dynamic Help
window.
What’s Next? 23
What’s Next?
We have covered some of the history of the Visual Basic language and pre-
sented Microsoft .NET. You also learned about the distinctions between
Microsoft .NET, Visual Studio .NET, and Visual Basic .NET. Based on this,
you took a tour of the Visual Studio .NET development environment which
you will be using throughout the remainder of the book.
In the next chapter you create your first application so that you can intro-
duce Visual Basic .NET for the first time. This is accomplished by creating
a new project using a menu item within Visual Studio .NET. All of the
necessary files and project information is generated for you. You will go
through the generated code to highlight some of the new changes in Visual
Basic .NET. For those readers new to Visual Basic, this will also help get
you started on the road to learning and being productive with Visual Basic
.NET.
NOTE
The answers to the Reviewing It, Checking It, and Applying It are available on the book’s
Web site.
24 Chapter 1: Overview of the Environment
Reviewing It
This section presents a review of the key concepts in this chapter. These
questions are intended to gauge your absorption of the relevant material.
REVIEW
1. What is the Microsoft .NET Framework?
2. What are Microsoft .NET Services?
Checking It
Select the correct answer to the following questions.
CHECK
Multiple Choice
1. Visual Basic .NET is:
a. A development environment.
b. An object-oriented software development language.
c. A simple scripting language.
d. A financial planning application.
2. Visual Studio .NET is:
a. A development environment.
b. An object-oriented software development language.
c. A simple scripting language.
d. A financial planning application.
3. Microsoft .NET is:
a. A new operating system.
b. A new platform for developing distributed Web applications.
c. A new Internet Service Provider (ISP).
d. The new name for the bundled package of all Microsoft products.
4. The VS Start Page allows you to:
a. View and open the most recently used Visual Studio .NET pro-
jects on your computer.
b. Get help on “What’s New” and display common newsgroups that
might help in your Visual Basic .NET development.
Applying It 25
True or False
Select one of the two possible answers and then verify from the book’s Web
site that you picked the correct one.
1. The Calculator program in Microsoft Windows is an example of a Web
application.
True/False
2. Visual Basic .NET can be used to build standalone applications and
Web applications.
True/False
3. Visual Basic .NET is a minor upgrade from Visual Basic 6.0.
True/False
4. Changing your profile in Visual Studio .NET affects the Dynamic Help
system.
True/False
Applying It
Try to complete the following exercise by yourself.
A P P LY
Independent Exercise
Because this is the first chapter and only an introductory overview is pre-
sented, please take this opportunity to read more about Microsoft’s .NET
strategy and technologies at www.microsoft.com/net.
2
Creating the First Application
In this chapter you create your first Visual Basic .NET application and
learn the source code that is automatically generated by Visual Studio
.NET. If you have used prior versions of Visual Basic, the goal of this chap-
ter is to quickly show you the structure of a new application. This is to ease
you into the dramatic changes that have occurred in Visual Basic since ver-
sion 6.0. If you have not used prior versions of Visual Basic, the goal of this
chapter is to give you a quick preview of what you will learn reading this
book. This chapter does not cover the specific language details so don’t
worry if some of the language syntax is unclear. You will start learning the
Visual Basic .NET language in detail in Part II, “Language Basics.”
In this chapter, you will
• Create a new Windows Application project using Visual Studio .NET
• Tour the structure of the new application as generated by Visual
Studio .NET
• Learn about more of the features of Visual Studio .NET such as the
Code Editor and the Object Browser
28 Chapter 2: Creating the First Application
Introduction
An application is a software program that runs, or executes, on a computer.
An application typically has a user interface that allows you, as a user, to
interact with it. There are many types of applications in existence such as
word processors and e-mail programs. You can buy applications at a store,
download them from the Internet, or you can build them yourself (although
it is often simpler to buy one rather than build one).
A project is a term used to defined the set of files that are the ingredients
of an application. An application can be made up of many types of files.
The most common type of file used in an application is called the source
file. A source file contains the steps that are performed when the applica-
tion runs. These steps, or instructions, are written in a computer lan-
guage such as Visual Basic .NET. Image files are another type of file that
may be part of a project. Images are commonly used as icons or pictures
to make the application easier to use by associating pictures with
commonly used tasks.
In this chapter, you are going to create a new Windows Application project
to demonstrate how you would start building an application. Once the pro-
ject is created you will continue with your tour of Visual Studio .NET.
A Windows Application is a specific type of application that allows you create
menus, toolbars, buttons, and other user interface components that you would
normally expect to see in an application that runs on Microsoft Windows. In
contrast, another type of application, a Console Application, runs only in a
window that displays text output. A console window does not support any of
the user interface components previously mentioned. Throughout the book
there are examples of different types of applications that illustrate this.
When you create a new project, Visual Studio .NET automatically creates
an initial set of files and some code to get you jump-started with your appli-
cation. As you can probably tell, this is an extremely useful time-saving fea-
ture of Visual Studio .NET.
TIP
You may want to create a folder on your computer for the purpose of placing all of your
projects. This way you can manage all of your projects in a central location rather than
having to search your hard disk later. Although this concern is somewhat addressed by
the VS Start Page because it lists the recent projects, once you start developing new
projects on your own this list may become large.
A new project containing a single blank form is generated for you when you
click the OK button. The project and its initial files are placed in a subdi-
rectory under the location you specified in the New Project dialog box. The
name for the subdirectory is the same name as the project name when you
first created the project.
NOTE
The format of the default name for a new project is the project type you selected
appended with a number. The very first time you select a project type and empty project
location (a directory that does not contain any projects), the appended number is “1.”
For example, the first time you create a Windows Application in an empty location,
the default project name is “WindowsApplication1.” The next time I create a
Windows Application project in the same location, the default name becomes
“WindowsApplication2.” And so on.
30 Chapter 2: Creating the First Application
Figure 2.2 shows the initial view of the newly created project. If you have
used Visual Basic 6.0, this should look very familiar to you. You start out
with a blank form in which you can start adding UI controls.
Notice that the solution and project have the same name. This is the
default behavior when you create a new project that is not part of another
solution. If you want to change the name of the solution or project for any
reason you can do so by using the Properties Window. Select View,
Properties Window or press the F4 key. The Properties window is a
dynamic window that displays the properties for the selected element in
your project. You can select an element by clicking on it with the mouse.
The Properties Window then displays a specific set of properties for that
element and a description for that property in the lower part of the window.
You can view the elements by using the scrollbar to scroll up and down.
Figure 2.3 shows the solution element selected in the Solution Explorer and
the properties for the solution displayed in the Properties Window.
The name of each property is displayed on the left side of the window and
the corresponding value is displayed to the right of each property. Some
properties are editable and some are not. If you see a property that appears
to be grayed out then this signifies that you cannot change the value and
you will be unable to change it. If it is not grayed out, you can change the
value by clicking on the value and entering in a new value. For example,
32 Chapter 2: Creating the First Application
you can see the Path property in Figure 2.3 is grayed out because you
cannot change the location of the project from the properties window.
Properties can have different types as values. For example, some properties
may allow text as a value. A text value can contain a set of characters that
you type in using the keyboard. Some properties only allow True or False.
Others only allow a predefined list of values. If you click on the value of the
property, you can at that point tell what values you can enter for the prop-
erty. If it is a text property, a blinking cursor appears signifying you can
enter text using the keyboard. If the property can only contain True/False
or a predefined list of values, you can either type the first character of the
value or use the drop-down combo list to select the desired value. For exam-
ple, if you wanted to change a property value from True to False, you could
click on the property and press the F key on the keyboard. Another
approach is to click on the value and double-click the mouse. This causes
the property to cycle through the possible values. Each double-click of the
mouse moves to the next value.
TIP
If you want to quickly change a property value to another value in a predefined list, just
double-click the property to cycle through the possible values.
Also notice that the values of the properties change to bold when you edit
them. Values that are bold in the Properties window signify that the prop-
erty has been changed from its default value. This is a quick way to tell
what property values have been changed since you first created the element
in the project.
TIP
Property values that are displayed in bold mean the value has been changed from its
default value. This is a quick way to identify property values are different from their ini-
tial default values.
As stated earlier, a default form is automatically created for you when you
create a new “Windows Application” project (which is what you saw in Figure
2.2). Forms have two parts to them—the Designer and the Code. The Designer
shows the visual representation and allows you to visually design the form by
placing other visual elements on the form. The Code represents the logic of the
form as defined using a software language such as Visual Basic .NET.
If you double-click on the form in Figure 2.2 you will see the source code for
that form. This is shown in Figure 2.6. To get back to the visual representa-
tion of the form you can double-click the form element in the Solution
Explorer window. An even easier way to move between the Code and the
Designer is to remember these two keystrokes:
• F7 to display the Code
• Shift+F7 to display the Designer
34 Chapter 2: Creating the First Application
TIP
Use F7 and Shift+F7 to switch between the Code window and the Designer window.
Figure 2.6: Code window showing source code for the Form.
If you are new to programming, I would not expect you to understand the
code in Figure 2.6 at this point in the book. Also, many Visual Basic 6.0
developers do not have an object-oriented programming background so
some of the code is going to look very unfamiliar to those readers as well.
The reason it is presented this early is so that you can continue the tour of
Visual Studio .NET within the context of a real project and at the same
time point out a couple of useful things along the way.
The rest of Part I of this book continues with the tour of Visual Studio
.NET. In Part II, the Visual Basic .NET language is presented and
explained thoroughly. In Part III object-oriented concepts are covered to
ensure you have the appropriate background before reading Part IV, which
covers Forms and UI related material. By the time you get to Part IV, you
should be in a good position to understand and internalize the generated
code.
Let’s not worry about the exact purpose of every line in the following code.
Instead, focus on some of the structural elements first. Here is the gener-
ated code for the form:
A Tour of the Generated Project 35
End Sub
End Sub
#End Region
End Class
36 Chapter 2: Creating the First Application
The Imports statement is also provided as part of the Visual Basic .NET
language so that you can include a namespace at the top of your source
code and just refer to the class name within your code. This way you do not
need to continuously write the fully qualified class name including the
namespace. Using the Imports statement, the previous code snippet could
be changed to the following:
Imports MyCode
Dim form as Form = new Form()
in the project you just created. If you are ever in doubt whether a particular
assembly is being referenced by your project, you can always check the
references in the Solution Explorer to find the answer.
NOTE
Although assemblies are new to Visual Basic .NET, they are a different way of imple-
menting what most Visual Basic 6.0 users know of as Project References. In Visual
Basic 6.0, you would specify a reference to another project by selecting it from a list of
known libraries installed on the computer. Once the reference was established, the
code from the referenced library was available to the program. In Visual Basic .NET,
after the assembly is imported the program can use the imported code.
Everything between the Public Class Form1 and End Class lines define the
Form1 element you see in the Solution Explorer. You can think of this as
the beginning and ending points of the Form1’s definition in the source
code. All of the form’s logic must exist between these two lines of code.
NOTE
If you haven’t noticed yet, Visual Basic .NET is now a fully object-oriented language. This
is a major change that existing Visual Basic 6.0 developers should realize. Don’t be
alarmed by this as change sometimes causes concern. Part III of this book presents a
thorough overview of object-oriented development so that you can better understand
and learn the language.
38 Chapter 2: Creating the First Application
Another interesting point is the code between the #Region and #End Region
lines. This region of code is automatically updated by the Designer window.
The Designer window allows you to graphically place objects, such as but-
tons, on the form. When you make changes to the form with the Designer,
the Designer adds the necessary code changes to your form in the region
between the #Region and #End Region lines. At the beginning phase of
learning Visual Basic .NET you should not be changing these lines of code
manually as it may cause problems with your program.
NOTE
Novice programmers should NOT edit the code between the #Region and #End Region
lines. This code is automatically updated by the Designer.
As shown in Figure 2.6, the Code window also has an addition from previ-
ous versions of Visual Basic. In the left margin of the Code window you can
see a vertical line going down the page with some squares with plus (+) or
minus (–) symbols in them. If you click on a square with a minus, the code
collapses and the square changes to contain a plus sign. If you click on a
square with a plus, the code reappears and the square changes to contain a
minus. Clicking on the squares this way allows you to expand and contract
sections of code within the Code window. This can be very helpful if you
have lots of code in one window and you want to only see certain sections at
a time.
What’s Next
You have created your first Visual Basic .NET project and toured more
aspects of Visual Studio .NET. You have also skimmed through the struc-
ture of the autogenerated code for this project.
In the next chapter, you build the application using this project and run it
to see what happens. Generally, when you feel your application is complete
and bug-free (no defects) you would want to make your application avail-
able to others. This is called deploying your application and you will learn
how to do this with Visual Studio .NET.
Reviewing It
This section presents a review of the key concepts in this chapter. The ques-
tion is intended to gauge your absorption of the relevant material.
REVIEW
1. Describe an application, a project, and a solution and how they relate
to one another.
Checking It 39
Checking It
Select the correct answer to the following questions.
CHECK
Multiple Choice
1. If you are viewing a form in the Designer window, you can view the
form’s code using:
a. F5.
b. F6.
c. F7.
d. Ctrl+C.
2. If you are viewing a form in the Code window, you can view the visual
representation in the Designer window using:
a. Shift+F5.
b. Shift+F6.
c. Shift+F7.
d. Shift+C.
3. Property values that are uneditable are displayed:
a. With a “lock” icon next to them.
b. As grayed out.
c. Just like any other property.
d. In red.
True or False
Select one of the two possible answers and then verify on our Web site that
you picked the correct one.
1. There are several additions to Visual Basic .NET but there are very
little changes to the language itself.
True/False
2. Solutions contain projects.
True/False
3. The Imports statement is for using assemblies.
True/False
40 Chapter 2: Creating the First Application
Applying It
Try to complete the following exercise by yourself.
A P P LY
Independent Exercise
Create a new “Windows Application” project and make sure the Form’s
properties are displayed in the Properties window by selecting the form
(select the form by clicking on it). Turn off the maximize box by changing
the MaximizeBox property to False, change the form’s title by editing the
Text property, and change the border style to FixedSingle. After you change
these properties, notice which form properties are bold and which are not.
3
Compiling and Running the Application
In this chapter you will learn how to turn your project into a running appli-
cation. This is more commonly referred to as “building” your project. You
will build the sample project created in the previous chapter and then run
it to see what it looks like. In the process of doing this, these topics will be
covered:
• Building the project
• Explaining Build messages
• Building and Rebuilding
• Running the application
44 Chapter 3: Compiling and Running the Application
When you build a project in Visual Studio .NET, you have the option of
building it in Debug mode or Release mode. In Debug mode, the generated
Build Messages 45
Build Messages
At this point, notice the text displayed in the Output Window. As a result of
this build, the Output Window contains text informing you that one project
was built successfully, zero projects failed building, and zero projects were
skipped. Remember that each Solution in Visual Studio .NET can contain
multiple projects. Obviously, the goal is to have all of your projects in your
solution built successfully.
So, based on this, I can assume the project was built successfully and move
on. But, what do I do if my project does not build successfully? To show
this, I have typed garbage (random characters) into my source code before
trying to build it. Figure 3.2 shows the erroneous text I added and the out-
put of the Build process.
This time I am not presented with the Output Window. Instead, there is a
Task List window displaying a list of tasks I must perform before the Build
process can complete successfully. Each task generated as a result of a
failed build shows an informative description of the task and the file where
the error originated. If you double-click on the task, the offending line is
highlighted and immediately made visible in the code editor for you to deal
with. This is a very nice feature that you will find yourself using quite often
as you fix problems in your projects.
If I select View, Other Windows, Output I would see the error message from
the build process shown in Figure 3.3. As you can see, this time the output
of the build process tells you that zero projects were built successfully and
that one project failed to build.
46 Chapter 3: Compiling and Running the Application
NOTE
Actually, you can execute code in the debugger regardless of whether the project was
built in Debug mode or Release mode. However, the debugger will only be able to per-
form debugging functions such as setting breakpoints and watching variables if the pro-
ject was built in Debug mode.
If you intend on using the debugger with your built project, verify the project was built in
Debug mode first. If it was not built in Debug mode just set the configuration to Debug
in the Configuration Manager and rebuild the solution.
You can execute the project in the debugger by selecting Debug, Start or
by pressing the F5 key. If you do not want to run in the debugger you can
select Debug, Start Without Debugging or by pressing the Ctrl+F5 keys
simultaneously. Figure 3.4 shows the sample application running using the
F5 key to start it. This example shows nothing more than a simple blank
form. Once again, this example was only intended to provide some context
while presenting the Visual Studio .NET development environment.
48 Chapter 3: Compiling and Running the Application
For those readers familiar with debuggers and stepping through applica-
tions, the F9 key is used to toggle a breakpoint on and off on the current
line in the Code window. Once a breakpoint is hit and program execution
stops on a particular line of code, you can step through the code using the
F8 key. At any point, you can press the F5 key to resume execution of the
program.
NOTE
You can close the application by clicking the close box (the button with the “X”) in the
titlebar or by pressing Alt-F4.
Once a project is built and free of errors, you will want to deploy it to other
computers so that other users can use it. The simplest way to achieve this
is to just copy the files to the computer you wish to run it on. It is as simple
as that. With Visual Basic .NET, you no longer need to register anything on
the computer where the software is going to run. Prior to Visual Basic
.NET, you were required to register COM dlls, as an example, using
regsvr32.exe prior to using the dlls. If the dll’s were not registered they
could not be used.
Deploying your software can be more involved if you wish to create an
installation program to do the job of installing your software on another
Under the Covers 49
C++ 6.0. The framework provides application isolation so that different ver-
sions of the same application can run on the same computer. Also, you can
have different versions of the same assembly installed and running on the
same computer without breaking existing applications.
NOTE
All source code written in Visual Studio .NET supported languages are compiled into
the Intermediate Language (IL for short) during the build process.
This is what enables code written in one language to access data types and code writ-
ten in another language seamlessly. You can even use code written in different lan-
guages within the same project.
The good news is that this all happens under the covers and you really
don’t need to understand the details. The important point to remember is
that all source code is compiled to IL code and the IL code is managed by
the Common Language Runtime.
What’s Next
You have gone through the process of building the project. This included an
explanation of the build messages in the Output Window and tasks in the
Task window in the event a build fails. You then executed the application in
order to see it working.
In the next chapter, we discuss the types and structures of the various VB
projects that you can create. A description of each project type is given
along with an example to show what each type of project looks like when it
is running. This is intended to give you an idea of the types of applications
you can build with Visual Basic .NET.
Reviewing It
This section presents a review of the key concepts in this chapter. These
REVIEW
questions are intended to gauge your absorption of the relevant material.
1. Describe what the Intermediate Language (IL) is.
2. Describe the difference between Building and Rebuilding.
Checking It 51
Checking It
Select the correct answer to the following questions.
CHECK
Multiple Choice
1. If you want to start debugging your project, you could press which
key?
a. F5.
b. F6.
c. F7.
d. None of the above.
2. If you want to start the application without debugging it you could
press which key combination?
a. Ctrl+F5.
b. Ctrl+F6.
c. Ctrl+F7.
d. None of the above.
3. IL stands for:
a. Interface Language.
b. Instructor Lounge.
c. Inspector Larry.
d. Intermediate Language.
4. CLR stands for:
a. Common Language Runtime.
b. Common Line Return.
c. Clear Language Reform.
d. None of the above.
52 Chapter 3: Compiling and Running the Application
True or False
Select one of the two possible answers and then verify on our Web site that
you picked the correct one.
1. All applications developed in Microsoft .NET must be registered on the
target computer before it can run.
True/False
2. Managed code is compiled just-in-time by the Common Language
Runtime.
True/False
3. Only Visual Basic .NET source code is ever compiled to IL code.
True/False
Applying It
Try to complete the following exercise by yourself.
A P P LY
Independent Exercise
The purpose of this exercise is to familiarize yourself with building a pro-
ject and viewing the build messages. Create a new “Windows Application”
project and build it. Once it builds, introduce an error into the source code
by typing anything in the Code Window and select Build Solution from the
Build menu. Remove the text you typed in so that the Code Window is back
to what it was and rebuild the project.
4
Visual Basic .NET Project Types
There are several different types of projects that you can create using
Visual Basic .NET. This chapter presents the project types so that you can
understand the types of software projects you can create as you read the
rest of the book. When you create one of these projects, all of the initial files
and source code are generated to give you a head start. Once the project is
created, it is up to you to then add the specific code that is unique to your
project. Hopefully, the descriptions of these project types give you a better
understanding of the true breadth and power that Visual Basic .NET
provides you as a developer:
• Windows Application
• Class Library
• Windows Control Library
• ASP .NET Web Application
• ASP .NET Web Service
• Web Control Library
• Console Application
• Windows Service
• Empty Project
• Empty Web Project
56 Chapter 4: Visual Basic .NET Project Types
Windows Application
The Windows Application project is used to create applications that are
installed and run on Microsoft Windows. This is the traditional type of
application that has existed on Microsoft Windows for years. These types
of projects generally contain a user interface similar to what you are
used to seeing in most Microsoft Windows applications. It usually con-
tains common user interface features such as a menu, toolbar, buttons,
and so on. Visual Basic 6.0 users should be familiar with this type of pro-
ject already. When you start developing applications of your own, you
will be creating projects of this type for those applications that are not
Web-related and are intended to run on the computer where it is
installed.
Figure 4.1 shows the Visual Studio.NET workspace after a new Windows
Application project is created. All of the necessary code to get your applica-
tion started is created for you and the project’s main form is visible. At this
point you can start enhancing the project as you like by adding a menu,
toolbar, and buttons to the form. You can even add additional forms. It is up
to you to construct your application as simple or as complex as you like.
The initial structure of this project includes the default form and references
to any assemblies.
The form has a visible component that is editable using the Designer win-
dow. This is the window shown in Figure 4.1. You can also edit the form’s
code directly using the Code window. You can access the Code window for a
form using the F7 key. To get back to the Designer window for a form you
can press Shift+F7. You will learn about the Designer Window in much
more detail in Part IV, “Working with Forms and Controls,” when you are
dealing with forms and controls.
TIP
You can press F7 to display the form’s Code window and Shift+F7 to display the form’s
Designer window.
Class Library 57
Class Library
A Class Library project is used to create a set of classes that can be used by
one or many other projects. The project itself becomes an “assembly” that
can be used by other projects once it is built. In Part III, “Working with
Objects,” you learn about object-oriented concepts and this is where this
type of project will be demonstrated. Visual Basic 6.0 users are probably
already familiar with this type of project as you can create a Class Library
in Visual Basic 6.0 which essentially enables you to build a COM dll.
Figure 4.2 shows the Visual Studio.NET workspace after a new Class
Library project is created. All of the source code is generated to give you a
head start in building your class library. Notice that the “Class1” is initially
visible in the Designer window. Just like with the forms, you can access
the code for the class using F7 and back to the Designer window using
Shift+F7. The initial structure of this project includes a default Class and
any project references as a result of importing assemblies.
58 Chapter 4: Visual Basic .NET Project Types
For now, think of this type of project as a way to create a library of source
code that can be shared and used by many projects without having to dupli-
cate the code in each of those other projects. Each project that wants to
refer to code in this project would simply import a reference to this project
using the assembly name. The assembly name is defined in the Property
Pages for the project. You can display this by right-clicking on a project in
the Solution Explorer and then selecting the Properties menu item from the
pop-up menu. The project Property Pages window is shown in Figure 4.3.
When you get to the point of wanting to develop your own assemblies, you
will create one or more projects of this type for that purpose.
Windows Control Library 59
You will inevitably come across a particular situation where you need a con-
trol that is not commonly available. When you do reach that point, you
have the capability to create a project of this type and build your own con-
trol which you can then use as part of your application. If the control is
good enough, you could easily package it up and provide it for sale to other
developers needing such a control.
Figure 4.4 shows the Visual Studio.NET workspace after a new Windows
Control Library project is created. As you can see, the Designer Window is
visible showing the display area for the control. This display area is where
you would manage and direct the look of your control. You will see how
to do this later in this book. The initial structure of this project includes
the default control and any project references as a result of importing
assemblies.
Using a Web Application project you can create Web Forms. Web Forms is a
major new development as part of Microsoft.NET and ASP.NET in particu-
lar. Web Forms allow you to design and develop forms that render them-
selves according to the target browser or display device on which they run.
This frees you from having to know and deal with the specific issues around
the type of browser your user may be using, for example.
Figure 4.5 shows the Visual Studio.NET workspace after a new Web
Application project is created. As you can see, the Designer Window is visi-
ble showing the display area for the Web Form. This is where you would
probably add controls and provide any additional graphical output for the
form. The initial structure of this project includes several different files. It’s
better to talk about these files in the context of learning about developing a
Web application. Because of this, these files are discussed in Part VI,
“Developing for the Web,” when we talk about Web Forms and developing
for the Web.
Although ASP.NET is not covered at any great length in this book, you will
be covering Web Forms in Part VI of this book as you take a look at Web
development.
62 Chapter 4: Visual Basic .NET Project Types
Console Application
Microsoft Windows provides a command prompt window that allows you to
type in commands using the keyboard to perform everyday tasks such as
displaying lists of files, copying files, and deleting files. Figure 4.6 shows
the command prompt window. A Console Application project allows you to
build a program that can be run within the command prompt window.
Console Applications are limited to text output and do not have any associ-
ated graphical display. The text output is limited to a command prompt
window in which the Console Application runs.
The initial structure of this project includes the default module and any
project references as a result of importing assemblies.
A Console Application project is used in the next chapter so you can see it
first hand then.
64 Chapter 4: Visual Basic .NET Project Types
Windows Service
A service in Microsoft Windows is a specific type of program that performs
a specific job or function in the background. This type of program does not
have a user interface that you can interface with. A Windows Service pro-
ject allows you to develop this type of program using Visual Basic .NET.
The initial structure of this project includes the default service and any
project references as a result of importing assemblies.
Your computer currently has a set of services that was installed as part of
Microsoft Windows. You can display the list of registered services by click-
ing on the Services icon in the Administrative Tools in your Control Panel.
Figure 4.7 shows the Administrative Tools folder and the Services icon you
would need to click on. Figure 4.8 shows the list of registered services on
my computer. Once you develop a service and install it, you would see it
displayed in the list in Figure 4.8 on your computer.
Empty Project
You can also create an Empty Project project. You may want to do this if
you are planning on creating a solution that contains many projects. You
could first create the empty project, name the solution, and then start
adding projects to it.
You could also start with an empty project if you wanted to start out by
writing all of the source code yourself. This would not be recommended as
you can benefit from choosing one of the other type of projects to get you
started faster.
What’s Next
We have touched on most of the project types that are available to you as
you develop software using Visual Basic .NET. Each of the types will start
to have more meaning to you as you progress through the book. If you don’t
quite have a handle on these project types yet, please refer back to this
chapter.
In the next chapter you will start learning the Visual Basic .NET language
in detail. The chapter starts out with an introduction to programming for
those readers just starting out in software development. After that, this
book’s first programming example is presented so that you can start down
the road of learning VB.NET.
Reviewing It
This section presents a review of the key concepts in this chapter. The ques-
REVIEW
tion is intended to gauge your absorption of the relevant material.
1. Describe the purpose of having different types of projects. Also,
describe the Windows Application and Console Application project and
their differences.
66 Chapter 4: Visual Basic .NET Project Types
Checking It
Select the correct answer to the following questions.
CHECK
Multiple Choice
1. Which project would you used to develop a common program that runs
in Microsoft Windows?
a. Windows Control Library.
b. Windows Application.
c. Windows Service.
d. Class Library.
2. If you found yourself needing to develop a new user interface control
for your Microsoft Windows application, what type of project would
you create to start developing it?
a. Windows Application.
b. Console Application.
c. Windows Control Library.
d. None of the above.
3. Let’s say you came up with an award-winning idea for developing a
brand-new service that other developers could invoke over the
Internet. What type of project would you create to start developing it?
a. Web Service.
b. Windows Service.
c. Neither a nor b.
d. My Great Idea Service.
4. If you found yourself needing to develop a new user interface control
for your Web application, what type of project would you create to
start developing it?
a. Windows Control Library.
b. Console Application.
c. Web Control Library.
d. None of the above.
Applying It 67
True or False
Select one of the two possible answers and then verify in Appendix A that
you picked the correct one.
1. A Window Application project is used to create a graphical application
that looks and feels like other programs that run on Microsoft Windows.
True/False
2. A Class Library project is essentially used to create a library of source
code that can be used by other projects.
True/False
3. A Windows Control Library project is used to create custom graphical
controls that can be used by other programs.
True/False
4. A Web Application project is used to develop an application that runs
on the World Wide Web.
True/False
5. A Web Service project is used to develop a service that can be used
across the Web by applications that know how to communicate with
the service.
True/False
6. A Web Control Library project is used to create custom graphical con-
trols that can be used in Web Applications.
True/False
7. A Console Application project is used to develop a program that runs
solely within a command prompt window.
True/False
Applying It
Try to complete the following exercise by yourself.
A P P LY
Independent Exercise
The purpose of this exercise is to familiarize yourself with building a
Console Application project. Create a new Console Application project and
build it. Run the project using the F5 key so that you can familiarize your-
self with the output of a Console Application. This type of application is
used in the next few chapters so it’s a good idea to learn it now.
Part II
Language Basics
Language Description
Fundamental Data Types
Data Conversion and Expressions
Arrays, Enumerations, and Structures
Control Statements
Subroutines and Functions
Introduction to Debugging and Exception Handling
Microsoft .NET Framework—Assemblies and Namespaces
5
Language Description
In this chapter you will take a tour of the Visual Basic language. We will
start with a brief history of programming languages in general and BASIC
and Visual Basic in particular. Next you will learn the structure of a Visual
Basic project as it integrates into a Visual Studio .NET solution.
You will also write and then dissect and analyze a very simple console
application written in Visual Basic .NET. You will use this application to
introduce the first and most fundamental concepts of the language: identi-
fiers and literals, comments and whitespace, as well as the general struc-
ture of a Visual Basic .NET program.
The material for the chapter is structured into these topics:
• Introduction to programming
• Programming languages
• Structure of a Visual Basic project
• Identifiers, literals, keywords, and whitespace
• Comments
72 Chapter 5: Language Description
Introduction to Programming
To understand what programming and programming languages are all
about, you need to understand first how a computer works. Even if you are
familiar with this subject please do not skip the next few paragraphs,
which define a few fundamental notions used throughout the rest of the
book.
A computer consists of hardware and software. By hardware we understand
normally the physical (material) components of the computer, of which the
most important are
• The processor or processors, also known as Central Processing Unit(s)
or CPU(s).
• The working memory (mostly known as RAM, for Random Access
Memory), which is a transient location in which software executes.
This memory is in use only while the computer is powered; that is why
it is called transient. When the computer is powered off, whatever is
in memory will be lost.
• The permanent memory (or permanent storage), which is where soft-
ware and data are stored while the computer is powered down. Some
examples of permanent memory are hard disks, floppy disks, CDs, and
so on, together with the devices that link them with the CPU and
RAM.
• Other devices and peripherals that are of less interest for you cur-
rently include the monitor, keyboard, mouse, miscellaneous video and
sound cards, and so on.
Memory
address:
0 01101011 Byte at address 0
1 00010010 …
2 11001001
3 00000100
…
298 01101011
299 00010010 Memory location at
address 298 consisting
300 11001001 of 4 bytes
301 00000100
302 00010010 Memory location at
address 302 consisting
303 11001001 of 2 bytes
304 00000100
…
Programming Languages
You have seen that a program consists fundamentally of a series of steps
(instructions) to the CPU on how to manipulate working memory and other
resources to produce some useful output, based on some kind of input from
the user or other programs.
The programmer provides these instructions to the CPU in a format that it
understands. As you already learned, this format is known as machine code
(also known as machine language). The first programs written were indeed
written in machine code. However, this code is not easy to use or read, and
it is even harder to maintain over time (especially if there are changes to
the set of instructions the CPU supports). The next step in the evolution of
programming languages is the assembly languages. These languages
require one simple translation to machine code before the CPU can under-
stand it. This translation step is achieved using a program called an assem-
bler. However, the assembly languages were not a big step forward; they
retained all the complexity and unintuitive features of the machine code.
Further down the evolution line of the programming languages is the first
generation of high-level languages. They are named high-level because they
require a special (non-trivial) step to transform them into code that the
CPU can understand. This step is called compilation and is performed by
special programs called compilers. The compiler will take the source code
written in the respective language (for example Fortran or C) and translate
it into machine code for a given hardware platform and operating system.
By source code we understand the instructions in the original (high-level)
language. We use the term executable format for the (compiled) final format
that can be executed.
The high-level languages themselves have evolved through a series of steps
(sometimes known as generations), from procedural languages to structured
languages and then to object-oriented languages, such as C++ and Eiffel.
The latest generation of languages add a new step into the translation from
source code to executable format: an intermediary step called byte codes in
the case of Java and intermediate language (IL) in the case of the Visual
Studio .NET. Although the two are not identical in implementation,
they share a set of common good ideas, one of which is ease of use and
Structure of a Visual Basic Project 75
NOTE
The console is the name for the command prompt (DOS) window, in programmer’s par-
lance. Writing a console application means in effect that all the user interaction takes
place using the simple command prompt interface and no graphical user interface (GUI)
is involved.
76 Chapter 5: Language Description
It may seem strange to some readers that you start learning Visual Basic—
one of the languages that is specifically designed to ease GUI develop-
ment—by writing a console application. The reason we believe this is the
best approach is that Visual Basic was dramatically changed (for the bet-
ter) by introducing a series of features that make it a full-blown object-ori-
ented language. These changes include introduction of object-oriented
features like inheritance, method overloading, and shared (static) members,
to name just a few. We do believe it is easier to understand these concepts
exemplified by using simple programming examples, without adding the
complexity of GUI forms and controls, until after the basic object-oriented
paradigm has been successfully learned. Therefore start simple, and add
complexity as you continue learning.
Let’s start by creating a new Visual Basic project. From the New Project
dialog select Visual Basic projects on the left side and Console Application
in the Templates pane on the right side. Change the name of the project to
HelloWorld. The dialog should look like the one in Figure 5.2. Click the OK
button to create the new project.
Now the Visual Studio IDE shows the newly opened project, similar to the
one shown in Figure 5.3.
As you have seen in the previous chapters, you have a main window that con-
tains the miscellaneous project components that are open. If more than one
project component is open, multiple tabs will be present on the top of the
main view. Right now you should have only one tab labeled Module1.vb. On
the right you see the project window (labeled Solution Explorer) and the
Properties window—which were briefly discussed in the previous chapters.
We will explore these and other windows in more detail in this chapter.
Structure of a Visual Basic Project 77
Figure 5.3: The Visual Studio IDE with the newly created HelloWorld.
In the Solution Explorer you can look at all the component parts of your
solution and project. When you create a new project, the IDE creates a new
solution with the same name as the project. A solution may be comprised of
one or more projects. If you click on the solution in the Solution Explorer
you will see in the Properties window (below it) the properties of the newly
created solution. We will return to this later on in the book. For now, let’s
continue our exploration.
Click on the project (HelloWorld). The Properties window will now show the
properties of the project. Notice that the project file has an extension,
.vbproj, which indicates that this is a Visual Basic project. Each project in a
solution is developed in a language—Visual Basic, C#, and so on, although
projects may interact with one another as you will see. Under the project,
you have two entries—one labeled References (which you will ignore for
now) and another labeled Module1.vb.
Now click on the Module1.vb in the Solution Explorer window. The
Properties window changes again to show the properties of Module1.vb,
which is the currently selected object. Module1 is a Visual Basic module,
which is one of the fundamental components that can be part of a project.
Each module consists of source code that, when compiled, will yield exe-
cutable code (after passing through intermediate language code, first).
78 Chapter 5: Language Description
The first (Module Module1) and last (End Module) lines of code indicate
where the module starts and ends, and are (as you have seen) generated by
the wizard. Also generated by the wizard are the two lines in the middle:
Sub Main() and End Sub. You can think of these for now as being the entry
and exit points of the program. That means your program will start with
the statement immediately following Sub Main() and will end the moment
it reaches the End Sub. In between these two statements it will execute
sequentially all the steps that you will enter. For now this would mean
nothing because there is nothing between the Sub Main() starting point and
the End Sub ending point. That means that if you ran the program as it is,
it would do nothing.
Let’s give the computer something interesting to do. Click in the Module1
main view (on the left) and enter the lines shown in bold below, as indi-
cated. You will notice that when you enter the period between different
parts of each statement, a drop-down prompt will appear below as you type
text. This feature is known as IntelliSense; do not worry about it for now,
you will come back to it later.
Module Module1
Sub Main()
Console.Out.WriteLine(“Hello World!”)
EXAMPLE
Console.Out.WriteLine(“Press the <Enter> key to end the program”)
Console.In.ReadLine()
End Sub
End Module
Save the program and now let’s build (compile) and run (execute) your new
application. Select the Debug, Start menu (or simply press F5) to have the
IDE compile the code for us and then run it. You should see the output of
the program as shown in Figure 5.4.
Notice the “Hello World!” and “Press the <Enter> key to end the
program” message displayed in the command prompt window. Press the
Enter key to end the program—the focus will return to the Visual Studio
IDE.
You have just coded, compiled, and executed your second simple program in
Visual Basic. Let’s see what the structure of a Visual Basic program is.
You have a Solution (HelloWorld) that contains your Visual Basic project
(also HelloWorld). The Visual Basic project is a collection of code and com-
ponents grouped together to constitute a program. In your case you have
only one component—a module, named Module1. This module contains the
entry and exit points of the program, and between these, the steps that the
CPU must execute. You can think for now of the module as a container for a
part of the program.
In this case you have three steps. First you request the text “Hello World!”
to be displayed to the console. You achieve this by using the WriteLine()
method of an object called Console.Out. Do not worry if you do not under-
stand exactly what the previous sentence means, we will get back to it later
on and explain it in detail, in later chapters. For now think of the
Console.Out.WriteLine() statement as an instruction to write to the con-
sole the text passed to it in parentheses. The second line is very similar to
the first line, except the text written to the console is different (“Press the
<Enter> key to end the program”).
In a similar fashion, the last line before the End Sub exit point reads a line
of input from the console until the Enter key is pressed. The reason you
have the last two statements is so that you can read the console output—
the computer will wait until you press the Enter key. If you delete the last
line, the program will run just as fine, except that it would not wait for us
to read the “Hello World!” text, it would see that the program has finished
and it would close the console window. You can try (as an exercise) to delete
the last line and see what happens when you run the program.
x, bFound, m_name, and NUMBER_PI. Any identifier that violates these rules is
not valid and the IDE and then the compiler will signal you with a syntax
error if you try to run the program. Examples of invalid identifiers are
m-name, 3stooges, and joe smith.
NOTE
An identifier can also start with an underscore, although it is better to use a letter. The
detailed syntax for identifiers (and in general for the Visual Basic .NET language) is pre-
sented on our Web site.
You have probably noticed that some of the identifiers in the program you
have written are colored in light blue. These are a special class of identi-
fiers known as keywords. Keywords are reserved identifiers that the lan-
guage itself defines and that cannot be used, except in the way defined by
the language itself. The compiler detects these keywords and highlights
them (in blue, by default), so that you can read the code easier. For example
if is a keyword used in a branching statement, as you will see. That means
that you cannot name a module if.
Literals are values that are used in code as they are. Examples are num-
bers like 0, 1, 2.5, or string literals like “Hello World!”.
Whitespace is defined as the spaces between different symbols used. It con-
sists of the space, tab, and new line characters.
It is important to remember that Visual Basic is a case insensitive
language—that means an identifier can be written in any combination of
upper and lowercase letters. For example if, If, iF and IF are all the same
identifier. You will notice that the IDE is going to change the capitalization
of the keywords to a standard format. This is an option called “code beauti-
fication” that can be disabled if you choose to, although we recommended
that you keep it on.
Comments
The sample program you wrote is a very simple example of code—there is
nothing complicated going on. However, a real-life program is normally
more complicated and lives a longer life than a sample program in a book
for learning programming. The people developing these programs have
realized very early that a mechanism to add notes and comments about
what certain pieces of code do is an absolute must—from the human per-
spective. These comments are required as an additional explanation for
what a given piece of code does. They are useful to somebody who uses the
What’s Next 81
Sub Main()
Console.Out.WriteLine(“Hello World!”)
EXAMPLE Console.Out.WriteLine(“Press the <Enter> key to end the program”)
‘ The next line prevents the console window to be closed
Console.In.ReadLine()
End Sub
End Module
As you have noticed already the IDE has colored the line you entered in
green. This is the default color used for comments in Visual Studio .NET. It
seems that most IDE manufacturers have adhered to this convention in the
past few years. One older (and still supported) way of adding comments to
code is to use the Rem keyword (from REMark). You could have entered the
comments above as
Rem The next two lines prevent the console window to be closed prematurely
What’s Next
You have learned of the fundamental language features of Visual Basic
.NET and you have also seen a very brief history of the evolution of the pro-
gramming languages.
82 Chapter 5: Language Description
In the next chapter you will start the study of the fundamental Visual
Basic data types and the operators associated with them. You will also
write a few simple examples using the data types that you will learn.
NOTE
The answers to the “Reviewing It,” “Checking It,” and “Applying It” sections are avail-
able on our Web site.
Reviewing It
This section presents a review of the key concepts in this chapter. These
questions are intended to gauge your absorption of the relevant material.
REVIEW
1. What do we understand by software? Describe the way a software pro-
gram executes.
2. What is the role of the operating system?
3. What is a high-level programming language?
4. What is the console?
5. What is a Visual Basic identifier?
6. What is a comment?
Checking It
Select the correct answer(s) to the following questions.
CHECK
Multiple Choice
1. RAM is:
a. Random Access Memory.
b. Working memory.
c. Transient memory.
d. All of the above.
2. Memory address is:
a. The physical location of memory bit.
b. The index of a byte in RAM.
c. The index of a cluster on a hard disk.
d. The absolute position of a transistor gate in RAM.
Checking It 83
3. A compiler is:
a. A plug-and-play device that translates source code.
b. A software program that helps us build user interface projects.
c. A software program that translates source code into machine
code.
d. A part of the operating system that reads machine code.
4. What is the relationship between a solution and a project in Visual
Basic .NET?
a. A solution can have many projects.
b. A project can have many solutions.
c. A solution can have exactly one project.
d. A project can have exactly one solution.
5. A module is:
a. A fundamental component that is part of a solution.
b. A fundamental component that can be part of a project.
c. A Visual Basic .NET statement.
d. A set of instructions on how to build a project.
6. Which of the characters shown are not allowed in a Visual Basic .NET
identifier?
a. Underscore (_).
b. Dot (.).
c. Dash (-).
d. Colon (:).
7. A comment is used to:
a. Give additional hints to the compiler or interpreter.
b. Disable lines of code that are inconvenient.
c. Give additional explanations about a piece of code.
d. Tell the user what to do when he reaches the comment line.
84 Chapter 5: Language Description
True or False
Select one of the two possible answers and then verify on our Web site that
you picked the correct one.
1. One bit has 8 bytes.
True/False
2. A memory location and memory address are the same thing.
True/False
3. In the sample project shown earlier in this chapter, Sub Main is the
entry point for the program.
True/False
4. The console is the command prompt (DOS) window.
True/False
5. A Visual Basic .NET identifier can contain an underscore character
(_).
True/False
6. A keyword is used to supply additional information to the compiler.
True/False
Applying It
A P P LY
Try to complete the following exercises by yourself.
Independent Exercise 1
Create a new console project and have it output the text “My first project”
to the console, and then wait for the user to press Enter to terminate the
project.
Independent Exercise 2
Try the same as in Exercise 1 without the statements that wait for the
user. Execute the program and see what happens.
6
Fundamental Data Types
We will start this chapter by defining data types and then looking at the
fundamental data types used by Visual Basic. You will write a few exam-
ples to illustrate the concepts that you learn. Specific topics are
• Numeric data types
• Boolean data type
• String and Char data types
• Date data type
• Other data types
The fundamental data types used in Visual Basic are the simple data types
that are used as building blocks for the more complex data types. They are
defined by the language and cannot be modified. They are the most com-
mon data types used in Visual Basic. You will see later in this chapter that
the data types (or, in short, “types”) can be further classified by additional
criteria. You will start by learning the numeric data types, and move next
to the Boolean, String, Char, and Date types.
NOTE
All data types used by Visual Basic (as well as other languages in Visual Studio .NET)
are actually defined in the .NET Framework—the infrastructure that underlies Visual
Studio .NET. We will come back to this topic later on in the book.
As you see you have a rich set of numeric types, both integral and decimal,
covering a wide range of scale and precision. Except for Byte, all the other
types are signed—that means they can be used to represent both negative
and positive values. Byte can store only positive numbers between 0 and
255 (the numbers that can be stored using 1 byte = 8 bits of memory).
NOTE
Byte is sometimes treated differently from numeric types, namely as a binary data type.
For simplicity, we have included it with the numeric types.
From the integral types (types that support integer numbers without deci-
mals), the most commonly used is Integer, which has the convenience of a
wide enough value range and at the same time, it takes a reasonable 4
bytes of memory. From the types that support decimal places, Double and
Decimal are the most commonly used. One thing to remember is that both
Single and Double are using a floating-point storage mechanism that allows
for a wider range of numbers, at the price of the precision of the numbers
stored. The operations on these types of values may be subject to small
rounding errors. This is not the case for the Decimal type; we will revisit
this issue later in this chapter.
Sub Main()
Dim i As Integer
i = 6
Console.Out.WriteLine(“The value of i is {0}”, i)
End Module
Save and run the program. You will notice the message saying that the
value of i is 6. Press Enter to finish the program and return to the IDE. In
this very simple program you have declared a variable, you have assigned a
90 Chapter 6: Fundamental Data Types
value to it, and then written its value to the console. Let’s analyze each
step. The first line after the entry point of the program (Sub Main()) is
Dim i As Integer
This is a variable declaration. The compiler needs to know what are the
types of values that you use in your program. You use a type declaration,
like the one above to tell the compiler that you intend to use an Integer
value named i. A variable is a name for a value that you use in your pro-
gram for making calculations, storing data, and so on. A variable can be
thought as a name for a memory location, which memory location is of the
type you declared. In your case you tell the compiler to reserve 4 bytes of
memory for an Integer value that you intend to use, and that the name
associated to this particular memory location is “i”.
NOTE
A variable is a Visual Basic identifier, and therefore is subject to the naming rules for
such an identifier: it must start with a letter and can contain only letters, digits, and the
underscore character.
i = 6
The next line is an assignment statement—that is, you tell the compiler
what value to store in the memory location that the variable i is associated
with (6 in this example). When you declare a variable, the compiler will
reserve the memory for it and will initialize it to be 0 (for numeric types).
To change this value you must use an assignment statement. After this
statement the value of i should be 6. You will verify that the compiler did
the right assignment by writing the value to the console using the next
statement. It is a variation of the method you have seen before, but you
need not worry about it yet. Think of it as simply a way to display a string
and a value to the console.
The last lines are familiar: you need to stop the console window from being
closed before you can see the output of your sample program.
There is a way to combine the type declaration and the initial assignment
of a value to a variable. Replace the lines
Dim i As Integer
i = 6
with
Dim i As Integer = 6
Numeric Data Types 91
This is the exact equivalent of the first two lines and is more compact and
readable. If the initial value is 0, you need not place the initialization (= 0)
after the type declaration because this is the default value the compiler
uses.
If you need more than one variable you can use multiple statements to
declare them as
Dim i As Integer = 6
Dim noOfApples As Short = 7
If the variables are of the same type you can use a declaration like
Dim x, y, z As Double
This line will declare three variables (x, y, and z) of type Double, and will
initialize them all with 0.
Sub Main()
Dim i, j, k As Integer
i = 11
j = 3
k = i + j ‘ addition
Console.Out.WriteLine(“The value of k is {0}”, k) ‘ 14
k = i - j ‘ subtraction
Console.Out.WriteLine(“The value of k is {0}”, k) ‘ 8
k = i * j ‘ multiplication
Console.Out.WriteLine(“The value of k is {0}”, k) ‘ 33
k = i \ j ‘ integer division
Console.Out.WriteLine(“The value of k is {0}”, k) ‘ 3
92 Chapter 6: Fundamental Data Types
k = i Mod j ‘ modulo
Console.Out.WriteLine(“The value of k is {0}”, k) ‘ 2
Dim d, f As Decimal
d = 2
f = d / 17 ‘ floating point division
Console.Out.WriteLine(“The value of f is {0}”, f) ‘ 0.1176...
Dim x, y As Double
x = 2
y = x / 17 ‘ floating point division
Console.Out.WriteLine(“The value of y is {0}”, y) ‘ 0.1176...
y = x ^ 31 ‘ exponentiation
Console.Out.WriteLine(“The value of y is {0}”, y) ‘ 0.1176...
End Module
Save and run the program. Your output should match the one in Figure 6.1.
As you can see you use the variable k to assign to it the results of addition,
subtraction, multiplication, and then integer division of the variables i and
j. For each operation you output the results to the console (as the value of
the variable k). It is important to note the integer division (\) produces an
integer result, namely the integer part of the division after eliminating the
decimal part. No rounding is done, for example, 11 \ 3 yields 3, not 4 (as
3.6666… rounded would yield).
String and Char Data Types 93
TIP
You have used the Dim declaration statements interspersed within code, closed to the
point where they are actually used. This is against traditional (structured) programming
style, which recommends that all variables be declared at the top of the procedure
where they are used (in this case it would be the Sub Main()). We believe that this
approach is more readable, as you do not need to scroll to the top of the procedure to
find out what type of variable is f, which is used towards the bottom of the procedure.
Boolean variables are used in various ways such as loop statements, as you
will see later on in the book. The default value of a Boolean variable is
False. That means if you don’t initialize a Boolean variable when declaring
it, it will be automatically initialized to False.
NOTE
UNICODE is an international standard that defines how all characters in all known lan-
guages are mapped to a value stored in 2 bytes—that is, a number between 0 and
65635. An older standard was (and still is) in used in some older versions of Windows
and other operating systems. This standard is known as ASCII and uses only one byte
to represent a character. The .NET Framework automatically takes care of converting
strings and characters to and from ASCII.
94 Chapter 6: Fundamental Data Types
To represent strings of characters (normal text) you use the String data
type. A String is an array of UNICODE characters that can have between 0
and approximately 2 billion characters. It is, therefore, a variable size data
type where size depends upon the number of characters it holds. A String
variable can be declared and initialized in the usual fashion:
Dim s As String = “Mark Twain”
The literal String values are represented as text delimited by the “ (double
quote) character. The String values support the & operator that can be used
to concatenate two String values together. For example:
Dim firstName As String = “Mark”
Dim lastName As String = “Twain”
Dim name As String
name = firstName & “ “ & lastName
‘ name is now “Mark Twain”
This example declares and initializes two String variables (firstName and
lastName) and then declares the name variable and assigns to it the result of
the concatenation of the firstName and lastName. Note the literal String
consisting of one space that is placed in between firstName and lastName.
If the space was missing the name variable would hold the result
“MarkTwain.”
The + can be used instead of the concatenation operator & with the same
results. The previous statements can be written also as follows:
Dim firstName As String = “Mark”
Dim lastName As String = “Twain”
Dim name As String
name = firstName + “ “ + lastName
‘ name is now “Mark Twain”
We recommend you use the &, which cannot be confused with the arithmetic
+ operator. In any case, even if you decide to use the + operator, be consis-
tent in your code; do not mix them in the same project.
The literal date values are represented using the # delimiter. They can con-
sist of a date or time expressed in the appropriate format for the country
and time zone. Months can be expressed either as numeric values or as lit-
eral values (in the appropriate language).
What’s Next
In this chapter you have seen what are the fundamental data types that
Visual Basic defines. You have also learned how to declare a variable of a
given type, how to initialize a variable, and how to assign a value to a vari-
able. You have also learned a few operators on the fundamental data types.
You will continue by studying conversions between data types, as well as
other operators and usage of the fundamental data types.
NOTE
The answers to “Reviewing It,” “Checking It,” and “Applying It” are available on our Web
site.
Reviewing It
This section presents a review of the key concepts in this chapter. These
questions are intended to gauge your absorption of the relevant material.
REVIEW
1. What is a data type? Why do you need data types?
2. What is a variable?
3. Describe what happens in memory when an assignment statement is
executed for a Double value.
4. What is an operator? Give examples.
5. What values can a Boolean variable have?
6. What is the difference between String and Char?
96 Chapter 6: Fundamental Data Types
Checking It
Select the correct answer to the following questions.
CHECK
Multiple Choice
1. The size of the memory location required by a fundamental data type
is:
a. Fixed size, depending on the actual type.
b. Fixed size, always 4 bytes.
c. Fixed size for some types, variable size for others.
d. Not applicable. Fundamental data types are always allocated by
the compiler.
2. Integral numeric types are:
a. Integer.
b. Short, Integer, and Long.
c. Byte, Short, Integer, and Long.
d. Byte, Short, Integer, Long, and Char.
3. Which fundamental numeric type can represent a decimal number
with the highest possible precision?
a. Double.
b. Single.
c. String.
d. Decimal.
4. A variable declaration is:
a. Telling the compiler about a new data type.
b. A statement used to initialize a variable.
c. A statement used to tell the compiler about a new variable.
d. There is no such thing. Variables cannot be declared.
5. Which is the initial value for a variable of type Single?
a. 0.
b. 0.0.
Checking It 97
True or False
Select one of the two possible answers and then verify on our Web site that
you picked the correct one.
1. A Boolean can have only two values (True and False).
NOTE
The above True and False are the values for the Boolean data type, and as such are dif-
ferent from the answer to the question (true or false).
True/False
2. A variable of String type has a fixed size.
True/False
3. More than one variable can be declared in the same Dim statement.
True/False
4. All variables have a value when first declared, even if not initialized.
True/False
98 Chapter 6: Fundamental Data Types
Applying It
Try to complete the following exercises by yourself.
A P P LY
Independent Exercise 1
Create a new console project that outputs area of a circle with a radius of
1.526 units.
Independent Exercise 2
Create a program that computes the modulo of 143 and 13.
7
Data Conversion and Expressions
In this chapter you will learn about data conversions (conversions between
different data types), and you will learn a few conversion functions and
some new operators. You also will learn about comparison operators and
Boolean (logical) operators and expressions.
The chapter contains in the following topics:
• Implicit data conversion
• Explicit data conversion
• In-place arithmetic operators
• Comparison operators
• Boolean operators
• Expressions and operator precedence
You will start by studying conversion between the fundamental data types.
By data conversion we understand the transformation of one data type into
another. In any given program you will use multiple data types, as you
have seen even from the simple examples you have studied so far. It will be
often required to assign a value of a type to a variable that was declared as
being of a different type. As you have seen the assignment can take place
only between identical data types, that is, you can assign an Integer value
only to an Integer variable, and not to a Date variable. The purpose of the
first part of this chapter is to determine how data conversions take place.
In the second part of the chapter you will look at a few new operators and
then at the expressions that you could build with them.
This chapter (as well as the rest of the book) assumes you are using the strict
type checking added to Visual Basic .NET. This option can be set in the
Project Properties dialog box in the category Build by setting the Option
Strict On. Alternatively, you can have this statement at the beginning of all
your programs:
Option Strict On
102 Chapter 7: Data Conversions and Expressions
There is no reason not to use the strict option, unless you are porting code
from a previous version of Visual Basic, and wish to keep the code as is.
This option will enforce a strict type checking and will allow you to catch a
lot of programming errors early in the development cycle.
You will notice the fact that d is underlined, and if you place the mouse cur-
sor above d and hold it still for a few seconds, a ToolTip will be displayed.
The ToolTip text will indicate the cause of the error, as illustrated in
Figure 7.1.
From the first example you can infer that the compiler ‘knows’ to convert
an Integer to a Double, but not the other way around. In other (more tech-
nical) words: there is an implicit conversion from Integer to Double, but not
from Double to Integer.
How would you know what all the existing implicit conversions are? You
could look up in the reference online help that comes with Visual Studio
.NET, or you could remember the following simple rules:
The only implicit conversions are among numeric data types, with one
exception: from Char to String.
Implicit Data Conversion 103
The implicit conversions between numeric data types are always from a
‘smaller’ type to a ‘larger’ type, i.e. from a type that can have a narrower
range of values to one that can hold a wider range. For example Byte can
be implicitly converted to any other numeric type, while Double can be
implicitly converted to no other numeric type. The logic behind this rule is
(as you have probably guessed) quite simple: the variable that gets
assigned the new value can always hold it, if the value is between the
range of acceptable values for that type or smaller.
NOTE
There may be a precision loss when converting a Long or Decimal value to Single or
Double variables, but the number magnitude will be preserved.
The next line shows the implicit conversions for numeric types. Any type in
the list can be converted implicitly to any other type in the list that is on its
right. For example, Long can be implicitly converted to Decimal, Single,
and Double, but not to Integer, Short, or Byte.
Double ← Single ← Decimal ← Long ← Integer ← Short ← Byte
String ← Char
104 Chapter 7: Data Conversions and Expressions
NOTE
It is possible to extend the range of implicit conversions to converting any type to
almost any other type, by setting the Option Strict to False. This will in effect dis-
able the type checking of the compiler, and will permit writing unsafe code. The errors
introduced can be very subtle and hard to catch. These are the reasons for which we
strongly recommend that you set the Option Strict to True.
The naming rule for these functions is that they begin with “C” (from
Conversion) and continue with an abbreviation of the data type to convert
to. For example to convert a Double to an Integer one could use code simi-
lar to the one in the following example:
Dim i As Integer, d As Double
‘ get the value of d from someplace
i = CInt(d)
Explicit Data Conversion 105
The CInt is the name of the conversion function (and it is a Visual Basic
language identifier). Following CInt is the Double value d that you need to
convert to Integer, enclosed in parentheses. This is a standard way to call
or invoke a function in Visual Basic, and it is similar to the mathematical
notation for functions learned in high school. The value in parentheses is
called a parameter (or argument) of the function, and must be in the func-
tion domain (in this case the domain is not restricted; any value is accept-
able as a parameter). In the example, the function CInt has only one
parameter, but you will encounter functions with more than one parameter.
In this case the parameters will be separated by commas. In a similar way
to that of mathematical function, the CInt function (as well as all Visual
Basic functions) will process the value passed in as parameter and return a
value. In this case the Double passed in is transformed to an Integer and
the resulting Integer value is returned from the function. This value is
known as the return value of the function, and it will always by in the
range or return type of the function; in our case the return type is the set of
values that would fit in the Integer data type. In short, it is said that the
function takes a Double and returns an Integer. The returned value is the
value that will be assigned to i.
NOTE
With the analogy you use for functions, it becomes more clear what data types are,
namely sets of values, like the Real, Integer, and Rational numbers you learned in
school. They can be used as a function’s domain or range, or just as a set of all possi-
ble values for a given variable. And similar to mathematics you will be able to define
your own subsets and operations and functions on these subsets.
Let’s use an example to practice what you learned so far in this chapter.
Create a project as you have done before, change its name to
DataConversion, and enter the following code in the Sub Main:
Sub Main()
System.Console.Out.WriteLine(“Please enter a number and then press <Enter>:”)
Dim s As String
s = Console.In.ReadLine()
Dim d As Double
d = CDbl(s)
Console.Out.WriteLine(“The Double value d is {0}”, d)
Dim i As Integer
i = CInt(d)
Console.Out.WriteLine(“The Integer value i is {0}”, i)
Save and run the program, enter (type in) a number when prompted, and
press Enter. Make sure you are entering a valid number like 16.67. The
output screen should be similar to the one shown in Figure 7.2.
The first noticeable statement you observe is the one using the Console.
In.ReadLine() method to get input from the user (you in this case). It is
enough (for now) to say that this method returns whatever the user types
on the console on one line (until it presses Enter). The input is returned as
a String. You will learn more about the input and output methods later on
in the book; until then you will use them to output data to the console and
to get data inputted by the user back from the console.
Explicit Data Conversion 107
The second thing to notice is that you have used another conversion func-
tion CDbl to convert the String value the user has entered (s) into a Double
variable . It is very similar to the CInt function you saw earlier; it will take
a value and attempt to convert it to a Double. You output this value to the
console using the known method.
Next you convert the Double d to an Integer i and again output the result
to the console.
Now let’s see what happens when the user makes a mistake and enters
some value that cannot be converted to a number. Run the sample pro-
gram again, but this time enter a few letters, such as “joe”. You will get
an error message saying that an unhandled exception (of type System.
FormatException) occurred, and giving you the possibility to break or con-
tinue. Break means suspend program execution at the point where the
exception occurred so that you can see what was the problem. Continue
means (in this case) go ahead and terminate the program. Because you
know what the problem is, click on continue. This will direct the IDE to
terminate the program.
This example was intended to show what would happen if an attempt to
convert a value to another type fails.
As you saw in Table 7.1, there are a number of different operators to con-
vert numbers into other numbers, strings to numbers and dates, and so on.
However, Table 7.1 does not list any functions to convert a Char into a
number or a number into a Char. These functions exist, and an example
using them is presented in the following code. You can incorporate the bold
lines into the sample project you just created.
Sub Main()
System.Console.Out.WriteLine(“Please enter a number and then press <Enter>:”)
Dim s As String
s = System.Console.In.ReadLine()
Dim d As Double
d = CDbl(s)
Console.Out.WriteLine(“The Double value d is {0}”, d)
Dim i As Integer
i = CInt(d)
Console.Out.WriteLine(“The Integer value i is {0}”, i)
Dim c As Char
c = Chr(i)
Console.Out.WriteLine(“The Character value c is {0}”, c)
108 Chapter 7: Data Conversions and Expressions
i = Asc(c)
System.Console.Out.WriteLine(“The Integer value i is {0}”, i)
When you run the project, type 65.4 when prompted to enter a number. The
output should look like the one in Figure 7.3.
The Chr function converts an Integer to a Char, while the Asc function is
the reverse, and will convert a Char to an Integer. In your example the
Integer value i was 65 (if you typed the indicated number) and was trans-
formed in the Char value ‘A’ when assigned to the variable c. The value 65
is the UNICODE number (code) for the character ‘A’. Each character in the
UNICODE set has (as you saw in Chapter 6, “Fundamental Data Types,”) a
number or code associated with it. The Chr function transforms an Integer
representing this code into a Char, while the Asc function transforms a
Char into the associated code.
NOTE
Asc and Chr are quite venerable BASIC functions, standing for “to character” and “to
ASCII.” As we mentioned above, ASCII is a subset of UNICODE characters that was
(and still is sometimes) used in older computers and operating systems to represent
characters.
In the rest of this chapter you will look at a few different types of operators
and functions. In the final part of the chapter you will learn how to com-
bine variables, values, operators, and functions into expressions.
In-place Operators 109
In-place Operators
You have seen what the arithmetic operators are for the basic operations:
addition, subtraction, multiplication, division, modulo, and exponentiation.
You will learn now a few new operators that are based on these arithmetic
operators. They are called in-place arithmetic operators.
Consider the following example, which declares a variable i as Integer and
initializes it to 6, and then increments its value by 3.
Dim i As Integer = 6
i = i + 3
It happens that this type of code occurs quite frequently in day-to-day pro-
gramming. As programmers (and language architects) are practical people,
they decided that the expression could be simplified by writing it as:
Dim i As Integer = 6
i += 3
Note how the i was omitted from the right side of the assignment operator,
and the plus sign was moved in front of equal to create the new in-place
operator “+=”. The two expressions are identical in results, with the excep-
tion of the second version being shorter and somewhat more intuitive: you
are not assigning a brand new value to i, which happens to be made of the
old value of i + 3. But rather you increment i “in-place” by 3. It is up to you
to use the form that you like. Most people with background in C/C++/Java
will use the second form, while people who use an older dialect of BASIC or
Visual Basic are more familiar with the first form.
Similar operators are available for most of the other arithmetic operators
(except modulo). The following example illustrates some of these in-place
operators. Create a new console project and name it “InPlaceOps,” and then
add the following lines to it.
Sub Main()
Dim i As Integer = 12
i -= 3 ‘ i is now 9
Console.Out.WriteLine(“The Integer value i is {0}”, i)
i *= 3 ‘ i is now 27
Console.Out.WriteLine(“The Integer value i is {0}”, i)
i \= 9 ‘ i is now 3
Console.Out.WriteLine(“The Integer value i is {0}”, i)
d ^= 3 ‘ d is now 1363.938029
Console.Out.WriteLine(“The Double value d is {0}”, d)
Dim s As String = “i is “
s &= CStr(i) ‘ s is now “i is 3”
Console.Out.WriteLine(“The String value s is ‘{0}’”, s)
Save and run the program, and ensure the values displayed are as pre-
dicted in the comments. The only other notable operator you used is the in-
place String concatenation operator &=. It is used to concatenate the result
of the String conversion of the Integer i (using CStr(i)) to the original
value of s (“i is ”). The result is the displayed string “i is 3” delimited by sin-
gle quotes.
Comparison Operators
Another class of operators commonly used in programming is the compari-
son operators, also known as relational operators in mathematics. These
operators compare two values and return a Boolean value (True or False)
depending on the result of the comparison. For example:
Dim i As Integer = 3, b As Boolean
b = i < 5
With the exception of the last two special operators (Like and Is, which you
will study later on) the rest are common mathematical operators. The sym-
bols used are slightly different, but the meaning is the same.
One thing to note is that the = symbol is used for both assignment and
equality. This can cause confusion sometimes because an expression like “i
= 3” can mean either “assign 3 to i” or “verify if i is equal to 3,” depending
on the context in which it is used.
Boolean Operators
The boolean or logical operators are commonly used to combine Boolean
values or expressions into more complex Boolean expressions. For example
Dim i As Integer = 3, j As Integer = 5, b As Boolean
b = i < 5 And j >= 6 ‘ b is False
The comparison expressions i < 5 and j >= 6 are combined by the logical
operator And. And has the exact meaning as in English: if both comparison
expressions (i < 5 and j >= 6) are true, the result is True. If at least one of
the expressions is false, the result of the logical And operation is False. This
result will be assigned to the Boolean variable b.
Visual Basic also has an Or logical operator, which is the equivalent of the
English meaning of the word “or”. Here is the same example as before:
Dim i As Integer = 3, j As Integer = 5, b As Boolean
b = i < 5 Or j >= 6 ‘ b is True
In this case b will be True if at least one of the expressions i < 5 and j >=
6 is true, or potentially both of them are true. It will be False if both i < 5
and j >= 6 are false.
There is also an exclusive-or operator (Xor) that can be used to determine if
one or the other of the expressions is True, but not both at the same time.
Reusing the same example:
Dim i As Integer = 3, j As Integer = 5, b As Boolean
b = i < 5 Xor j >= 6 ‘ b is True
112 Chapter 7: Data Conversions and Expressions
j = 7
b = i < 5 Xor j >= 6 ‘ b is False
The fourth logical operator used is the unary Not operator. It can be applied
to a Boolean expression to negate (reverse) the value, that is, if the value is
True it will yield False, and the opposite. For example:
Dim i As Integer = 3, j As Integer = 5, b As Boolean
b = i < 5 Or j >= 6 ‘ b is True
b = Not b ‘ b is False
The last statement assigns to b the opposite of what the current value of b
is currently. In your case b is True; therefore it will assign False to it.
compiler first add 5 and 3 and then multiply the result by 2 you would
write it as:
i = (5 + 3) * 2
In Table 7.3 you can see the three types of operators and their precedence
and operator type, from the highest ones to the top of the table to the low-
est precedence to the bottom of the table.
As you can see the operators are grouped based on their type. The ones
with the higher precedence are the arithmetic and concatenation operators,
followed by the comparison operators, and at the end you have the logical
operators.
Operators that are of the same precedence (like addition and subtraction,
for example) are evaluated in order from left to right.
Expressions are the most common programming construct of any program-
ming language. They are used in all statements that you have seen and in
many more that you will learn about in this book.
Although expressions are not complicated, it is important that you under-
stand them properly before proceeding forward.
114 Chapter 7: Data Conversions and Expressions
What’s Next
In the next chapter you will learn about some slightly more complicated
data types that Visual Basic .NET uses. You will study arrays, enumera-
tions, and structures—the first user-defined data type.
You will learn how to declare single and multi-dimensional arrays, and how
to access array elements and use them in expressions. Next you will look at
enumerations: why would one use them and how.
The second part of the next chapter will be concerned with structures.
You will learn the basic concepts of these user-defined data types: how to
declare and use them, as well as some introductory concepts on objects and
references.
NOTE
The answers to the “Reviewing It,” “Checking It,” and “Applying It” sections are avail-
able on our Web site.
Reviewing It
This section presents a review of the key concepts in this chapter. These
questions are intended to gauge your absorption of the relevant material.
REVIEW
1. What is the difference between implicit and explicit data conversion?
2. Can you convert a String value to a double? If yes, how?
3. What is an in-place operator?
4. What is a comparison operator? Give examples.
5. What is a Boolean operator? Give examples.
6. What is an expression?
Checking It
Select the correct answer to the following questions.
CHECK
Multiple Choice
1. An implicit numeric conversion is performed when:
a. A numeric value is assigned to another numeric value of a type
that is of a larger size.
b. A numeric value is assigned to another numeric value of a type
that is of a smaller size.
Checking It 115
c. Both a and b.
d. Neither a nor b.
2. CSng() is used to convert:
a. Numeric types to Decimal.
b. Numeric types to Single.
c. Numeric types to Double.
d. Any type to Single.
3. What is the result of the following expression: Asc(Chr(66))?
a. Character B.
b. 66.
c. It is an invalid expression; Chr() does not accept an Integer
parameter.
d. It is an invalid expression, Asc() does not accept a Char
parameter.
4. Is “0 <= i <= 100” a valid Visual Basic expression?
a. Yes.
b. No. Correct would be “0 <= i Or i <= 100”.
c. No. Correct would be “0 <= i And Not i <= 100”.
d. No. Correct would be “0 <= i And i <= 100”.
5. Assuming all variables (i, j, and k) are Integers initialized to 2, what
is the outcome of the expression “i * 4 \ j \ k”?
a. 1.
b. 2.
c. 4.
d. 8.
6. Assuming all variables (i and j) are Integers initialized to 2, what is
the outcome of the expression “i ^ 2 >= 0 And j – 2 <= 0”?
a. 0.
b. 4.
116 Chapter 7: Data Conversions and Expressions
c. True.
d. You cannot evaluate the expression until it is executed at run-
time.
7. What means to short-circuit evaluate a Boolean expression?
a. Evaluate from left to right in a fast manner.
b. Bypass type checking when evaluating a Boolean expression.
c. Evaluate the expression until the first False is encountered.
d. Evaluate the expression until the result is determined and ignore
the rest of the expression.
True or False
Select one of the two possible answers and then verify on our Web site that
you picked the correct one.
1. A numeric type can be implicitly converted to Boolean.
True/False
2. A numeric type can be explicitly converted to Boolean.
True/False
3. A numeric type can be explicitly converted to Char.
True/False
4. A numeric type can be explicitly converted to Date.
True/False
5. Boolean operators have highest precedence.
True/False
6. Expressions can contain only comparison and Boolean operators.
True/False
Applying It
Try to complete the following exercises by yourself.
A P P LY
Independent Exercise 1
Create a new console project that reads two Double numbers from the user,
multiplies the two, and displays the result.
Applying It 117
Independent Exercise 2
Create a program that reads two Boolean values from the user, computes
the exclusive or of the two values, and displays the result.
8
Arrays, Enumerations, and Structures
In this chapter you will study a few more advanced and also more useful
data types: arrays, enumerations, and structures. These data types are also
known as structured data types.
The chapter is structured as follows:
• Arrays
• Enumerations
• Structure declaration
• Using the structured data types
You will start by learning about arrays: what an array is, how to declare an
array, how to access the elements of an array, how to modify the size of an
array, and how to remove all elements from an array.
Next you will look at enumerations. You will learn how to declare and use
them, as well as when to use an enumeration versus using regular integral
data types.
In the second part of the chapter you will learn about structures and the
art of user-defined types. You will learn how to declare a structure, what
are structure members, and some issues related to members visibility.
You will also learn the basic steps in using structured data types: arrays,
enumerations, and structures, namely assignment behavior for structured
data types.
120 Chapter 8: Arrays, Enumerations, and Structures
Arrays
You have seen how a variable of a given data type is but a name for a mem-
ory location that can store a value of that type. Now what would you do if
you would like to have a whole bunch of values of the same type stored as
compact as possible and have the same name and some indexing scheme to
be able to identify any given value? The answer is quite simple: you would
have an array.
For example let’s consider that you need to operate on five accounts,
namely on the balances of these accounts. You could declare a variable for
each account that will hold the balance for that account, as in the following
example:
Dim balance1 As Decimal
Dim balance2 As Decimal
Dim balance3 As Decimal
Dim balance4 As Decimal
Dim balance5 As Decimal
Or you could use an array of five account balances—in this case an array of
five Decimal values. An array is a type of data that can hold more than one
value of a given data type. These values are called array elements (or items)
and they are of the same data type (as specified in the array declaration).
You can think of an array as a list of items, each item in the list being an
array element. You would declare an array as shown in the following exam-
ple:
Dim balance(4) As Decimal
This statement will do something very similar with the previous one, which
declared five variables of Decimal type. It will allocate memory for five val-
ues of Decimal type. The way to access these values is slightly different, as
you will soon see. The number in parentheses following the name of the
array variable balance is known as the array upper bound, and represents
the number of values in the array, plus one. In order to access any value in
the array you would use its index. The index of an array element is the
actual position of that element in the array. The first element in the array
is at position (or index) 0. The next one is at position 1, and so on, up to
position array upper bound – 1, where array size is the size declared in the
array declaration. Have a look at the following example:
Dim balance(4) As Decimal
balance(0) = 100
balance(4) = 250
Arrays 121
This code will create an array of five Decimals, will set the value of the first
element of the array to be 100, and then will declare a Boolean variable
and assign to it the result of evaluating a logical expression. The logical
expression compares the value of the array element at position 0 (the one
you just set to be 100) to the literal value 250. In a similar fashion you
could use array elements in any type of expression.
You have seen that regular variables can be initialized when declared.
Could you do the same thing for arrays? The answer is yes and the example
that follows illustrates how to do it. Create a new console project and name
it ArrayExample. Then enter the code as shown in the Sub Main:
Sub Main()
Dim balance() As Decimal = {100, 200, 300, 400, 250}
Console.Out.WriteLine(“The value of array element 0 is {0}”, balance(0))
Console.Out.WriteLine(“The value of array element 1 is {0}”, balance(1))
Console.Out.WriteLine(“The value of array element 2 is {0}”, balance(2))
Console.Out.WriteLine(“The value of array element 3 is {0}”, balance(3))
Console.Out.WriteLine(“The value of array element 4 is {0}”, balance(4))
Dim b As Boolean
b = balance(0) <= 500
Console.Out.WriteLine(“The value b is {0}”, b)
122 Chapter 8: Arrays, Enumerations, and Structures
Please note the first line, which is the declaration and initialization state-
ment for the array. The first difference you see is that there is no array size
specified in parentheses (although the parentheses themselves are still pre-
sent). Next, it is easy to see the initialization code following the = sign. The
arrays are initialized using a set of literal values of the appropriate type,
delimited by the open and closing curly braces. A comma is required to
delimit any individual array element from the next one. Because the com-
piler knows exactly how many elements are in the initialization values lit-
eral array (that is, the values between the { and } braces), it does not need a
size for the arrays that are initialized as shown. It is actually a syntax
error to provide a size, and the IDE and compiler will flag it appropriately.
Next in the sample you output the value of each array element to the con-
sole, and then you declare a Boolean and set it to be the result of the
expression, as described previously. You then output the value of the vari-
able b to the console. Save and run the project and the results should be
similar to those shown in Figure 8.1.
It is quite seldom that you know up front what is the size of the array that
you will need. Quite often this size is determined at runtime. This implies
that you need the capability to declare an empty array (or a placeholder)
and then initialize it when you know what the size of the array is. This is
called dynamic initialization of an array. Our example can be modified to
illustrate this way of using an array:
Sub Main()
Dim balance() As Decimal
Arrays 123
Dim b As Boolean
b = balance(0) <= 500
Console.Out.WriteLine(“The value b is {0}”, b)
As you can see the modifications are minor: you have removed the initial-
ization code from the array declaration line, and you have added a new line
that assigns a new array of five Decimal values (specified between the { and
} braces) to the balance array variable. If you did not know the values for
the new array you could use something like:
balance = New Decimal(n) {}
Where n is the upper bound of the new array (and it can be a variable),
while the empty curly braces are needed to indicate it is an array that is
being constructed. Note also the use of the keyword New—we will come
back to it when you learn about objects and classes.
This simple example is meant to illustrate how to declare and initialize the
values in an array, and then how to access these values. An array is quite
similar to the mathematical concept of a matrix with one dimension (for the
examples you have seen so far). But as you will see next, arrays can have
more than one dimension. For example, to represent the values of the bal-
ances of the five accounts over the course of three years you would need
either three arrays (one per year, each array with five values for the bal-
ances in that year) or you could use a matrix with two dimensions. In pro-
grammer parlance this construct is called a two-dimensional array. Arrays
in Visual Basic can have up to 60 dimensions (dimensions, not elements!),
although more than three dimensions is quite unusual.
Declaring a multidimensional array is very similar to declaring a one-
dimensional array you have seen. The following example illustrates this:
Dim balance(2, 4) As Decimal
This declares an array with three dimensions, the upper bound of each
dimension being 9 (a total of 1,000 Double elements). As you can see the
size of the array increases very fast for multidimensional arrays, so one has
to be careful on when and how one of these arrays is used.
To access an array element from a multidimensional array you need to
specify an index for each of the dimensions of the array. In the case of your
two-dimensional array you could use code like this:
Dim balance(2, 4) As Decimal
balance(0, 2) = 300
This example sets the value for the element identified by the indices (0, 2)
to be 300. In the case of a two-dimensional array you can picture this in
terms of rows and columns: the third element on the first row. The indices
are in row-column order, which means that the first dimension (and index)
represents the row(s), and the second dimension represents the column(s).
This type of representation becomes less intuitive when dealing with arrays
with three or more dimensions, but these are rare cases.
Can you initialize a multidimensional array in the same fashion in which
you initialized the one-dimensional array you used in your example? The
answer is yes, and let’s see how. Modify the sample project you used previ-
ously so that the code looks like this:
Sub Main()
Dim balance(,) As Decimal = {{100, 200, 300, 400, 250}, _
{100, 200, 300, 400, 250}, _
{100, 200, 300, 400, 250}}
Console.Out.WriteLine(“The array element 0,0 is {0}”, balance(0, 0))
Console.Out.WriteLine(“The array element 0,1 is {0}”, balance(0, 1))
Console.Out.WriteLine(“The array element 0,2 is {0}”, balance(0, 2))
Console.Out.WriteLine(“The array element 0,3 is {0}”, balance(0, 3))
Console.Out.WriteLine(“The array element 0,4 is {0}”, balance(0, 4))
Dim b As Boolean
b = balance(0, 0) <= 500
Console.Out.WriteLine(“The value b is {0}”, b)
Do not omit the _ (underscore) characters at the end of the lines after the
commas. This is the line-continuation character in Visual Basic. If you need
to write a line that is longer than will fit in the editor window (or if you
simply want to make the code look better), you can continue that line on
the next line by adding the underscore character at the end of the line.
Each statement in Visual Basic ends at the end of the line unless you have
the underscore symbol as the last symbol on the line, in which case the
compiler will interpret the following line as a continuation of the current
line.
In this case you are declaring an array with two dimensions and then ini-
tializing it to the set of values specified after the = symbol, between curly
braces. The values are entered as the array would contain other arrays,
and each of these arrays in turn contains the values. Note the fact that the
two dimension sizes are empty “(,)”, for the same reason as in the case of
the one-dimensional array: the compiler can determine the sizes of each
dimension. The number of dimensions is indicated by the number of
commas between the parentheses (0 = one-dimensional array, 1 = two-
dimensional array, and so on). It now becomes clear why you split the
initialization line into three lines: the values are positioned in the same
way as the corresponding elements would be represented in the array after
it is initialized.
The rest of the program is very much the same, except that the individual
elements of the array are now accessed using two indices instead of one
(the row and column).
In a similar fashion to the one-dimensional arrays, you can use a notation
to declare an array of a known number of dimensions but unknown sizes,
and then use the New keyword to construct an array and assign it to the
declared variable. For example:
Dim balance(,) As Decimal
balance = New Decimal(2, 4) {}
Enumerations
Let’s assume you have been given the task of writing a subsystem for a
game of cards (like bridge, for example). Your task is to determine if a given
card from the deck was used already. That means you need some means to
represent the deck of cards and remember for each card if it was used or
126 Chapter 8: Arrays, Enumerations, and Structures
not. A deck of cards consists of 52 cards divided into 4 suits (clubs, dia-
monds, hearts, and spades). Each suit consists of the cards from 2 to 10, the
Jack, Queen, King, and Ace of the suit.
To store the fact that a card was used you can use an array of 52 Boolean
values. Or even better (more intuitive) you could use a two-dimensional
array of 4 rows (one per suit) and 13 columns (one for each card in the
suit). Deciding that you use the latter version, you are faced with another
issue. What would the correlation be between the indices and the suits and
cards? That is, to find out if the Queen of Hearts was used, at what row
and column do you need to retrieve the element in the array? You could
arbitrarily establish that you use 0 for clubs, 1 for diamonds, 2 for hearts,
and 3 for spades, and 0 for the Two, 1 for the Three, …, 12 for the Ace in
each suit. That means you could find out if the Queen of Hearts was used
by getting the value of the array element at position (2, 10). However this is
not really intuitive and it is error prone: assume that somebody else looks
at your program and tries to figure out what card you are referring to.
There is nothing that tells him that the element at (2, 10) is really the
Queen of Hearts.
But Visual Basic allows you to use a better approach to this problem using
enumerations. An enumeration is a set of values that are given a name, and
can be used as a data type. For example you could define an enumeration
for the card suits:
Enum CardSuit
clubs
diamonds
hearts
spades
End Enum
You can see that the enumeration declaration is delimited by the keyword
Enum followed by the enumeration name, and End Enum, which marks the
end of the declaration. This declaration declares a new data type that con-
sists of only four possible values. You can use this data type to declare new
variables and build expressions, like any of the fundamental data types.
For example you could write code like this:
Dim cs As CardSuit = CardSuit.hearts
cs = CardSuit.clubs
You declare and initialize the cs variable to be of type CardSuit, which you
have defined as an enumeration with the four possible values. You can
assign new values (from the enumeration) to the new variable, or output
the value of the variable to the console (as you will see soon).
Enumerations 127
Create a new console project and name it EnumExample. Enter the code
that follows.
NOTE
The Enum declarations are outside the Sub Main body. This is because they are type
declarations—they define new types.
Module Module1
Enum CardSuit
clubs = 0
diamonds = 1
hearts = 2
spades = 3
End Enum
Enum CardRank
two = 0
three = 1
four = 2
five = 3
six = 4
seven = 5
eight = 6
nine = 7
ten = 8
jack = 9
queen = 10
king = 11
ace = 12
End Enum
Sub Main()
Dim deck(4, 13) As Boolean
End Module
When you declare the type for the cs and cr variables, the newly defined
types (CardSuit and CardRank) are in the IntelliSense list of available types.
The same applies for when you assign a value to one of the two variables: a
list of possible values is displayed. That makes it easier to use than using
the Integer values.
The Enum elements are in effect Integers, and, as you can see from the pre-
vious code listing, you can explicitly assign values to each element of en
enumeration. If you do not assign any value, the elements will have the
value equal to their position in the enumeration (starting with 0). You can
have negative values and multiple elements with the same value, if
required.
If you execute this program you will notice that the output values for both
cs and cr are the element names hearts and queen, respectively. But you
can use these enumerated values as regular Integers. This is illustrated by
the two assignments to the bUsed variable. The first one uses the cs and cr
variables to access the array element for the Queen of hearts. The second
assignment uses the explicit enumerated values to get the array element
for the Ace of Spades.
In summary you can say that enumerations are useful in defining new data
types that are subsets of the Integer data type. Each element in the subset
has a name—which is a valid Visual Basic identifier. Elements can be used
in the same way as any literal value. So instead of using the Integer literal
2 you use CardSuit.hearts.
Structure Declaration
A structure is a complex data type that consists of one or more members
(also known as fields). Let’s look at an example so that you understand bet-
ter. Assume that you are dealing with a graphics application that requires
you to access (get and set) the color of a point (known as pixel) anywhere on
the display, as well as other graphic operations that require the pixel coor-
dinates. You can represent the address of any point on the screen as a pair
of x and y coordinates. That means that any time you need to operate on a
given point you need to specify both the x and the y coordinate. It would be
useful to be able to treat each pixel as a unit, rather than dealing with
Structure Declaration 129
independent x-y numbers. That is where the structures come into consider-
ation. You can declare a structure that consists of the x and y coordinates
for any pixel.
Create a new console project and name it StructExample. Enter the follow-
ing code in Module1. Note that the Structure declaration is outside the body
of Sub Main, as expected, because it is a type declaration.
Module Module1
Structure PixelCoord
Public x As Single
Public y As Single
End Structure
Sub Main()
Dim p As PixelCoord
p.x = 200
p.y = 100
Console.Out.WriteLine(“The value p.x is {0}”, p.x)
Console.Out.WriteLine(“The value p.y is {0}”, p.y)
End Module
From this code you can see that the structure declaration is delimited by
the keyword Structure, followed by the structure name, and the End
Structure keyword, which marks the end of the declaration. Inside the
structure declaration you have the structure member declarations. Each
member of a structure is a variable of a specified type. You use syntax simi-
lar to the Dim statement you have used in declaring variables so far, except
for the fact that the keyword Public is used to declare the members of the
structure.
NOTE
The Public keyword indicates that the member is visible (accessible) outside the struc-
ture. You will understand more when you will learn of visibility later on in the book.
You are declaring a new data type that consists of two Single values, the
first one named x and the second one named y. When the compiler will allo-
cate memory for a variable of this type it will allocate a memory location
that is equal with the combined sizes of its members (two Single values in
this case).
130 Chapter 8: Arrays, Enumerations, and Structures
This structure allows you to declare variables that better represent one
pixel. You can access structure members using the dot-notation. That is you
use the period (known as “dot” in programmer dialect) after a variable of
structure type, to access any of its members. You have probably noticed
that, when you type the dot after the name of the variable p, a list of mem-
bers appears that includes the x and y members you declared, and some
other names that are not present in your structure declaration. This is
quite all right; you can think of these as some members that all structures
have. You will understand better what these members are when you are
going to study objects and classes. You will ignore them for now.
In the Sub Main you declare a variable of the PixelCoord type, you set the
values of the two structure members and then you output these values to
the console. You could use any of these values in an expression, as you
would any variable of Single type. The difference is that the name of the
variable is composed of the name of the structure variable + the name of
the member, accessed using the dot-notation, p.x.
As mentioned earlier, the data types of the structure members can be any
valid data type. That of course includes all the fundamental data types (like
Integer, String, and so on), but it also includes arrays, enumerations and
other structures. Let’s look at a more complex example. Modify the code you
have entered to look like the code listed below:
Module Module1
Enum PixelColor
red
green
blue
End Enum
Structure PixelCoord
Public x As Single
Public y As Single
Public flags() As Byte
Public color As PixelColor
End Structure
Structure Rectangle
Public topLeft As PixelCoord
Public topRight As PixelCoord
Public bottomLeft As PixelCoord
Public bottomRight As PixelCoord
Public fillColor As PixelColor
End Structure
Structure Declaration 131
Sub Main()
Dim r As Rectangle
r.topLeft.x = 100
r.topLeft.y = 100
r.topLeft.color = PixelColor.green
r.topRight.x = 300
r.topRight.y = 100
r.topRight.color = PixelColor.green
r.bottomLeft.x = 100
r.bottomLeft.y = 300
r.bottomLeft.color = PixelColor.green
r.bottomRight.x = 300
r.bottomRight.y = 300
r.bottomRight.color = PixelColor.green
End Module
You have added a PixelColor enumeration with three elements (red, green,
and blue). You will use this enumeration to indicate the color of a given
pixel. You have changed the PixelCoord structure to include an array of
flags as Byte values, and a color member declared as an enumerated value
of type PixelColor.
You have also added a new structure named Rectangle that contains four
members of PixelCoord type (one of each of the four corners of the rectan-
gle) and one member of the enumerated PixelColor type, which indicates
the color used to fill the rectangle.
In the Sub Main you declare a variable of type Rectangle and then you
assign values to its members. Because some of its members are structures
too, you use the dot-notation recursively to access the members of its mem-
bers that are structures. For example to access the x and y coordinates of
the top-left corner of the rectangle you use r.topLeft.x and r.topLeft.y. In
this example r is the variable of Rectangle type, topLeft is a member of the
Rectangle structure, and it is of type PixelCoord. The x and y are members
of the PixelCoord structure and are of Single type.
132 Chapter 8: Arrays, Enumerations, and Structures
Variable i 6 Variable i 6
ByVal Assignment: j = i
Variable j 0 Variable j 6
Variable i 6 Variable i 6
ByRef Assignment: j = i
Variable j 0 Variable j
Module Module1
Structure Card
Public name As String
Public pcid As Integer
End Structure
Sub Main()
Dim i As Integer = 7, j As Integer = 3
System.Console.Out.WriteLine(“BEFORE i is {0} and j is {1}”, i, j)
i = j
j = 2
System.Console.Out.WriteLine(“AFTER i is {0} and j is {1}”, i, j)
c1 = c2
c2.name = “Joe”
c2.pcid = 123
Console.Out.WriteLine(“AFTER c1.name is {0} and c1.pcid is {1}”, _
c1.name, c1.pcid)
134 Chapter 8: Arrays, Enumerations, and Structures
End Module
First you declare a two-member structure that you will use in the example.
Your example consists of three parts: the assignment of two Integer vari-
ables, two Card structure variables, and two arrays.
In the case of the Integer variables you declare and initialize them, and
then output their values to the console before the assignment. You then
assign j to i and then change the value of j. If the assignment would be by
reference, you would see the value of i change as well. You verify that this
is not the case by outputting the values of i and j to the console, and indeed
the i and j hold different values.
You apply the same procedure for two variables, c1 and c2, of Card struc-
ture type. You declare and initialize the variables, then their values
BEFORE the assignment are outputed to the console. Then you assign c2 to
c1, and change the values for both members of c2. If the assignment would
be by reference, that would change the values of c1 as well. You output the
value of both variables and verify that indeed this is not the case.
The final portion of your test will verify that the array assignment takes
place by reference. Create two arrays (a1 and a2) of Integer values, and ini-
tialize them with different values. Verify that the element 3 of both arrays
contains different values BEFORE the assignment. Then assign a2 to a1,
and then change the value of the element 3 of the a1 array to –1. When you
output the values to the console for the element three in both arrays, you
will find out that both values are –1. You have never assigned –1 to the
a2(3), therefore the only way it can have this value is if both a1 and a2
arrays are actually referring to the same array now. That means the
assignment operator is behaving by reference for arrays.
Checking It 135
What’s Next
In this chapter you studied how to declare and use some advanced data
types. You learned what arrays, enumerations, and structures are and a
few examples of how to use them. You have also seen what by value and by
reference behavior is for assignment.
In the next chapter you will study some of the control statements of Visual
Basic, namely branching and loop statements.
You will study the If and Select Case statements, and then the Do While,
While, and For loops.
NOTE
The answers to the “Reviewing It,” “Checking It,” and “Applying It” are available on our
Web site.
Reviewing It
This section presents a review of the key concepts in this chapter. These
questions are intended to gauge your absorption of the relevant material.
REVIEW
1. What is an array?
2. Enumerate all methods by which you can set the values of array ele-
ments.
3. What is an enumeration?
4. What is a structure?
5. What is the purpose of the dot-notation?
6. What is the difference between by-value and by-reference assignment?
Checking It
Select the correct answer to the following questions.
CHECK
Multiple Choice
1. By array dimension you understand:
a. The number of elements the array holds.
b. The measure of the array in one direction (coordinate).
c. The structure of the memory location for the array.
d. The size of the array as a whole.
136 Chapter 8: Arrays, Enumerations, and Structures
a. 45.
b. 60.
c. 345.
d. As many as required; it will grow to accommodate new elements.
4. Can enumeration elements be used as array indices?
a. Yes.
b. No. Only integers can be used as array indices.
c. Yes, but a conversion function must be used.
d. No. Array indices must be literals.
5. Can a structure member (field) be an array?
a. Yes.
b. No.
c. Yes, but only one-dimensional arrays.
d. Yes, but only uninitialized (dynamic) arrays.
6. Can array elements be structures?
a. Yes.
b. No.
c. Yes, but only structures without array fields.
d. No, arrays must be of fundamental types only.
7. If you have an array A and an array B, and you assign B to A, and
then change the value of one element of A (for example A(0)), what
happens to the corresponding element B(0)?
Checking It 137
True or False
Select one of the two possible answers and then verify on our Web site that
you picked the correct one.
1. The size of an array is the sum of the sizes of each dimension.
True/False
2. The elements of an array are all of the same type.
True/False
3. An array must be initialized upon declaration.
True/False
4. An enumeration is the same as an array, but it has names for its ele-
ments.
True/False
5. Structures can contain other structures as members.
True/False
6. Structures are assigned by value (values of individual members are
copied into the assignment target).
True/False
138 Chapter 8: Arrays, Enumerations, and Structures
Applying It
Try to complete the following exercises by yourself.
A P P LY
Independent Exercise 1
Create a new console project that declares a one-dimensional array of
Strings of size 3. Have the user enter values for the elements of the array
and then concatenate the elements and display the result.
Independent Exercise 2
Create a program that declares a structure for the personal information
about an individual: last name, first name, date of birth, and gender. Then
get the user to fill in information about itself and output this information to
the console.
9
Control Statements
In this chapter you will learn the fundamental control statements used by
the Visual Basic language. These are statements that control the flow of the
programs, and they can be classified in two categories: branching state-
ments and loop statements. You will study the fundamental Visual Basic
branching and loop statements in this chapter, structured as follows:
• The If statement
• The Select Case statement
• The For loop
• The Do loop
• The While loop
The programs you used as examples up to this point were linear programs;
that is, they started in one point (after the Sub Main) and continue in a lin-
ear fashion by executing all statements between the starting point and the
end point (the End Sub statement). Real-life programs are seldom that sim-
ple. Most frequently you must execute some block of statements only if
some condition is met. Or you may need to execute one statement multiple
times. That is, you must be able to control the execution flow of the pro-
gram—hence the name control statements.
There are two types of control statements: branching statements and loop
statements. The branching statements are used to selectively execute a
group of statements only when a condition is met. Branching statements
are the If and Select Case statements. The loop statements are used to
execute a group of statements multiple times. The loop statements that you
will learn in this chapter are the For loop, Do loop, and While loop.
142 Chapter 9: Control Statements
The If Statement
The If statements is one of the most common Visual Basic statements. It
allows you to execute one or more statements only when a specific condition
is met. This condition is a Boolean expression that will evaluate to True or
False. Let’s look at an example:
Sub Main()
Console.Out.WriteLine(“Enter a value for i and press <ENTER>: “)
Dim i As Integer
i = CInt(Console.In.ReadLine())
If i < j Then
Console.Out.WriteLine(“i is less than j”)
End If
These example declare two Integer variables i and j and gets some values
for them from the user. Then if i is less than j it will output to the console
the string “i is less than j”. For this you used an If statement. The If state-
ment consists of the keyword If followed by the Boolean expression and the
keyword Then. On the next line you have the statement that you want to
execute conditionally. You can have more than one statement here. The If
statement must always end with the End If keywords.
What happens at runtime is probably quite clear by now: first the Boolean
expression “i < j” is evaluated. If this expression is true (that is, if i holds a
value that is less than the one j is holding), the statements between the
Then and End If statement are executed. If the expression is false (that is, i
is less than or equal to j) the statements are not executed. That means con-
trol will be transferred to the first statement following the End If state-
ment.
To run the example, create a new console project and call it IfExample, and
then enter the code as shown previously, and run it. If you enter a value for
i that is less than the value for j (such as 3 and 5) the output will look like
Figure 9.1.
The If Statement 143
If i is greater than or equal to j then the output will look like the one in
Figure 9.2.
This line of code does the same thing as the If you have seen previously.
The differences are that the statement that is executed when the expres-
sion is true is on the same line as the If...Then statement, and the End If
is missing.
144 Chapter 9: Control Statements
NOTE
This form of If is useful in some instances when there is only one statement following
the Then and it is short. If there is an Else part (described later in this chapter) or
more than one statement, then the block-If statement form should be used.
There are cases when you would like to execute some statements when a
condition is true, and some other statements when the condition is false. To
continue this example, you would like to display the text “j is less than or
equal to i” if your expression (i < j) is false. You can use another form for
the If statement to achieve this. Modify the If statement in the previous
example to look like the code in bold:
If i < j Then
Console.Out.WriteLine(“i is less than j”)
Else
Console.Out.WriteLine(“j is less than or equal to i”)
End If
You use the keyword Else to delimit the statements that will be executed if
the condition is true and the ones that are executed when the condition is
false. If the expression i < j is true then the statements between Then and
Else are executed; otherwise the statements between Else and End If are
executed. This form of the If statement is also quite common.
There is a corresponding form of the single-line If statement that uses the
Else keyword as well:
If bDebug Then Stop Else End
In this example if the value of the bDebug variable is True then the state-
ment Stop is executed; otherwise, the statement End is executed.
WARNING
We believe this form is less readable than the block-If statement, and should not be
used. It is included here for completeness.
The new lines (in bold) illustrate a way to branch in three cases. First the
expression i < j is evaluated, and if it is True, the statement between Then
and ElseIf is executed. If i < j is False, the expression of the following
ElseIf is evaluated. If it is True the statements following the Then and the
following Else or ElseIf are executed. Finally if none of the expressions
evaluated are True the Else statements are executed. The If statement is
equivalent to a group of nested If statements as in the following example:
If i < j Then
System.Console.Out.WriteLine(“i is less than j”)
Else
If i = j Then
System.Console.Out.WriteLine(“i equals j”)
Else
System.Console.Out.WriteLine(“j is less than i”)
End If
End If
The former example is clearer, in this case. The ElseIf form becomes more
readable if there are multiple conditions to test. A few important things to
remember are that you can have more than one ElseIf part and that the
Else part is not mandatory.
Considering what you have learned about the If statement so far you could
use the following expression to describe the general syntax of an If state-
ment:
If <expression-1> Then
<statements-1>
[ElseIf <expression-2> Then
<statements-2>]
…
[ElseIf <expression-n> Then
<statements-n>]
[Else
<else-statements>]
End If
146 Chapter 9: Control Statements
The detailed syntax for the If and all other statements in the book is
shown on our Web site.
The keywords are in bold. <expression-1>, <expression-2>, and so on are
placeholders for the actual Boolean expressions that would be used.
<statements-1>, <statements-2>, …, <else-statements> are placeholders
for the actual statement(s) that will be placed in the respective position in
the statement. The use of braces [ ] denotes an optional part of the state-
ment, that is, it can be omitted and the statement would still be correct.
The use of … (ellipsis) denotes the fact that the part of the statement pre-
ceding it can be repeated. In our example here we mean that the ElseIf
optional part can be repeated more than once. You can have 0 or more
ElseIf parts of the statement. We will use the same conventions to for-
mally illustrate the syntax of the other statements you will encounter in
this book.
Select Case s
Case “Bob”
Console.Out.WriteLine(“Hi Bob!”)
Case “Gabriel”
Console.Out.WriteLine(“You again?!”)
Case “Jim”
Console.Out.WriteLine(“You are a male!”)
Case “John”
Console.Out.WriteLine(“You are a male!”)
Case “Tom”
Console.Out.WriteLine(“You are a male!”)
Case “Rob”
Console.Out.WriteLine(“You are a male!”)
Case “Joanne”
Console.Out.WriteLine(“You are a female!”)
The Select Case Statement 147
Case “Sarah”
Console.Out.WriteLine(“You are a female!”)
Case “Betty”
Console.Out.WriteLine(“You are a female!”)
Case “Jane”
Console.Out.WriteLine(“You are a female!”)
Case Else
Console.Out.WriteLine(“I do not know. Are you an alien?”)
End Select
The logic is quite simple: if you can recognize the name as male or female
(or one of the two authors) you print a message to the console and then
exit. If the name is not recognized, you print a default message and exit.
The implementation of this logic gets the input from the user into the
String variable s and then uses a Select Case statement to branch to the
appropriate statement to execute. Each branch is made of the keyword Case
and the expression that follows it, plus the statements that follow it until
the next Case branch or the end of the statement (End Select) is encoun-
tered. The way the Select Case works is the Select Case expression is
evaluated first (in this case the expression is the String variable s). Next,
each Case expression is evaluated to see if it matches the value of the
Select Case expression. For example, if the user types in “John” the state-
ments following the Case “John” branch would be executed. If no match is
found and there is a Case Else branch present, the statements in the Case
Else are executed. In either case, the execution is then transferred to the
statement following the end of the statement (End Select).
If you run this example you will get an output similar to the one in
Figure 9.3.
You have probably noticed that you have multiple branches that to the
same thing for different values of the Case expression. For example for all
the male names that you know will write the same message (“You are a
male!”) to the console. The same for all the female names. It would be good
if you could somehow compress these branches into one. The Select Case
statement allows you to do this. You can specify multiple values following
the same Case statement, delimited by commas. Change the preceding
example code to the following:
Sub Main()
System.Console.Out.WriteLine(“I am the Oracle and I will guess your gender”)
System.Console.Out.WriteLine(“Enter your first name, then press <ENTER>: “)
Dim s As String
s = System.Console.In.ReadLine()
Select Case s
Case “Bob”
Console.Out.WriteLine(“Hi Bob!”)
Case “Gabriel”
Console.Out.WriteLine(“You again?!”)
Case “Jim”, “John”, “Tom”, “Rob”
Console.Out.WriteLine(“You are a male!”)
Case “Joanne”, “Sarah”, “Betty”, “Jane”
Console.Out.WriteLine(“You are a female!”)
Case Else
Console.Out.WriteLine(“I do not know. Are you an alien?”)
End Select
As you can see this is much easier and compact code. The comma is equiva-
lent to the logical Or statement: if the value of the s string (Select Case
expression) matches any of the values delimited by commas then the state-
ments following this Case will be executed.
The type of the Select Case expression must be either a numeric value or a
string value. The values of the Case expressions must match the type of the
Select Case expression. There are other valid expressions for the Case
expressions, especially when dealing with numeric types. For example,
when using an Integer i:
Select Case i
Case 1, 3, 5
Console.Out.WriteLine(“1, 3 or 5”)
Case 7 To 11, Is >= 15
The Select Case Statement 149
You can specify an interval using the keyword To, or use a comparison oper-
ator (like >=) and the keyword Is. The interval and comparison operators
could be used also for Strings, although is not that frequent.
You could express the syntax of the Select Case statement formally as
follows:
Select Case <select-expression>
Case <case-expression-1>
<statements-1>
…
[Case Else
<else-statements>]
End Select
WARNING
You are not allowed to place any statements between the Select Case line and the
first Case branch.
You are probably wondering whether you could implement the same
example using an If statement with a lot of ElseIf branches, something
like this:
If s.Equals(“Bob”) Then
Console.Out.WriteLine(“Hi Bob!”)
ElseIf s.Equals(“Gabriel”) Then
Console.Out.WriteLine(“You again?!”)
ElseIf s.Equals(“Jim”) Or s.Equals(“John”) Then
Console.Out.WriteLine(“You are a male!”)
…
Else
Console.Out.WriteLine(“I do not know what you are. Are you an alien?”)
End If
If you know the size of the array (the number of elements in the array) that
is a very easy task. What happens if you do not know the size of the array
when you write the program, but rather this information will be supplied to
you when you are at runtime? In this case this method would not work any-
more. You need a new type of statement that would allow you to execute
something like: for each element i of the array vals, get its value and add it
to the variable total. This statement exists and it is called a For loop. Let’s
create a new console project and name it ForLoopExample. Enter the code as
follows in the Sub Main.
Sub Main()
Dim vals() As Integer = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
This program will calculate the sum of the elements of the Integer array
vals from an index given by the user to the last item in the array. To do
this you first get an integer value for the index variable from the user.
Then you check that the value of the index is within the bounds of the
array, between 0 and 9 inclusive. If this is not the case you display a mes-
sage informing the user of the problem, and terminate the program using
the End statement.
NOTE
The End statement can be used as an extreme resort to terminate a Visual Basic appli-
cation. It should be used only in cases when the program cannot continue, and a nor-
mal termination is not possible. You will learn more about End later on in the book.
If the value of the index is valid, you then declare two integer variables.
One is used as a counter (you will see soon what this means). The other one
(total) is used to store the sum of all elements of the array that are
between index and the last element of the array (9).
Then you have the actual For loop, delimited by the keywords For and Next.
The statements inside the loop (between the For and the Next) are known as
the loop body. The variable i is known as the loop counter. The expressions
following the = and the To keyword are known as the range of the counter, or
start and end values, respectively, of the counter. The body of the loop will be
executed a number of times (determined by the value’s start and end). One
such execution is called an iteration. The value of the counter will be incre-
mented for each iteration of the loop. In effect the statements in the body of
the loop will be executed (end – start + 1) times with the counter starting at
start at the first iteration and ending at end value.
In our example, assuming you entered the value 3 for the index variable,
the loop body will be executed 9 – 3 + 1 = 7 times. The counter i will start
as 3 and end up as 9. The body of the loop consists of the statement that
adds to the current value of the variable total the value of the element of
the vals array at position i. That means you will add to total all elements
of the vals array from 3 to 9. And this is exactly what you wanted to do.
If you would like to see how the value of the total variable evolves in time,
you could add an output statement in the loop to display the current value
of the i and the total variables. Modify the For loop to look like this
example:
For i = index To 9
total += vals(i)
Console.Out.WriteLine(“The total value is {0} at i = {1}”, total, i)
Next
Console.Out.WriteLine(“The final total value is {0}”, total)
152 Chapter 9: Control Statements
If you run the program and enter 3 a start index you should get an output
like the one in Figure 9.4.
If the index variable in the example is 9, the loop body would be executed
only once. If the index is greater than 9, the loop body would not be exe-
cuted at all.
The formal syntax for the For loop is
For <counter> = <start> To <end> [Step <step>]
<body-statements>
Next [<counter>]
You have seen what most of these keywords and expressions are. The
optional Step and the expression <step> following are used to control the
value by which the counter is incremented at every iteration, as you will
see later in this chapter. The other element that you have not seen so far is
the optional <counter> following the Next keyword.
Qualified Next
The qualified Next is a feature that allows you to identify easily which Next
belongs to which For, especially in nested loops like the one in the following
example.
Dim i As Integer, j As Integer
For i = 0 To n – 1
For j = 0 To m – 1
‘ statements
Next j
Next i
The compiler does not require that you use the Next j and Next i, but if
you do, you must match it with the appropriate For. For example the
following code is also correct:
The For Loop 153
The use of the qualified Next makes your code more readable, but it is also
more difficult to change. For example, if you need to change the counter
variable name, you will need to change it in one more place. Therefore, it is
a question of personal preference which form you use; each one has its
small advantages and disadvantages.
The counter variable i will start as 1 and will be incremented at every iter-
ation by 2, that is, 3, 5, and so on up to 31.
This feature can be useful to walk through a string or array in reverse
order (from end to start). The next code example will reverse a string the
user enters and output it to the console:
Sub Main()
Console.Out.WriteLine(“Enter the string to revert and press <Enter>:”)
Dim s As String = Console.In.ReadLine()
Dim i As Integer, n As Integer
n = s.Length()
154 Chapter 9: Control Statements
Dim z As String
For i = n - 1 To 0 Step -1
z &= s.Substring(i, 1)
Next
Console.Out.WriteLine(“The reverted string is {0}”, z)
Note how the Step –1 is used in conjunction with the reversion of the val-
ues for start and end (the smaller value is to the right of the To keyword) to
have the loop reversed. (Start with the higher value and decrement at each
step by one, until the lesser value is reached.) This allows you to “walk” the
s String variable in reverse order, from end to start, and add each character
at the current counter position i to the output String z.
Exit For
There are rare cases when you need to exit a For loop before the whole
number of iterations were performed—such as when an error condition
occurs that prohibits the rest of the iterations from being completed. In a
case like this you can use a loop exit statement:
For i = 0 To n - 1
‘ normal loop body
If <some error condition> Then Exit For
Next
The bold statement illustrates the use of the Exit For statement to leave a
For loop before its natural completion. We do not recommend the usage of
this technique in the following pattern: search for something using a For
loop, and when found exit the loop and continue. A Do loop would be much
better for implementing this algorithm, as you will see next.
The For loops are very useful in a lot of programming tasks, from array
manipulation and graphics rendering to database and string handling. But
the For loops are not covering the whole domain of loop programming.
The Do Loop
There are certain cases in which you need to execute the body of the loop
while a specific expression is True (or False). This means executing a loop
an unknown number of times. You would not be able to use a counter and a
range of values, as in a For loop. You can use a Do loop to solve this type of
problem.
The Do Loop 155
In the following example you would like to allow the user to perform a sim-
ple mathematical computation as many times as he or she wishes. To run
the example, create a new console project and enter the code as shown.
Sub Main()
Dim sContinue As String = “yes”
Do While sContinue.Equals(“yes”)
Console.Out.WriteLine(“Enter the value for i and press <Enter>:”)
Dim i As Integer
i = CInt(System.Console.In.ReadLine())
Console.Out.WriteLine(“Enter the value for j and press <Enter>:”)
Dim j As Integer
j = CInt(Console.In.ReadLine())
Console.Out.WriteLine(“The complex math computation yields {0}”, i + j)
Console.Out.WriteLine(“”)
Console.Out.WriteLine(“Enter ‘yes’ to continue, anything else to end,”)
Console.Out.WriteLine(“then press <Enter>”)
sContinue = Console.In.ReadLine()
sContinue = sContinue.ToLower()
sContinue = sContinue.Trim()
Loop
End Sub
You use the String variable sContinue to determine whether the user
wants to execute the body of the Do loop one more time. In the actual body
of the loop, you get two Integer values from the user, add them, and dis-
play the result. Next you ask the user if he or she wants to continue, and
store the String answer into the sContinue variable declared outside the
loop. You convert the string to lowercase (in case the user typed “YES,” for
example) and then you call the Trim() method of the string object (which
will remove the beginning and trailing whitespace characters, such as
spaces and tabs, from the string). When the execution point reaches the
Loop keyword (which marks the loop end) the expression following the Do
keyword is evaluated. In this case the loop will be executed While the
expression sContinue.Equals(“yes”) is True, while the user enters “yes” at
the console. Equals can be thought of as a comparison operator for strings.
You will learn more about it when we learn about classes and objects.
If you run the program and enter some numeric values for i and j, and
enter “yes” when asked to continue, you will get an output like the one
shown in Figure 9.5.
156 Chapter 9: Control Statements
As you can see from this example the Do loop is different from the For loop.
There is no counter variable, no range for the counter, and no Step. The
body of the loop will be executed as long as the conditional expression of the
loop is evaluated to True. Therefore, a loop like the one in the next bad
example will never exit, and it is called an infinite loop.
Do While True
‘ any statements
Loop
Writing a loop like this makes little sense because it is unlikely that you
want to execute this loop for the rest of the eternity. You may encounter
cases where this approach is used in conjunction with the Exit Do state-
ment (which, similar to the Exit For, allows you to unconditionally leave
the loop). The next example illustrates this pattern:
Do While True
‘ any statements
If <condition> Then Exit Do
Loop
Or as an alternative form of the Do loop (you will look at this form shortly):
Do
‘ any statements
Loop Until <condition>
Any of the two alternatives is better because it is clearer what is the condi-
tion for which the loop is executed as part of the loop statement, instead of
being hidden inside the loop body.
The Do Loop 157
Do
Console.Out.WriteLine(“Enter the value for i and press <Enter>:”)
Dim i As Integer
i = CInt(Console.In.ReadLine())
Console.Out.WriteLine(“Enter the value for j and press <Enter>:”)
Dim j As Integer
j = CInt(Console.In.ReadLine())
Console.Out.WriteLine(“The complex math computation yields {0}”, i + j)
Console.Out.WriteLine(“”)
Console.Out.WriteLine(“Enter ‘yes’ to continue, anything else to end,”)
Console.Out.WriteLine(“then press <Enter>”)
sContinue = Console.In.ReadLine()
sContinue = sContinue.ToLower()
sContinue = sContinue.Trim()
Loop Until Not sContinue.Equals(“yes”)
End Sub
This example is the exact equivalent of the first Do loop example, and will
execute with identical results. The difference is that the conditional expres-
sion is placed at the bottom, after the Loop keyword. The implication of this
placement is that the loop will be executed at least once before the expres-
sion will be evaluated. In the first form it is possible that the loop will be
executed 0 times because the expression will be evaluated before the loop is
executed for the first time. If the expression returns false, the loop body
will not be executed at all.
You can formally describe the two types of Do loop statements as shown
here:
Do {While | Until} <conditional-expression>
<statements>
Loop
And:
Do
<statements>
Loop {While | Until} <conditional-expression>
The vertical bar between the keywords While and Until, delimited by
braces {}, denotes that only one of the two keywords must be present. You
will use this notation technique for other statements too.
158 Chapter 9: Control Statements
Now that you know what both For and Do loops are you can easily show
that a For loop can always be re-written as a Do loop. For example, the For
loop here (from one of our previous examples):
Dim i As Integer, t As Integer
For i = 1 To 31 Step 2
t += i
Next
Console.Out.WriteLine(“The final value of t is {0}”, t)
The two loops are doing exactly the same thing, but in slightly different
ways. In the Do loop you need to initialize and increment the counter vari-
able, and the While condition becomes that the counter is less than or equal
to the end value of the For loop. The moral is that if you rely on a counter
and have a range of values the counter navigates, use a For loop; for all
your other needs use a Do loop.
As you can see it is virtually identical to the Do loop, except for the lack of
the Do keyword and the use of End While as loop terminator.
Reviewing It 159
What’s Next
In this chapter you have learned the fundamental control statements in
Visual Basic. These statements allow you to control the execution flow or
your program, and make decisions on what parts of the program are exe-
cuted in what conditions and/or how many times. You have seen that the
control statements can be classified further in branching statements (like
the If and Select Case statements) and loop statements (like For, Do and
While).
In the next chapter you will learn how to structure your program into
smaller pieces, known as subroutines, procedures, and functions. You will
also learn why this is important and see a few examples of writing and
using procedures and functions and passing parameters.
NOTE
The answers to Reviewing It, Checking It, and Applying It are available on our Web site.
Reviewing It
This section presents a review of the key concepts in this chapter. These
REVIEW
questions are intended to gauge your absorption of the relevant material.
1. What are the differences and similarities between branching and loop
statements?
2. What is the syntax of the If statement?
3. What is a For loop?
4. What is a Do loop?
5. What are the differences between the For and Do loops?
160 Chapter 9: Control Statements
Checking It
Select the correct answer to the following questions.
CHECK
Multiple Choice
1. The type of the expression of an If statement is:
a. Numeric.
b. Logical.
c. True or False.
d. Depends upon the programmer.
2. Given an If statement without an Else part, what happens if the If
expression is False?
a. The statements inside the If are not executed.
b. The statements inside the If are executed.
c. An exception is thrown and the program ends.
d. Both b and c.
3. The type of the expression of a Select statement must be:
a. Numeric.
b. String.
c. Anything.
d. Numeric or String.
4. When does a For loop end (according to what you’ve learned so far)?
a. After a number of iterations equal to the difference between the
upper bound and the lower bound.
b. When the counter value is ≥ the upper bound (for incrementing
loops) or is ≤ lower bound (for decrementing loops).
c. When an Exit For statement is encountered.
d. When the Next statement is encountered.
Checking It 161
5. Can you modify the value of the counter variable inside a For loop?
For example, assuming i is the counter variable can you execute the
statement i += 1 inside the loop?
a. Yes.
b. No.
c. Yes, but it will affect the loop (number of iterations).
d. Yes, but it has no effect on the loop (it will be reset when Next is
encountered).
6. A Do loop will be executed at least once if:
a. The Do While ... Loop format is used.
b. The Do Until ... Loop format is used.
c. The Do ... Loop While format is used.
d. The Do ... Loop Until format is used.
7. The loop counter in a Do loop is incremented:
a. Automatically.
b. Manually.
c. In the Do expression.
d. There is no loop counter in a Do loop.
8. How many times would the following loop be executed?
For i = 10 To 0 Step –3
a. 3.
b. 4.
c. 9.
d. 10.
True or False
1. An If statement can have exactly one of each: If, ElseIf, and Else
parts.
True/False
2. Else is for If as Case Else is for Select Case.
True/False
162 Chapter 9: Control Statements
Applying It
Try to complete the following exercises by yourself.
A P P LY
Independent Exercise 1
Write a program to calculate the factorial of all numbers supplied by the
user. (The factorial of an integer n is the product of all numbers between 1
and n: 1*2*3*…*n). The program should work as follows:
1. Ask the user to enter a number n between 1 and 20, or 0 to exit the
program.
2. Validate n, if 0 exit program, if invalid display error message and go
back to step 1.
3. Calculate the factorial of n.
4. Display n.
5. Go back to Step 1.
Note that factorials grow very fast, so limit the number to 20 or less to
avoid arithmetic overflow errors. You will need a Long or larger type to hold
the factorial value.
Independent Exercise 2
Create a program that counts the number of spaces in a string entered
by the user. Note: you can use a property of the String type called
Chars(index) to get the character in a string at a given position.
10
Subroutines and Functions
In this chapter you will learn about ways to structure your programs in a
better way. You will study Visual Basic subroutines and functions, which
are known generically as procedures. The chapter will be divided in the
following categories:
• Introduction to structured programming
• Subroutines
• Functions
• Scope and lifetime
All the programs you have written so far used the same pattern: you have a
module (Module1) created by default, and this module has a Sub Main, in
which your code resides. When the End Sub is reached, the program ends.
As you probably imagined, these were just simple examples to illustrate the
introductory concepts of the language. A real-world program would contain
much more code than the few lines in these examples. That code could not
fit in the Sub Main that you used so far, and even if it did, it would be hard
to read, understand, and modify. That was the reason that programmers
and language architects have introduced the concept of splitting programs
into smaller units called procedures. Each procedure works like a small
standalone program, accepting input and producing output. As you will see
in the rest of this chapter, this input and output can have different sources.
Each language has its own name or names for procedures. In Visual Basic
there are two types of procedures, called subroutines and functions. They
are almost identical except for the name and the fact that functions return
a value (like a mathematical function does, for example sin(x)), while sub-
routines do not return any value. We will explain shortly what this means
through the use of a few examples.
166 Chapter 10: Subroutines and Functions
In the last part of this chapter, you will learn a few things about passing
parameters to subroutines and functions, as well as rules regarding the
scope of subroutines and functions within modules, and scope and lifetime
of variables within subroutines and functions. You will also learn about con-
stants and variables declared at module-level.
End
End If
End Module
This is the example used to illustrate a For loop. The lines in bold in the
previous example are identical; they perform the same task (prevent the
console window from closing—wait for the user to press Enter). You have to
type the same identical code twice. And if you would like to change this
piece of code, you have to change it in every location that you typed it in
the first place. That is not only a waste of time, but it is also error-prone.
NOTE
It is actually one of the major causes of errors in any real system. The technique of
duplicating portions of code in different places in the program (with eventually slight
modifications) is known as the copy-paste technique. The most common error related to
the copy-paste technique is to modify the code in a few places and forget to change it
in other places.
There is a better way to deal with this issue: define a procedure that exe-
cutes the task that you need to repeat, and call this procedure from the
main program any time the task needs to be executed. Consider the follow-
ing improved example.
Module Module1
Sub Main()
Dim vals() As Integer = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
End
End If
Sub WaitForEnter()
Console.Out.WriteLine(“Press the <Enter> key to end the program”)
Console.In.ReadLine()
End Sub
End Module
In this example we have moved the repetitive code into a new procedure
(named WaitForEnter), and then in the main program we replaced the code
with a call to this procedure. Let’s do an in-depth analysis of this.
The first step was to create a new procedure named WaitForEnter. This pro-
cedure is known in Visual Basic as a subroutine, or a sub. Sometimes the
term procedure is used to mean a sub, although it is incorrect. A procedure
can also be a function.
A sub is nothing more than a small program in itself. You can give it any
name you choose (as long as you remember that it is a language identifier,
and stick to the rules for identifiers). It is quite common to give it a mean-
ingful name related to what it does, so that you can remember easily what
task the subroutine is solving. The subroutine is very similar to the Sub
Main, except for the different name. It uses the keyword Sub followed by its
name and a set of parentheses () to mark its start point, and the keywords
End Sub to mark its end.
The body of the subroutine is the code between the Sub declaration and the
End Sub. This code will be executed when this subroutine is called, in the
same manner as the code in the Sub Main: starting with the first statement
following the Sub declaration line, and continuing up to the end point,
which is the End Sub. You can write any code you want in the body of the
subroutine, following the same rules as you did for the Sub Main. In particu-
lar you can declare variables, use control statements, and so on.
Introduction to Structured Programming 169
The next step was to call or invoke the subroutine from the points in Sub
Main where the replaced code was. This is done by simply placing the name
of the subroutine, followed by parentheses, where the replaced code was.
This will tell the compiler that when it reaches this line of code, it should
invoke the subroutine. That is, the execution point will move to the first
executable statement inside the called subroutine, in this case the
Console.Out.WriteLine statement.
NOTE
An executable statement is a statement that does something at runtime. A comment is
not an executable statement.
The compiler will then execute the rest of the subroutine and output the
“Press the <Enter> key to end the program” string to the console, and
then wait for the user to press Enter. As soon as the code in the subroutine
has finished executing, the execution point will return to the next state-
ment in the main program, which follows the call to the subroutine. This
will be either the End statement or the End Sub statement, depending from
where the subroutine was called in the first place.
This subroutine is part of the module Module1, as the Sub Main is. To better
organize the procedures in a program, Visual Basic groups them in mod-
ules. A module is a collection of procedures as well as type declarations (as
you have seen for enumerations and structures) and some other things that
you will see later on. A Visual Basic project can have many modules, and
each module can contain many procedures.
The code in a procedure also can call other procedures, either the ones you
defined, or system-defined procedures. And indeed, if you look at the code
in your Sub WaitForEnter you will notice that you call two system defined
subroutines: Console.Out.WriteLine() and Console.In.ReadLine(). These
are special forms of procedures defined by the programmers from Microsoft
who built the .NET Framework. In effect, an executing (running) program
is a stack of procedures that call one another to resolve different tasks. The
first one in the stack is the one called the Sub Main, which can call other
procedures to do some work, and these others can in turn call others, and
so on.
This is in brief what structured programming is about. We will have much
more to say about it in the next sections of this chapter.
170 Chapter 10: Subroutines and Functions
Subroutines
As you have seen, a subroutine is a language construct that allows you to
split a large task into smaller pieces. In the previous example, you imple-
mented a subroutine that does the same thing every time it is called: out-
puts the same string to the console, and then waits until the user presses
Enter. This case is rarely useful. There are many cases when you would
like the subroutine to do the same operation, but on different data. In this
example, we would like to output a different string when the user has
entered an incorrect value and the program will terminate abnormally, and
a success message when the task of summing the array elements is success-
ful. This is achievable through the use of subroutines with arguments, as
illustrated in the next example.
Module Module1
Sub Main()
Dim vals() As Integer = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
End Module
Subroutines 171
NOTE
The terms argument and parameter are often interchangeably used in programming lit-
erature to mean the same thing, argument in some cases, parameter in others. We are
trying to keep it consistent in this book. In real life be prepared to make the distinction
based on the context.
Next you will look at subroutines with more than one argument and at how
parameters are passed to subroutines.
name of a subroutine. You can have more than one argument in the list of
arguments by simply separating the arguments with commas. This is very
similar to the syntax used in the Dim statement. For example, if you need to
define a subroutine that requires three arguments you would write some-
thing like
Sub MyProcedure(ByVal count As Integer, ByVal name As String, ByVal dob As Date)
…
End Sub
The three arguments defined would require the subroutine call to look
something like this:
MyProcedure(6, “Joe”, #02/02/2002#)
We have used the keyword ByVal (standing for By Value) so far to indicate
to the compiler a certain way of handling the values passed to the subrou-
tine. The alternative is known as ByRef (standing for By Reference). As the
name suggests in the first case, ByVal, the compiler will pass the value of
the variable. That is, it will make a copy of the variable, and pass the copy
to the subroutine. The subroutine may change the value, but when the sub-
routine exits the original value of the variable will be unchanged. Consider
the following example:
Module Module1
Sub Main()
Console.Out.WriteLine(“Enter a value for i and press <Enter>:”)
Dim i As Integer
i = CInt(Console.In.ReadLine())
End Module
You are declaring two integers i and j, which you initialize with the values
entered by the user. You also have defined the subroutine Add, which takes
two arguments, both by value. The subroutine will add the value of the first
argument to the second argument. You also have a set of “trace calls” (out-
put values of some expression to the console) to view the value of j at differ-
ent points in the program. If you execute the program, and enter the values
1 and 2 for i and j, respectively, the output of the program will look like
the one in Figure 10.1.
You will notice that the value of j is changed to 3 in the Add subroutine,
after the addition of i took place. However, when you return in Main, the
value of j is back to 2! The reason for this apparently strange behavior is
that the variable j in the Main and the argument j in Add are different
entities; they refer to two different values in memory (they are at different
memory locations). Changing one will not affect the other. The compiler
made a copy of the value of the variable j from Main and assigned the value
to the argument j when the Add subroutine was called. But, when the sub-
routine Add ended, the changed value of the argument j in Add was not
stored back into the variable j. Actually, as you will see shortly, the com-
piler never does this.
If you intended to have the Add subroutine behave such that the value of
the argument j reflects, upon return, the sum of itself and i, you need to
174 Chapter 10: Subroutines and Functions
rewrite your code using the ByRef keyword in front of j. Make this one
change and run the example again.
Module Module1
Sub Main()
Console.Out.WriteLine(“Enter a value for i and press <Enter>:”)
Dim i As Integer
i = CInt(Console.In.ReadLine())
End Module
Now the output of the program (shown in Figure 10.2) shows the variable j
with a value of 3, after the call to Add.
The reason is that the compiler now handles j differently. It will not make
a copy of variable j value and assign it to the argument j of the subroutine
Add. Rather it will have both the variable and the argument refer to the
same memory location (hence the ByRef keyword). Modifying the argument
j of the subroutine, you actually are changing also the value of the variable
j in the Main. It is very important to understand this behavior correctly
because it can have nasty side effects. This difference is similar to the dif-
ference you have seen for variable assignment by value and by reference.
Functions 175
We recommend that you use the ByVal method of passing values as much as
possible; use ByRef only when the subroutine does actually modify the
value.
NOTE
We have used in the previous example the same identifier (j) for both the variable in
Main and the argument in the Add subroutine. This was done for the purpose of illus-
trating ByRef versus ByVal behavior. Normally we recommend that you use more mean-
ingful names for arguments.
Functions
You have seen examples of Visual Basic built-in functions when you learned
about conversion between different data types. We have used these func-
tions in some of the examples you have seen since then. A function is a sub-
routine that returns a value. The syntax is slightly different but the
functionality is identical. The difference is that it returns a value. Let’s
modify your last example to transform the Add subroutine into a function.
Module Module1
Sub Main()
Console.Out.WriteLine(“Enter a value for i and press <Enter>:”)
Dim i As Integer
i = CInt(Console.In.ReadLine())
End Module
The first thing you have to do is change the keywords from Sub and End Sub
to Function and End Function. The argument list is identical in syntax as
the one used for subroutines. However, after the closing parenthesis of the
argument list you notice the type declaration As Integer. This is the data
type of the return value of the function, also known as the function return
type, or in short return type. The return is one of the regular data types,
and it is used by the compiler to ensure the function is used properly. For
example in an expression it will ensure that the proper conversions are exe-
cuted, or in an assignment that the variable is of the appropriate type.
The body of the function is similar to the body of a subroutine, with one
exception: it must return a value of the type indicated in the declaration
line (the first line). In our example this must be an Integer value. This is
achieved using the Return statement. The value of the expression following
the Return keyword is what the function will return. In your case, this is
going to be the result of adding i to j. The Return statement does not have
to be the last statement in a function, as you will see shortly.
The way a function is used is identical to the way the system or built-in
functions are used: in an expression, or as part of an assignment (the way
you used it). You assigned the return value of the function to the variable
sum and then you output this variable to the console, to ensure the result is
what you expected.
As a twist on this example let’s assume that you are required to make the
function return a positive value or 0, if the sum of i and j is negative. The
modified example is shown here.
Functions 177
Module Module1
Sub Main()
Console.Out.WriteLine(“Enter a value for i and press <Enter>:”)
Dim i As Integer
i = CInt(Console.In.ReadLine())
End Module
You have modified the body of the Add function to illustrate a few important
points. The first is that you can have variable declarations in a function
(and in subroutines). You are declaring the sum variable to be of type
Integer. This variable is not related in any way with the variable with the
same name in Main. This is a very important fact that you need to remem-
ber: variables declared in a function or subroutine are local to that function
or subroutine. You will learn more on this subject in the remainder of this
chapter.
178 Chapter 10: Subroutines and Functions
Next you test to see if the sum variable is negative, and if it is you use the
Return statement to exit the function and return 0. This is meant to illus-
trate that when a Return statement is encountered, the function body is
exited, and the value after the Return becomes the function return value.
Older versions of Visual Basic are using a different syntax for returning a
value from a function. Namely the return value is assigned to the pseudo-
variable that is the function name itself, as in the following example:
Function Add(ByVal i As Integer, ByVal j As Integer) As Integer
Dim sum As Integer
sum = i + j
We find this notation harder to read, and less intuitive, and therefore we do
not recommend it. Another reason not to use it is that there is a possibility
that Microsoft will render this syntax obsolete at some point in the future.
The Return statement can be used also in subroutines, to exit before reach-
ing the end of the subroutine. In this case there is no return value speci-
fied. An example follows:
Sub WriteMessage(ByVal messages() As String, ByVal index As Integer)
If index < 0 Or messages.Length() <= index Then Return
Console.Out.WriteLine(messages(index))
End Sub
This example shows a subroutine that will output a message from an array
of string messages, at a specified index. If the index value passed in is
invalid (that is, less than 0 or greater than or equal to the length of the
array), the code simply returns without doing anything. This is achieved by
calling Return in conjunction with a single-line If statement.
The example also illustrates how to declare an argument of an array type,
and how to use it (like any other array variable) inside the body of the sub-
routine.
Scope and Lifetime 179
If you had a line of code before the Dim statement that would refer to i,
it would be a syntax error. Visual Studio and the compiler are happy
to point this out to you. Most of the time an Unknown variable
<yourVariableNameHere> error would occur. Also the variable i cannot
be accessed by code that is outside the Sub Main where it is declared.
This is one more reason to keep the variable declarations close to the point
where they are used. In this way, they cannot be inadvertently modified,
therefore reducing the risk of errors.
You cannot have two variables with the same name declared in the same
scope. The reason is quite simple: the compiler would not know which one to
use.
A variable can be declared also within a smaller scope than the whole sub-
routine. For example if it is declared in a block statement like an If, For,
Do, or similar, the scope is limited to the block statement. For example, next
we show code declaring and using an Integer j inside a For loop.
Sub Main()
Dim i As Integer
For i = 0 To 9
180 Chapter 10: Subroutines and Functions
Dim j As Integer
j = j + i
Next
‘ j cannot be accessed here
End Sub
If the code outside the loop tries to access the variable, a syntax error is
fired, and the program will not compile.
The lifetime of a variable is the period of time between the moment it is
declared and initialized and the moment the variable is discarded. It is in
effect the period of time the variable has a memory location allocated to it.
For most local variables, the lifetime is the period between their declaration
and the end of the procedure. In this example, the variable i has a lifetime
that spans from the moment it is declared up to the end of the Main sub-
routine. The lifetime of i is the time while the Sub Main executes.
In the previous example, the scope of the variable j is the For loop in which
it is declared. However, the lifetime of j is (same as in the case of i) the
duration of the Main subroutine. You can test that this is the case if you
display the value of j at each iteration of the loop, you will find out that is
every time incremented by i. Which means that the value of j is preserved
between loop iterations; it is not reinitialized with 0.
If you would like j to be 0 every time a loop iteration is starting) you need
to write the code differently:
Sub Main()
Dim i As Integer
For i = 0 To 9
Dim j As Integer = 0
j = j + i
Next
‘ j cannot be accessed here
End Sub
A constant declared like this is visible to the whole project (and in some
cases to other projects as well, as you will see). The lifetime of module level
constants and variables is the whole duration of the program execution.
The names and types of variables and constants declared at module level
also appear in the class view of the module. In the Solution Explorer, open
the tab labeled Class View and expand the tree until you see the contents of
the module.
The Dim statement was replaced by the keyword Const and the qualifier
Public, which is also a reserved keyword. Const means the value of the
variable is constant and cannot be changed. Public means that the visibil-
ity of the constant is set to be the whole project. It is okay to have a few
widely used constants declared as public constants, although you should try
to limit this number. The qualifier Public allows you to define constants
and variables that are visible to code in the whole program, regardless of
what module or class the code is in.
NOTE
Although it is okay to have public constants, it is highly recommended that you do not
use public variables. There are many reasons for this; one of the most important is
that it makes it very hard to write modular code (because a public variable can be modi-
fied anywhere in the program).
182 Chapter 10: Subroutines and Functions
The qualifier Private allows you to define constants and variables that are
visible in any subroutine or function in this module. Private constants are
very useful, but there is little use for private variables in modules. They
can be easily replaced by other means, as you will see when you learn
about classes and objects. There are some cases in which you may want to
use one. The syntax of the declaration is the same as for the Dim statement,
with the exception that it is done outside any subroutine or function. A
module-level variable (as they are called) can be accessed and modified in
any subroutine and function in the module, and this can cause issues when
writing multi-threaded code. You will learn more about this issue when you
study classes and objects in Part III, “Working with Objects.”
What happens if you have a subroutine that declares a variable with the
same name as a module-level variable? For example, if you have code like
this:
Module Module1
Private Const PI As Double = 3.141592
Sub Main()
Console.Out.WriteLine(PI)
Dim PI As String = “Joe”
Console.Out.WriteLine(PI)
End Sub
End Module
What is the output of this program going to be? The first output statement
will see the constant Double variable PI, and will output its value
(3.141592). The second output statement is placed after the declaration of a
local variable with the same name, but of different type. Its output will be
the value of this local variable. This means that the local variable PI takes
precedence over (or shadows) the module-level constant PI. This example
illustrates variable shadowing, but not good coding practice. We strongly
discourage using the same name for module-level and local variables and
constants. In addition we suggest that you use meaningful names for
Scope and Lifetime 183
module-level variables. The rule of thumb is that the wider the scope of the
variable, the more descriptive the name should be. For a local variable used
as a loop counter for a two-line loop i is sufficient—you can see the whole
scope of the variable on one screen. For a module-level a meaningful name
in combined case (like outputBuffer, overdrawProtectionEnabled, and so
on) should be used. It is also common practice to start the names of module
(and class) variables with the prefix “m_”, which can avoid naming con-
flicts. We will expand on this issue in the chapters on classes and class
fields.
One more point: the Const keyword can be used to declare constant values
local to a subroutine or function. In this case the qualifiers Public and
Private cannot be used. For example:
Module Module1
Sub Main()
Const PI As Double = 3.141592
‘ only code in this sub can use PI
End Sub
End Module
Sub Main()
Dim o As Test
o.x = 4
TestS(o)
Console.Out.WriteLine(o.x)
End Module
Structures use by-value semantics; therefore the ByVal versus ByRef modi-
fier for the argument of the TestS subroutine makes a difference. The o.x
will remain 6 after the function returns because the parameter modifier is
ByRef. If the parameter modifier is ByVal then o.x would remain 4 after the
function returns.
In the case of the TestA subroutine the modifier ByVal makes no difference
whatsoever. Regardless of whether it is ByVal or ByRef, the array element is
always changed in the original array, as declared in Main. The reason for
this is that the arrays use by-reference semantics.
Optional Arguments
There are cases when a subroutine or function can be called in some
instances with a value and sometimes without that value. For example,
assume you would like to write a function to copy part of a given array of
integers into a new array and return this new array. The function will have
as arguments the original (source) array, the position in this array where to
start copying elements, and the end position. However, you would like to be
able to not specify the end position, and then it should default to the end of
the array. Here is the finished example:
Module Module1
Sub Main()
Dim a() As Integer = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
Scope and Lifetime 185
Return cpy
End Function
End Module
The first thing to notice is that we have split the function declaration on
multiple lines (using the underscore _) and arranged it nicely.
The next thing to notice is that we have a function that will return an
array; the syntax used is similar to the one used to declare arrays. No size
or dimensions are required for the array, and should not be used. (It is a
syntax error to use size or dimensions).
186 Chapter 10: Subroutines and Functions
The optional arguments can be useful if used within reason. It makes little
sense to have more than one, at most two optional arguments. If you do,
maybe you want to consider creating two or more specialized subroutines or
functions, since the usage is so varied. As a rule you are trying to avoid
using them—it makes code harder to read and understand, and it may
cause problems with maintenance.
What’s Next 187
Sub Main()
‘ code
End Sub
End Module
If you had a second module in this project, and a subroutine in that mod-
ule, you could call the PublicSub() but not the PrivateSub(). If the
PublicSub() would be declared without the keyword Public you still could
call it from the other module.
You will learn more about subroutine and function visibility when you learn
about classes and objects.
What’s Next
This chapter covered a lot of ground in the fundamental principles of struc-
tured programming. You will continue your study with exception handling
in Visual Basic .NET and learn how this affects your programming style.
You will also learn the fundamental concepts of debugging using the Visual
Studio .NET.
NOTE
The answers to “Reviewing It,” “Checking It,” and “Applying It” are available on our Web
site.
188 Chapter 10: Subroutines and Functions
Reviewing It
This section presents a review of the key concepts in this chapter. These
questions are intended to gauge your absorption of the relevant material.
REVIEW
1. Why do you need to structure your programs?
2. What are the differences between a subroutine and a function?
3. What is the signature of a subroutine or function?
4. What is the difference between an argument and a parameter?
5. What is the scope of a variable? What is the variable lifetime?
6. What is the meaning of visibility in programming?
7. Discuss the difference between by-value and by-reference passing of
arguments to subroutines and functions, by analogy with the by-value
and by-reference assignment.
Checking It
Select the correct answer to the following questions.
CHECK
Multiple Choice
1. Invoking a sub-program (subroutine or function) means:
a. Terminating the current program and starting the invoked sub-
program.
b. Telling the compiler to take that code and embed it into the cur-
rent subroutine.
c. Executing the sub-program in parallel with the current program.
d. Executing the sub-program invoked, and then, when this returns,
continuing with the current code.
2. The parameter values of a subroutine (or function) are used to:
a. Transmit required values into the subroutine.
b. Return values from the subroutine.
c. Both transmit and return values.
d. Neither; they are used by the compiler only to make sure the
right subroutine is called.
Checking It 189
True or False
Select one of the two possible answers and then verify on our Web site that
you picked the correct one.
1. A Dim statement like Dim i As Integer is an executable statement.
True/False
2. A Dim statement like Dim i As Integer = 0 is an executable state-
ment.
True/False
3. A subroutine or function can invoke itself.
True/False
4. A subroutine (function) can invoke another subroutine that in turn
can invoke itself.
True/False
5. The value of a constant can be changed in the subroutine where it is
declared.
True/False
6. A private subroutine in a module can be invoked by any subroutine in
the same module, but by no subroutine outside that module.
True/False
Applying It
Try to complete the following exercises by yourself.
A P P LY
Independent Exercise 1
Change exercise 1 from Chapter 9, “Control Statements,” to calculate the
factorial using a function that calls itself—a recursive function. Hint:
Define a function called Factorial with one argument n, and have it com-
pute the factorial of the argument by calling itself. You will need to specify
a condition to end the recursion.
Applying It 191
Independent Exercise 2
Create and test a function that “pads” a String s with spaces up to a speci-
fied length n. If the length of the string passed in exceeds n, trim it to be at
most n characters. The function should have an optional parameter that
indicates whether the padding (spaces added) should be done to the left or
to the right of the original string. You will need the method Substring(i,
n) of the String type (which returns a sub-string of n characters, starting at
position i) and the global function Space(n), which creates and returns a
string of n spaces.
11
Introduction to Debugging and
Exception Handling
In this chapter you will learn the basic concepts of debugging an applica-
tion and of handling exceptions. The chapter will be divided into the follow-
ing categories:
• Preparing to debug a program
• Stepping through code
• Structured exception handling
• Unstructured exception handling
NOTE
In a more general sense the word algorithm can be used to describe any series of
steps that accomplishes a task, such as the steps required to withdraw money from an
automatic banking machine (enter card, enter code, specify amount, get money and
receipt, get card back).
is very similar to what you did in your sample programs so far using the
Console.Out.WriteLine. This technique is, of course, much better than ana-
lyzing the final output of the program. It would allow you to narrow down
the statements that were causing a problem, which is the first step in
solving it.
Sub Main()
Dim a() As Integer = {1, 6, 6, 9}
Console.Out.WriteLine(s)
End Sub
End Module
In the following, assume that you are using the default key mappings as
they ship with Visual Studio .NET.
196 Chapter 11: Introduction to Debugging and Exception Handling
NOTE
If you changed the key mappings please make the adjustments in the following code
too; that is, if you changed the mapping for the “step-over” command from F10 to
another key, please make the mental adjustment when we mention F10 in the book.
The key mappings can be viewed and/or changed in a number of places (Tools,Options
dialog; debug menu and tool bar; profile settings on the start page; etc.)
You will debug this program and step through all the statements in the pro-
gram. To do this place a breakpoint on the first executable statement of the
program. Click on the margin of the code window, to the right of the first
Dim statement in Main. A red dot should be displayed, and the statement
now has a red background, as illustrated in Figure 11.1.
This will tell the debugger to suspend program execution (to break) when it
encounters this line. You can have as many breakpoints as required in your
code.
Stepping through Code 197
To activate the debugger you can use the Debug, then Start menu, or press
the shortcut key F5, or click on the run icon in the toolbar (see Figure 11.1).
Press F5, and the IDE will start the program, and it will stop at the break-
point you set, as shown in Figure 11.2. The line is now displayed on a yel-
low background, which indicates that this is the current statement (the
statement that is going to be executed next).
The current statement background color will depend upon your system
settings. It shows as light gray in Figure 11.2.
Press F10 to execute this line. The current statement now becomes the
next executable line, as shown in Figure 11.3.
Please note in Figure 11.3 how the IDE layout is now changed. In the two
lower windows you can see the local variables and the call stack.
198 Chapter 11: Introduction to Debugging and Exception Handling
The window labeled locals is used to display the names, values, and types
for the local variables. In the previous example you see the array a and
string s. In the value column the array length is indicated, while for s an
empty string (“ ”) shows. Finally the Type column indicates what is the type
of each variable. It is Integer() (array) for a and String for s. If you press
F10 one more time you will notice that the value for s has changed to “The
array has “, and it is colored in red (which means it was changed by the
statement that you just executed).
The current statement consists of a call to the Count6es function, which
passes in the array a() and converts the returned integer value to a string,
and concatenates it to the current value of s. If you press F10 (which
stands for step over) all this would happen, but you will not be stepping
into the Count6es function. You need to step into the function, and for this
you use the F11 key. This will bring you into the function, as shown in
Figure 11.4.
Stepping through Code 199
If you press the wrong key at any time, you can let the program finish
(press F5) and then redo the steps again.
You can step over the first two Dim statements (use F10), and you will
notice that the Dim statement for i is skipped over. The reason is that a Dim
statement without initialization is not an executable statement. It is just a
declaration.
You can step into the loop, and you will see how the current statement is
moving four times through the loop, with the value of i (shown in the locals
window) changing at every iteration. In the same locals window you can see
all the local variables, and the function argument ints(). You can look at
the values of the individual array elements by clicking the + sign to the left
of the variable name. You will also notice a variable that you did not
declare: Count6es. This is actually the name of the function and functions
as a pseudo-variable, for the code that uses the older form of assigning to
the function name the return value, rather than using Return.
200 Chapter 11: Introduction to Debugging and Exception Handling
What is also interesting is that on the Call Stack window (bottom right)
you can see what is known as the call stack. This is the sequence of proce-
dures that are on the stack of execution at this point. Note that there are
multiple tabs in both bottom windows that offer different views in the
debugging process. Please select the Call Stack (if not already selected).
The IDE will remember the settings of your debugging session and will
restore them next time your debug a program. See Figure 11.5 for
reference.
The top-most line in the call stack window is the currently executing proce-
dure (or function). In your case it is the Count6es function, and it is shown
with the parameter values with which it was invoked. Next down is the
caller of this function, in your case the sub Main, and the position in main
from where it was called. The language in which these procedures are writ-
ten is also shown (in your case Basic). The last entry is a system entry
point, which calls out Main.
Stepping through Code 201
The call stack can be useful if you have an error in a function that is called
from many places in your program, and it fails only in some instances. You
would place a breakpoint in the function at the line that fails, and when it
fails you would look at the call stack to determine from where it is called
and what values were passed as parameters.
You also can set break points while the program is running. To toggle a
breakpoint on and off just click on the margin near the statement that you
would like to break on.
Other useful debugger commands are:
• Step out of a procedure/function (Shift+F11). This command will exe-
cute the rest of the code in the current procedure/function without
stopping and then it will stop as soon as it returns to the caller.
• Run to cursor (Ctrl+F10). This command allows you to execute all
statements between the current statement and the statement the cur-
sor (blinking caret, not mouse) is on. It is equivalent to setting a
breakpoint on the line the cursor is on and then executing the pro-
gram, and when it reaches the current line, toggling the breakpoint
off.
• Continue execution (F5). This allows the program to continue execut-
ing until the next breakpoint or the end of the program is encoun-
tered.
There are other commands available under the Debug menu, some of which
are useful. We will explain them as we use them in examples throughout
the book.
One other useful feature is the capability to view the values or variables
and expressions. You have seen how to do that in the Locals window. But
there are other ways to do it, too. When you return in the Main procedure
with the execution point, select Debug, Quick Watch. A dialog window like
the one in Figure 11.6 will be shown, and you can enter any valid expres-
sion that you would like to evaluate. Enter s.Length() and click on the
Recalculate button. The length of the string s will be displayed.
If you would like to monitor this expression as the code executes you can
add it to the Watch window, by clicking on the Add Watch button. This is
illustrated in Figure 11.7. You can have many expressions that you can
monitor at one time. You can add and remove expressions in the watch win-
dow. The same conventions as for the Locals window apply: if the statement
executed changes the value of the expression, the value is displayed in red.
202 Chapter 11: Introduction to Debugging and Exception Handling
In this example you can step through the program until you reach the End
Sub statement. At this point you can switch to the console window (using
Alt+Tab) and look at what the output is. Or, you can look at the value of the
string s to see what it is.
Structured Exception Handling (SEH) 203
NOTE
If you keep the mouse cursor still over any variable name in the currently executing pro-
cedure for a few seconds, the IDE will display the current value for that variable. That is
the same value as the one displayed in the locals, but sometimes it is more convenient
to do it this way.
This is a valid statement. If you try to execute this statement with a value
of zero for the y variable, the result will be undefined. In other words, you
have attempted to execute an invalid operation. The result of this action is
that your program will be interrupted, and an exception will be thrown. An
exception in this context is an object of a special data type; we will describe
it in more detail later. Thrown means that the compiler will check your
code to see whether it is prepared to deal with the exception. If it is not pre-
pared, it will display an error message, and your program will be termi-
nated. If you are running the program in the debugger, you will get the
option to debug your code, with the current statement being the one that
caused the exception.
NOTE
The term exception is used with two meanings in the text: one meaning the runtime
error that occurs, the other an object (variable) of a special type. These two are related:
The exception object is generated as a result of the runtime error and contains infor-
mation about the runtime error for which it was generated.
204 Chapter 11: Introduction to Debugging and Exception Handling
Try
result = i \ j
Catch e As DivideByZeroException
MsgBox(“We caught a divide by 0 exception”)
End Try
End Sub
End Module
The Try-Catch statement is delimited by the keywords Try and End Try.
The two keywords are strictly delimiters; they are non-executable state-
ments. Inside the statement you have two blocks. The first one (known as
the Try block) consists of the statement or statements that you believe may
cause exceptions to be thrown. The next block is known as the Catch block,
or the exception handler. The exception handler body is the code between
the line with the Catch keyword and the End Try. It is possible to have
more than one handler, as you will see shortly.
The way a Try-Catch statement works is as follows: if an exception occurs
while executing the code in the Try block, the program execution is inter-
rupted, and the control is passed to the appropriate Catch handler. In your
case this handler has just one line of code, which is displaying a message
using the MsgBox() function.
NOTE
The MsgBox() function is used to display a message dialog box and then waits for the
user to take some action. You will see more options of this function later in the book.
There may be multiple statements in the Try block, including loops, control
statements, and so on.
The Catch handler you used will not handle any type of exception,
just a specific type. The Catch keyword is followed by the code e As
DivideByZeroException. This type declaration indicates what type of
exception this Catch block handles. In this case it will handle only excep-
tions of type DivideByZeroException (which is a system-defined exception
Structured Exception Handling (SEH) 205
type). You will see that the only types that can be handled (caught) are a
special subset of types, derived from a system type named Exception. You
will learn more about the exception types when you learn of classes and
objects. For now, it is important to remember that not any type can be han-
dled as exceptions, for example String, Integer, and all other type you have
learned cannot be caught.
As mentioned previously, you can have multiple Catch blocks, each one
catching different exceptions. There is also a special form of the Catch
statement that will catch any exception. Let’s modify the code in your
example to look like this:
Module Module1
Sub Main()
Dim i As Integer = 5
Dim result As Integer
Try
result = Integer.MaxValue * i
Catch e As DivideByZeroException
MsgBox(“We caught a divide by 0 exception”)
Catch e As Exception
MsgBox(“We caught a generic exception”)
Console.Out.WriteLine(e.StackTrace)
Throw
End Try
End Sub
End Module
In your case you attempt to assign to an Integer the maximum value that
can be stored in an Integer (Integer.MaxValue) multiplied with i (5). The
result is not going to fit in an Integer, and an exception will be thrown. The
runtime will first check to see whether the first Catch block can handle the
exception (it can’t). Then it will move to the next Catch block, and this one
can handle all exceptions; therefore, it will be executed.
206 Chapter 11: Introduction to Debugging and Exception Handling
NOTE
Instead of using Catch e As Exception, you can use just Catch (without any type
declaration following). It has the same effect, with the difference being that you do not
have any information on what the exception was (since the variable e is not present).
We recommend the first form.
Because the catchall block catches all exceptions, it should always be the
last Catch in the Try-Catch statement (if is used).
Inside an exception handler (Catch block) you may have multiple state-
ments that deal with the exception. For example, you may set the value of
the result variable to 0. In your last example you also printed the call
stack to the console. The call stack in this case indicates where in code the
exception occurred, and it can be useful for debugging. All exceptions have
this property (as well as other useful properties that you will learn later in
this book).
A special statement that can occur only in a Catch block is called a Throw
statement. The Throw statement without any arguments is used to re-throw
the same exception, so that another handler deals with it. A usage scenario
would be if the Catch block is used to log a debugging message, but it does
not deal with the exception. The exception is then re-thrown for some other
handler to deal with. In your case there is no other handler; therefore, the
program is terminated.
In the next example you look at how exceptions are propagated on the call
stack. That is, if an exception occurs in a function that you call from
another function, how is the exception handled?
Module Module1
Sub Main()
Dim result As Integer
Try
result = MultiplyInts(Integer.MaxValue, 5)
Catch e As DivideByZeroException
MsgBox(“We caught a divide by 0 exception”)
Catch e As Exception
MsgBox(“We caught a generic exception”)
System.Console.Out.WriteLine(e.StackTrace)
End Try
End Sub
Return result
End Function
End Module
Module Module1
Sub Main()
Dim i, j As Integer
Main_Failed:
If err.Number = 11 Then
j = 1
Resume
ElseIf err.Number = 10 Then
Resume Next
Else
MsgBox(Err.Description)
End If
End Sub
End Module
The main components of an error handler are shown in the previous code.
The On Error GoTo statement tells the runtime that for any error that
occurs between itself and the end of the current procedure, it should trans-
fer control to the label mentioned after the keyword GoTo. In this case this
label is Main_Failed. A label is similar to a line number, it is a way to iden-
tify a place in a subprogram where other statements may jump to. In this
case it identifies the sequence of statements that will be executed if an
error occurs.
The code that deals with the errors is looking at the Number property of the
Err object and based on what the error was, it will take appropriate action.
The possible actions are to try again the statement that failed, ignore the
statement that failed, and continue with the next statement after it, or do
something else. We illustrate each one of these cases in your example. If
the error number is 11 (which corresponds to the DivideByZeroException),
you will change the value of j to 1 and re-execute the same statement. If
the error number is 10, you will ignore the offending statement and con-
tinue with the statement that follows after it. And, finally if it is something
else, you will display the error description and exit the program.
There are two more statements (variations of the On Error GoTo) that are
used in error handling. The first is On Error Resume Next, and it tells the
runtime to ignore any error it encounters and continue with the next state-
ment. This can be a very dangerous statement because it will ignore all
errors and exceptions, including serious system-level exceptions, and can
lead to program crashes that are very difficult to debug.
Reviewing It 209
What’s Next
In this chapter you learned how to debug a program, how to step through
code, and how to look at the values of variables and expressions as the pro-
gram is executed line-by-line.
You also have learned the basis of what exceptions are and how to deal
with them in a structured fashion. You also have seen the older version of
unstructured exception handling.
In the next chapters you will learn how a Visual Basic project is organized
hierarchically. You will learn about assemblies, namespaces, and modules.
You will also look at the most commonly used assemblies and namespaces
in the .NET Framework, and their contents.
NOTE
The answers to the “Reviewing It,” “Checking It,” and “Applying It” are available on our
Web site.
Reviewing It
This section presents a review of the key concepts in this chapter. These
REVIEW
questions are intended to gauge your absorption of the relevant material.
1. What is a bug, and why do you need a debugger?
2. What is a breakpoint?
3. What is meant by exception?
4. What is structured exception handling?
5. What is an exception handler?
210 Chapter 11: Introduction to Debugging and Exception Handling
Checking It
Select the correct answer to the following questions.
CHECK
Multiple Choice
1. To step through code means:
a. To execute the program line by line.
b. To execute the program statement by statement.
c. To browse the code looking for problems.
d. All the above.
2. In the locals window you can see:
a. Names of the local variables.
b. Names and values of the local variables.
c. Names, values, and data types of the local variables.
d. Names, values, data types, and status (modified or not) of the
local variables.
3. The call stack is:
a. The stack of all variables in the procedure.
b. The stack of all variables used in the procedure.
c. The sequence of procedures and functions that were called to get
to this point into the execution.
d. Both a and b.
4. Exceptions are:
a. Runtime errors.
b. Objects of a special data type used in SEH.
c. Both a and b.
d. Allowed deviations from a syntactic rule of the language.
5. If an exception is thrown and not caught, the result is:
a. The IDE will stop the program and point you to where the excep-
tion happened.
b. The program will be terminated and execution halted (if outside
IDE).
Checking It 211
True or False
Select one of the two possible answers and then verify on our Web site that
you picked the correct one.
1. Proper analysis and design normally can eliminate a large number of
bugs.
True/False
2. A trace statement is used to output the value(s) of variables to help
debugging.
True/False
3. The step-over command of the debugger is used to skip one statement
and execute the next one.
True/False
4. If the try block of a Try statement finishes without exceptions, the
Catch blocks are executed in order.
True/False
5. There is a Catch handler version that can catch any exceptions.
True/False
212 Chapter 11: Introduction to Debugging and Exception Handling
Applying It
Try to complete the following exercises by yourself.
A P P LY
Independent Exercise 1
Debug all the examples listed in this chapter, using step-through and look-
ing at all variables and the call stack.
Independent Exercise 2
Create a program that gets two integer values (i and j) from the user and
then executes the following operation “result = 256 * i \ j”. Make sure
that regardless of the values the user enters no exception is unhandled and
DivideByZeroException and OverflowException are handled specifically.
12
Microsoft .NET Framework—
Assemblies and Namespaces
This chapter is dedicated to the structure of a Visual Basic application. You
will learn of assemblies and namespaces. The chapter will be divided in the
following categories:
• Software development life cycle
• Assemblies
• Namespaces
• Useful namespaces
These steps are presented as logical steps, rather than physical ones. Each
step can be very extensive and detailed, even split in many sub-steps and
iterations, or it can be as simple as a sketch on a piece of paper, all depend-
ing on the software project type, size, and numerous other factors. We will
Assemblies 217
Assemblies
Now that you have seen the overall picture of software development, you
can better understand the structure of a Visual Studio .NET application. In
all .NET languages the application is represented by an assembly. An
assembly is a collection of all software of which the application consists. It
is called the unit of deployment for a .NET application. That means that
you need an assembly to install an application. This assembly is normally
an executable file (.exe) or a dynamic link library file (.dll). Each assembly
contains an assembly manifest, which is similar to a table of contents for
the assembly. It contains information about the assembly (name, version,
and so on), a list of files that are in this assembly, and a list of external ref-
erences. This assembly manifest is automatically created for you when you
build the assembly, based on the code you developed. Let us look at a very
simple example. You create a new console project called AssemblyExample
and have a Sub Main that outputs one line of text to the console. The
example is shown in Figure 12.1.
In the Solution Explorer window pane, on the right, you can see the assem-
bly structure. You have one project named AssemblyExample, and it has
some references and one file, Module1.vb. The project is the assembly, in
this case.
The references indicate what other assemblies you use. All projects in
Visual Studio .NET must have a reference to the System assembly.
Depending on the project type, some other assemblies may be required. If
you click on one of the references (for example, System) it will update the
properties pane (below the Solution Explorer) to show the properties of this
assembly. You should see something similar to Figure 12.2.
There are a number of properties that are used to identify the assembly
(such as name, identity, version, build, and revision numbers) and some
miscellaneous others (the actual filename of the assembly, its type, and
whether it uses a strong name or not.) A strong name is used as a security
mechanism to ensure that an assembly cannot be modified by anybody
except its developer and uses encryption to enforce that. This is an
advanced topic that will not be covered in this book.
Because your project is an assembly too, you can set some of its properties.
If you right-click on the project name and select Properties from the pop-up
menu, you will see a dialog box similar to the one in Figure 12.3.
Assemblies 219
On the left of the dialog there is a list of property categories, grouped under
two folders (Common and Configuration properties) from which you can
select. The Common categories refer to all configurations of this assembly,
while the Configuration properties are particular for one configuration.
That is why when selecting a category under the Common folder, the
configuration and platform drop-down lists at the top are grayed out
(not available).
A configuration is a way to build an assembly. The most common use for
configurations is to build debug and release configurations. The debug con-
figuration is used by the developer during the development and testing
phases of development. It contains information and statements that allow
the developer to quickly and easily identify bugs. This is achieved at the
price of a performance decrease, which is sometimes quite severe. That is
why, when the testing is finished and the final version of the product is
built, a release configuration is built, which has all the debug information
and statements stripped out, but has a better performance. You can manage
the configurations for any project using the Configuration Manager button
on the top right of the dialog. We will return to the Configuration Manager
later in the book.
The currently selected category is indicated by the small arrow to its left.
The properties that you are now interested in are the general and build cat-
egories, shown in Figures 12.3 and 12.4, respectively.
In the General category you can modify the assembly name, its type (that
is, the project type—we selected console), the startup object, and the root
namespace. We will return to the root namespace later. The startup object
is the module that contains the Sub Main that you want executed when the
application is run. As you will see shortly, you can change this setting.
220 Chapter 12: Microsoft .NET Framework—Assemblies and Namespaces
The Build category is used to select an icon for the application and to set
some basic options for the compiler. Your project is a console application;
therefore, you have no icons. The three options determine how the compiler
behaves in certain cases. You encountered the Option Strict when you
learned about data conversion (this option enforces type checking). The
Option Explicit is used to enforce variable declarations. We strongly sug-
gest that you leave both of them on. The third option is used for character
and string comparison. If set to binary, the characters are compared based
on the value of their code (UNICODE). Otherwise, if set to text, a language-
specific set of rules is applied, which correctly deals with accented and spe-
cial characters in each language. If the latter option is selected, it will slow
down somewhat character and string comparison.
The rest of the categories under the Common categories folder are more
advanced topics. We will come back to some of them later in the book.
In the configuration-specific folder, you have three categories—debugging,
optimizations, and build—shown in Figures 12.5, 12.6, and 12.7. Depending
on what configuration and platform you select, you will have different val-
ues for the settings in each category. The drop-down lists also indicate the
active configuration. The active configuration is the configuration that is
currently built when you build the project (by selecting the Build menu,
toolbar button, or the shortcut key F7). You also can see the properties in a
category that are common to all configurations by selecting the All
Configurations item in the drop-down list.
Assemblies 221
In the debugging category you can select some options for building the
debugging information into the assembly. These properties normally do not
apply to the release configuration. The Start Action property tells the com-
piler what to do when a debugging session starts, and default is to run the
project. You will see later on in the book what command-line arguments
and the working directory are used for. The last three properties are used
with ASP (Active Server Pages) projects or with non-Visual Basic projects.
The properties in the optimizations category are used to tell the compiler
whether to use some advanced optimization techniques. These are beyond
the scope of this book for beginners.
222 Chapter 12: Microsoft .NET Framework—Assemblies and Namespaces
In the Build category you have a few properties that you will use to cus-
tomize the debug and release configurations. The output path is the place
where the build assembly will be stored for each configuration. By default,
both configurations end up in the bin subfolder of the project folder. That
means that building the debug and then the release configurations will
result in the latter overwriting the former. If you want to keep both, you
will need to change this property. The checkbox labeled Generate
Debugging Information will, if checked, instruct the compiler to include all
the necessary information when building the assembly so that the debugger
can use it in the debugging process. This checkbox is normally checked for
the debug configuration and is not checked for the release configuration.
The Warnings checkboxes instruct the IDE what to do if a warning shows
up while building the assembly. These should be normally left at their
default values.
In the conditional compilation section, you instruct the compiler whether to
define two constants (DEBUG and TRACE), and any other compilation con-
stants that you need, per configuration. These constants are different from
the normal program constants declared with the Const keyword and should
be thought of as some special form of pre-processing instructions for the
compiler. You will learn later on in the book how these constants are used
and what they are used for.
Namespaces
A software project consists normally of a number of pieces of code (declara-
tions, procedures and functions, classes, and so on), known generically as
Namespaces 223
Sub Main()
‘ test the two methods
Println(“A test”)
NSEx2.Println(“A test”)
End Sub
Console.Out.WriteLine(message)
End Sub
End Module
End Namespace
Namespace NSEx2
‘ Write the message to the console, adding the current date and time
Public Sub Println(ByVal message As String)
Dim dt As Date = Now
Console.Out.WriteLine(CStr(dt) + “ : “ + message)
End Sub
End Module
End Namespace
3. Before running the example you need to make one more change, then
we will examine what you did in detail. Open the properties for the
project (right-click on the project name in the Solution Explorer win-
dow and select Properties). Select the General category under the com-
mon properties folder. Change the Root namespace property from
NamespaceExample to NamespaceExampleLib. Now, from the Startup
drop-down list select the first entry (which should read
NamespaceExampleLib.NSEx1.ModMain). Figure 12.9 illustrates the
dialog with the changes made.
Each assembly consists of a root namespace that contains all the compo-
nents in the assembly. By default this namespace has the same name as
the assembly and the project. You may change this to an empty string,
effectively removing the root namespace, but this is not recommended. The
root namespace may contain other namespaces (and these in turn may con-
tain other namespaces, as required). No declaration is required for the root
namespace; just change the property in the dialog as shown. In this exam-
ple the root namespace contains two other namespaces. You need to declare
these two namespaces using the Namespace keyword followed by the name
of the namespace (NSEx1 in this case). This name is a Visual Basic identifier
and must conform to the language-naming rules. Each namespace can con-
tain modules or, as you will see later, classes. The namespace ends with the
End Namespace keywords; everything between the Namespace and End
Namespace statements is part of that namespace.
In the ModMain module you have your Sub Main. This is the one you choose
in the Properties dialog when you selected the startup object. Each of the
two modules (ModMain and ModAux) has a procedure named Println, which
takes a string argument and outputs this string to the console. The second
version of the function prefixes the message with the current date and
time.
In the Sub Main you used the Println sub in the NSEx1 namespace as usual
(just call it by name), but you needed to prefix the call to the second version
of the Println sub by the name of its namespace (NSEx2). This is because,
within a namespace, all components declared in that namespace are avail-
able. You could access the first Println method by prefixing it with NSEx1,
but you do not need to; it is redundant. However, in order to access a com-
ponent declared in another namespace, you need to prefix it with the name
of its namespace.
NOTE
If namespaces are nested (a namespace that contains another namespace, and so
on) you need to fully qualify the component, that is, use notation like Namespace1.
Namespace2.Component.
Another very important aspect of namespaces is the fact that they allow
only certain components to be exported and used by external code. This is
achieved by declaring as Public only the components that need to be visible
from the outside of this namespace. Only Public components of a name-
space can be used outside the namespace itself. It is very good practice to
declare all utilities and components that need not be exposed to the outside
world as Private. This gives you the opportunity to change these private
components as you like (for example, to improve performance or fix bugs),
without worrying that you may break somebody else’s code. In effect it
shields the clients of your namespaces from the internal implementation of
the exposed functionality. This is a fundamental object-oriented (OO) con-
cept called encapsulation, and you will learn a lot more about it in the next
few chapters.
Next you will expand your example to use the two namespaces in a new
project. Follow these steps to reproduce the example.
1. Create a new project for this solution: right-click on the solution in the
solution explorer and select Add/New Project menu item. The regular
project dialog will open; select Console Project and rename the project
NamespaceExampleClient.
2. Now right-click on the References node under the new project and
select Add Reference. A dialog labeled Add Reference will be shown.
Namespaces 227
There are three tabs on this dialog. The first one shows references
from the .NET Framework; the second displays COM components; and
the third displays projects from this solution. This is the one you are
interested in. You can see NamespaceExample assembly listed as the
only entry. Select it by clicking on the Select button and then click OK
to add it to your project’s references. You will see it now listed under
the references for the NamespaceExampleClient project.
3. You can now use the Println procedures you defined in the last project
as if they were part of this project. Enter the code as shown:
Module Module1
Sub Main()
Dim s As String
Do
Console.Out.WriteLine(“Enter some text and press ENTER”)
Console.Out.WriteLine(“(leave empty and press ENTER to end)”)
s = Console.In.ReadLine()
NamespaceExampleLib.NSEx1.Println(s)
NamespaceExampleLib.NSEx2.Println(s)
Loop Until s.Length = 0
End Sub
End Module
4. You loop as long as the user inputs any text and output that text
using both versions of the Println procedures you have developed in
the other project. Before you can run it you need to set this project
as the startup project for this solution. Right-click on the
NamespaceExampleClient and select the menu item Set as Startup
Project. The startup project is displayed in bold in the Solution
Explorer. Now you can run the example, enter some text, and watch
in amazement how the Println procedures output it to the screen.
Press Enter without any text to end the program.
You probably have noticed in this example how you need to specify the full
name of the two procedures using the root namespace and then the name-
space and the procedure name. There is a better way to do this. You could
use the Imports statement. Modify the code to look like this:
Imports NamespaceExampleLib
Module Module1
228 Chapter 12: Microsoft .NET Framework—Assemblies and Namespaces
Sub Main()
Dim s As String
Do
Console.Out.WriteLine(“Enter some text and press ENTER”)
Console.Out.WriteLine(“(leave empty and press ENTER to end)”)
s = Console.In.ReadLine()
NSEx1.Println(s)
NSEx2.Println(s)
Loop Until s.Length = 0
End Sub
End Module
The Imports statement makes all public components in the specified name-
space public in the current namespace (by importing them). Hence, you do
not need to prefix the nested namespaces NSEx1 and NSEx2 with the root
namespace qualification.
If this is true then, you may ask, why not import the actual NSEx1 and
NSEx2 themselves? You could write code like such:
Imports NamespaceExampleLib.NSEx1
Imports NamespaceExampleLib.NSEx2
Module Module1
Sub Main()
Dim s As String
Do
Console.Out.WriteLine(“Enter some text and press ENTER”)
Console.Out.WriteLine(“(leave empty and press ENTER to end)”)
s = Console.In.ReadLine()
Println(s)
Println(s)
Loop Until s.Length = 0
End Sub
End Module
This code will not work; the compiler will rightly complain that both
Println procedure calls are ambiguous. If two namespaces contain conflict-
ing component declarations, the solution is to import just one of them
(namely the one that contains the conflicting components that you would
use most). You would use those without a qualified name and use the other
Useful Namespaces 229
Module Module1
Sub Main()
Dim s As String
Do
Console.Out.WriteLine(“Enter some text and press ENTER”)
Console.Out.WriteLine(“(leave empty and press ENTER to end)”)
s = Console.In.ReadLine()
NSEx1.Println(s)
Println(s)
Loop Until s.Length = 0
End Sub
End Module
Assuming that you use the second version of the Println procedure more
often, you import its namespace (NSEx2) and use it without a qualified
name. If you want to use the NSEx1 version of the Println you need to qual-
ify the call using the namespace.
You have probably observed that the IntelliSense drop-down prompts for
the namespaces that you created to be the same as the system namespaces.
Another important feature is that, when debugging, you can step from one
project into the other project’s code. Try to set a breakpoint on the first call
to Println and step into it; you can see the call stack showing the two
projects.
Useful Namespaces
The System namespace (within the assembly with the same name) is the
fundamental namespace that all Visual Studio .NET projects import by
default. It contains the fundamental data type definitions, as well as utility
classes and the fundamental class Exception and some of the commonly
used exceptions. It also contains other specialized namespaces, some of
which are discussed next. The most important ones for you in this book are
highlighted in bold.
230 Chapter 12: Microsoft .NET Framework—Assemblies and Namespaces
What’s Next
You have seen in this part what the fundamental Visual Basic .NET lan-
guage constructs are. You have also learned the basis of programming for
Visual Studio .NET in Visual Basic using structured programming con-
structs. You know the fundamental and complex data types, basic state-
ments, procedures and functions, and the structure of an application. You
also have basic knowledge of debugging a program and handling excep-
tions. If you are uncertain about any of these concepts, this is a good time
to review the concepts introduced in Part II and make sure that you have a
firm grasp on them.
Moving forward you will start to learn object-oriented concepts and imple-
mentations using the Visual Basic .NET environment. We will use what
you have learned so far and expand on some of the concepts. You will see
that there is no magic involved in OO, and developing code in OO fashion is
easier and more natural than what you have seen in Part II.
NOTE
The answers to the “Reviewing It,” “Checking It,” and “Applying It” are available in
Appendix A, “Answers,” at the end of the book.
Reviewing It
This section presents a review of the key concepts in this chapter. These
REVIEW
questions are intended to gauge your absorption of the relevant material.
1. Define and describe the software development life cycle.
2. What is an assembly? Enumerate its major properties.
3. What is a build configuration used for?
4. What is a namespace?
5. What does the Import statement do?
232 Chapter 12: Microsoft .NET Framework—Assemblies and Namespaces
Checking It
Select the correct answer to the following questions.
CHECK
Multiple Choice
1. The relationship between assembly, solution, and namespace is:
a. Assemblies have solutions, solutions have namespaces.
b. Namespaces have solutions, solutions have assemblies.
c. Solutions have assemblies, assemblies have namespaces.
d. Assemblies have namespaces, namespace has solutions.
2. The root namespace of an assembly is:
a. A formal name for the assembly.
b. The namespace that contains the assembly.
c. An advanced property used only in special circumstances that
you have not learned about.
d. The main namespace of that assembly, which contains all other
assembly components and namespaces.
3. Namespaces are useful when:
a. You would like to better structure a large project.
b. You would like to prevent name ambiguity with other projects.
c. You would like to hide implementation details for the project.
d. All of the above.
4. If a function F is declared as Private in a namespace N that resides in
module M, who can call the function?
a. Anyone.
b. Anyone in module M.
c. Anyone in namespace N.
d. Anyone in namespace N or who imports namespace N.
5. If a function F is declared as Public in a namespace N that resides in
module M, who can call the function?
a. Anyone.
b. Anyone in module M.
Checking It 233
c. Anyone in namespace N.
d. Anyone in this project or who imports namespace N.
6. If a function F is declared as Public in Module M, which is contained in
namespace N2, which is contained in namespace N1, how can you call
the function from another assembly? (Select all that apply.)
a. Import N1 and then access as N2.F.
b. Import N1 and then access F by name.
c. Import N2 and then access F by name.
d. Import N1.N2 and then access F by name.
True or False
Select one of the two possible answers and then verify on our Web site that
you picked the correct one.
1. The design phase comes before the development phase.
True/False
2. The only supported configurations for an assembly are debug and
release.
True/False
3. Generating debugging information when building an assembly slows
down the performance of your project at runtime.
True/False
4. A namespace must not contain other namespaces.
True/False
5. If two namespaces imported in a project contain a function with the
same name and signature, you cannot compile the project.
True/False
234 Chapter 12: Microsoft .NET Framework—Assemblies and Namespaces
Applying It
Try to complete the following exercise by yourself.
A P P LY
Independent Exercise
Modify the example you used for namespaces to export an enumeration and
a function that transforms a string to the enumerated value. For example,
use CardSuit enumeration containing the four suits (spades, hearts, dia-
monds, and clubs), and create a function that will accept a String parame-
ter (like heart) and return the enumerated value that corresponds.
Part III
You will start by looking at what objects and classes are, from a general
(non-programmer) perspective. You will then learn a few formal definitions
for the concepts of class and object, as applied to programming. You will
then continue with a few examples of simple classes. You will create the
class definition, and declare and use objects. The final section of this
chapter talks about constructors.
Note for the readers familiar with previous versions of Visual Basic: the
concepts and implementation related to the object-oriented part of Visual
Basic .NET are completely different from the ones in Visual Basic 6 and
earlier. We recommend reading carefully the chapters in Part III, “Working
with Objects,” and trying the examples so that the concepts presented get
crystallized.
238 Chapter 13: Objects and Classes
NOTE
The Greek philosopher Plato was the first to formulate this idea about 2,500 years ago,
when developing his concept of forms. He claimed that these forms (his name for
classes) physically exist in a parallel/abstract world.
The particular information that differentiates one horse from other horses
is used to build the mental image of a horse (or in the general case of any
object) in our minds. For example: the generic class horse has a color, which
is a characteristic of the class. That is, you know that any horse has a color.
You cannot predict what the color for a specific horse would be without
Defining a Class in Visual Basic .NET 239
more information about the horse. This information would be the actual
color of the horse, which is in effect the value of the color characteristic of
the class.
The same general/particular mechanism is used by OO programming lan-
guages to define classes and objects. A class is a user-defined data type that
describes a set of objects that share some characteristics. An object is a
member of this set. It is said that an object is an instance of the class to
which it belongs. An object cannot belong to more than one class; an object
cannot be a horse and a rock at the same time. You will see later when you
will learn about inheritance, that this statement must be understood in a
certain way.
NOTE
For example you can have a more general class called Mammal, that would include all
mammals, and therefore all horses. In mathematical terms it is a superset of the
Horse class. Therefore, in this sense a Horse is also a Mammal. The catch is that the
Mammal and Horse classes are related in a special way, while the Horse and Rock
class are not related (presumably).
NOTE
The prefix m_ is a notation convention used for class fields and stands for data member
(another name for field in C++ classes; C++ was one of the first object-oriented lan-
guages). We will use this convention throughout the book. It is helpful in that it allows
you to distinguish between fields and properties.
All instances of this class will have these three fields; each instance may
have different values for the fields. This is similar to the real life, where all
horses have a name, height, and color, but each horse has its own values for
these attributes. The idea behind the object-oriented paradigm is to try and
emulate real life in a natural, intuitive way.
You can now use the class you defined. You can declare variables of this
class type, which are known as object variables. These variables are refer-
ring to objects (or instances) of type Horse. You can use a variable declared
in this way to access the members of the class (fields, in the example). You
can set the values of these fields, and in general use the variables as you
would use any structure variable, with one important difference: Objects
have by-reference assignment semantics. That means that assigning a vari-
able of type Horse to another one will not make a copy of the object, but
rather have the latter refer to the same object as the first one.
Enter the following code in Sub Main, in Module1. The code illustrates an
example of using the Horse class.
Module Module1
Sub Main()
Dim h As Horse = New Horse()
h.m_name = “Bucefalus”
h.m_color = “black”
Defining a Class in Visual Basic .NET 241
h.m_height = 2
Dim g As Horse
g = h
g.m_height = 1.8
Console.Out.WriteLine(“Height of h is now {0}”, h.m_height)
End Sub
End Module
First you declare a new variable of type Horse and initialize it. You could
say in other words that you create a Horse instance, or create a Horse
object. This is done using the New keyword, which you have seen briefly
before. New is used to create a new object of the specified type. It is followed
by a class name and the parentheses. The New operator instructs the com-
piler to allocate the memory required for one object of the specified class.
V B 6 C O M PAT I B I L I T Y
The Set keyword used in previous versions of Visual Basic when dealing with objects is
not supported in Visual Basic .NET. The IDE will automatically remove it if you use it.
NOTE
You could write the declaration for the h variable as:
Dim h As New Horse()
This is the older form of a new object declaration, which is equivalent with the new
form used previously. This form may be familiar to programmers using older versions of
Visual basic.
The variable h is said to refer to the object. You use it to access the fields
of the Horse object; namely you set the values for these fields. You will
encounter often the use of the variable name as a substitute for the object.
For example you could say “you set the properties of the object h.” This is
just a shortcut for saying that you set the values for the object the variable
h refers to. Although the shortcut is quite commonly used, it is important to
understand the subtle difference between the variable and the object. The
variable has as a value a reference to the object; whereas the object is the
physical memory location where the data for this instance of the class is
maintained.
In the second part of our simple example you declare another variable (g) of
type Horse. You then assign to it the h variable. The effect of this assign-
ment is that g will refer to the same object as h. To illustrate this, our
example changes the value of the m_height field of g. You then output the
value of the m_height field of h, and you will see that it has changed. That
242 Chapter 13: Objects and Classes
means that the two variables h and g refer to the same object. This con-
firms the fact that the assignment (g = h) is done by reference and not by
value.
When a variable of an object type is declared but not initialized (as you did
when declaring g), it gets initialized to a special default value named
Nothing. Nothing is a keyword that indicates that the object variable does
not refer to any valid object. In our example g would have the value Nothing
before you assign h to it in the next statement. You can verify this by using
the debugger to step through the program and watch the value of g, just
before the assignment. If you attempt to use an object variable that is
Nothing to access the underlying object, it will cause an exception
(NullReferenceException) to be thrown stating that the object reference
is invalid.
NOTE
Those coming from other languages such as C, C++, or Java, will notice that Nothing is
very similar to the NULL value for a pointer, or the Java null value for a reference. All
mean the same thing: The variable does not point/refer to a valid object.
You can also explicitly set the value of an object variable to be Nothing
when you no longer need the variable. This is normally not required; the
compiler will do that for you when the variable goes out of scope (in your
example g will be set to Nothing at the end of Sub Main). However, we illus-
trate this technique in the next example because there are cases when you
may need to use it.
Module Module1
Sub Main()
Dim h As Horse = New Horse()
h.m_name = “Bucefalus”
h.m_color = “black”
h.m_height = 2
Dim g As Horse
g = h
g.m_height = 1.8
g = Nothing ‘ Any reference to g after this line will cause an exception
Console.Out.WriteLine(“Height of h is now {0}”, h.m_height)
End Sub
End Module
To check whether an object is valid (if it is not Nothing), you can use the Is
operator, as illustrated in the next example:
Dim h As Horse
‘ later on in the code
Class Fields 243
If h Is Nothing Then
‘ the object is nothing, take action
Else
‘ we have a valid object, use it
End If
NOTE
You can use the negation of the expression h Is Nothing as Not h Is Nothing. A
common mistake is to write it as h Is Not Nothing, which is syntactically incorrect.
In this section you have learned how to create and declare a simple class in
Visual Basic. You have also learned how to declare variables of object type,
initialize them, and use them to access the fields of the object.
Class Fields
The fields of a class constitute its data, what the compiler will allocate in
memory when an object of this class is instantiated. The fields are funda-
mental to the class: Defining the correct fields is crucial. This is normally
done as part of the design stage of the software development life cycle
(SDLC).
Class fields can have access modifiers similar to the ones you encountered
for the structure fields:
• Public means that the field is accessible by anyone in this project and
in other projects that use the class. Anyone can get the value of the
field and set it back (if it is not a constant field).
• Private means that the field is not visible to anyone but the object
itself. You will see in the next chapter why this is useful.
• Protected is a special modifier used in inheritance hierarchies.
You will learn more about it there; we just mention it here for
completeness.
• Friend is used to define fields that can be accessed by anyone in the
current assembly, but they will not be visible to those outside the
assembly. In effect it means public for the purpose of the current
assembly and private for the rest of the world.
If you would like the external users of the class Horse to be prevented to
access the m_height field, you can make it Friend. That will allow you to
continue accessing it from the code in this assembly (as you did previously),
but it will be invisible to the users who use the assembly and import the
class Horse.
244 Chapter 13: Objects and Classes
If you change the height to Private, no one (except the code in the class
Horse itself ) can access it. This will cause your previous example to fail to
compile.
We mentioned that the classes are normally defined in the design stage of
the SDLC. You will need to graphically represent classes and fields, make
diagrams with classes, and in general visually represent classes and their
members. You will present the fundamental notions required to understand
the notation you use—which is the almost universally accepted symbolic
notation known as the Unified Modeling Language or UML. You can find a
summary of UML at the end of the book in Appendix A, “UML Crash
Course.”
Classes are represented as rectangles with two or three compartments. The
class name is always in the upper compartment; the attributes of the class
are always in the second compartment. The third compartment is used for
methods; we will go into details about methods in Chapter 15, “Methods.”
Figure 13.1 illustrates an example of your class Horse.
Horse
+m_name: String
+m_color: String
m_height: Single
The Friend visibility is indicated by not using any of these notations. The
next example shows the attributeName attribute with Public visibility:
+attributeName : TypeName
The type of the fields in a class can be any valid type. They can be funda-
mental data types, as in the previous example. They can be structures, enu-
merations, or arrays. They can be objects of another class, or even of the
same class. The next example illustrates some of these types:
Public Class Foo
Private m_dob As Date ‘ date
Protected m_list() As Horse ‘ list of Horse objects
Friend m_suit As CardSuit = CardSuit.diamonds
Public m_aFoo As Foo
End Class
Every time a new object is created, all fields will be initialized to the
default values specified in the class definition. If no default value exists,
the value will be set to the default value for the type. That is 0 for numeric
values, empty string for strings, False for Boolean, Nothing for objects.
In your original example, when you will construct a Horse instance, the
m_name and m_color will be initialized to empty strings (“ ”), but the
m_height will be initialized to 1.5, which is the value you specified.
You can test this, using a modified version of the preceding example.
Module Module1
Sub Main()
246 Chapter 13: Objects and Classes
You create a new horse and, without doing anything else, you output the
value of its height to the console, which will show 1.5.
Class Constructors
In code, you can frequently encounter a case where an object must be cre-
ated and immediately after its properties must be set to a set of values. For
example, if you continue with the Horse class:
Module Module1
Sub Main()
Dim h As Horse = New Horse()
h.m_name = “Lightning”
h.m_color = “Brown”
h.m_height = 1.9
The example is pretty common: Create an object and set the values for its
fields. This task can become tedious, especially for classes with a large
number of fields. That is one of the reasons why class constructors (or con-
structors, in short) were introduced in the object-oriented languages. A con-
structor is a special Sub procedure, named New, which allows a new object to
be initialized in a certain way. The next example shows the class Horse with
a constructor.
Public Class Horse
Public m_name As String
Public m_color As String
Friend m_height As Single = 1.5 ‘ in meters
The constructor is a normal Sub procedure, except that it has a special key-
word name (New), and it must be declared as part of a class. Class proce-
dures and functions are usually known as class methods (or methods in
short). Therefore, a constructor is a special type of method. You can declare
it with any arguments you think are appropriate for the class. The con-
structor will be called when you construct a new object passing in parame-
ters that match its argument list, the way it is illustrated in the next
example:
Module Module1
Sub Main()
Dim h As Horse = New Horse(“Lightning”, “Brown”, 1.9)
Notice that the parentheses after the class name (Horse) following the key-
word New in the initialization of h now include the parameters that you wish
to pass to the constructor. This statement will call the constructor you
defined in the previous class. You could re-write the code in a different way,
but the end result will be identical:
Dim h As Horse
h = New Horse(“Lightning”, “Brown”, 1.9)
The only difference is that the variable h will be Nothing to start with, and
then a new object will be created and a reference to it will be assigned to h.
The constructor procedure will be executed in both cases, setting the values
for all the fields of the class. A constructor is a regular Sub procedure, and it
may contain any other statements that can be part of a procedure: branch-
ing statements, loop statements, and so on. For example, let’s assume that
you would like to make sure that the value for the height is within reason-
able limits for a horse (at least 1 meter and at most 2.5 meters high). You
can modify the class as shown here:
Public Class Horse
Public m_name As String
Public m_color As String
Friend m_height As Single = 1.5 ‘ in meters
m_color = color
If 1 <= height And height <= 2.5 Then
m_height = height
End If
End Sub
End Class
If the conditions are met (height between 1 and 2.5), the m_height field will
be set to the height parameter; otherwise it will keep the default value of
1.5, as specified in the field declaration.
The fields are initialized before the constructor is executed. In your case the
m_height will have a value of 1.5 before the constructor is executed. So if an
invalid height is passed to the constructor, the m_height will remain 1.5.
In UML you represent the methods of a class (known in UML as
operations) in the third compartment of the class rectangle as shown in
Figure 13.2. Because the constructors are just a special type of method, you
will place them there, too, as shown.
Horse
+m_name: String
+m_color: String
m_height: Single
+New()
What would happen with your example if you would like to construct a
Horse object sometimes with the three arguments shown previously, and
sometimes only with two of them? You have two options:
• You could use a constructor with optional arguments.
• You could have more than one constructor.
m_name = name
m_color = color
If 1 <= height And height <= 2.5 Then
m_height = height
End If
End Sub
End Class
In this case you declare the last two arguments as optional. You could call
the constructor now with any of the following:
Dim h As Horse = New Horse(“Lightning”)
Dim h As Horse = New Horse(“Lightning”, “Brown”)
Dim h As Horse = New Horse(“Lightning”, , 1.9)
Dim h As Horse = New Horse(“Lightning”, “Brown”, 1.9)
The second solution to your problem involves the use of overloaded meth-
ods. Overloaded methods are methods that have the same name but have a
different signature. You recall that the signature of a procedure or function
involves the number, type, and order of its arguments. When one of these
overloaded methods is called, the compiler will figure out which one of them
to call, based on the signature (number, order, and type of the parameters
passed).
NOTE
The overloaded methods should be semantically close related—that is, do similar
things. For example you could have two overloaded methods named Print, of which the
first one prints a document to the printer, and the second one calculates the probability
that tomorrow it will rain. This is legal, but nevertheless misleading at best. The lan-
guage does not enforce semantics (it can’t); it is you who must preserve this similarity,
or change the names of the methods to reflect the reality, if they are not similar!
Overloading is extensively used both in mathematics and in programming (computer sci-
ence in general). For example the operator + is overloaded to mean addition of inte-
gers, reals, and complex numbers as well as things that are not numbers at all
(vectors, matrices, and others).
If you have two constructors with the same name you must specify
Overloads for both of them, otherwise the program will not compile. We
illustrate with an example:
Public Class Horse
Public m_name As String
Public m_color As String
Friend m_height As Single = 1.5 ‘ in meters
m_name = name
m_color = color
If 1 <= height And height <= 2.5 Then
m_height = height
End If
End Sub
The second constructor takes only the name and color as arguments. You
can construct a new Horse object with any of the following two:
Dim h As Horse = New Horse(“Lightning”, “Brown”)
Dim h As Horse = New Horse(“Lightning”, “Brown”, 1.9)
Both solutions have their own advantages, and it is up to you to figure out
which one to use. As a general guideline, if a method has more than two
optional parameters, it is better probably to write a few overloaded versions
of the method.
NOTE
Special care should be taken when the two approaches are mixed: You can end up with
overloaded methods with optional parameters that could (if some parameters were
missing) be interpreted as another overload of the same method. This could be a major
source of debugging pain. Therefore, if any ambiguities are possible, the compiler will
refuse to build your project.
If you attempt to create a Horse object using the first form of the construc-
tor that you used (also known as the empty or default constructor), you will
discover that the compiler complains that there is no such constructor
defined.
Dim h As Horse = New Horse()
And it is right; there is no constructor (in either solution) that takes 0 para-
meters. So how come you could construct a Horse object in your first itera-
tion of the example without having a proper constructor? The explanation
is that Visual Basic .NET provides a public empty constructor for any class
that does not have any constructor. The moment you declare one or more
constructors, you lose this default constructor. You can either add it as an
overloaded method or make all arguments optional. In either case you can
now construct objects using the empty constructor. This is useful in particu-
lar when you declare and initialize arrays made of the instances of the
class.
Class Constructors 251
Constructors have access modifiers similar to the fields; they can be Public,
Private, Protected, or Friend. The same UML visibility notations apply to
methods (and constructors) as for attributes (+ for Public, # for Protected, -
for Private, and no symbol for Friend). The meaning is the same as for
the fields—public is visible for anyone and so on. A Private constructor, for
instance, may be called only by the other methods of the class. You can call
a constructor from another constructor by using the keyword MyClass. The
following example expands the class Horse to include a default constructor
and a private constructor that is called from the other two public ones.
Public Class Horse
Public m_name As String
Public m_color As String
Friend m_height As Single = 1.5 ‘ in meters
Notice how the two public constructors access the private constructor using
MyClass.New. The keyword MyClass represents this object (for those coming
from C++ or Java it is the equivalent of the this keyword). MyClass can be
used inside any class method to access any other method of the object. You
could use MyClass.m_height to access the field m_height, but it would be
redundant. MyClass is normally required only in some special cases, when
qualification is needed for the field or method. In the previous example, New
is a keyword, and it must be accessed in this way. The appropriate over-
loaded New method is called (based on the signature, as explained previ-
ously). You also would be required to use it if you did not use the m_ prefix
for the fields, and you would have an argument with the same name.
Consider the following example:
252 Chapter 13: Objects and Classes
You have both a class field named name and a method argument named
name. To distinguish between the two, you must use the MyClass keyword to
prefix the class field. This technique is a bit risky, especially if the method
is larger than a few lines of code, as one might inadvertently use one when
he meant to use the other. This can yield to subtle and hard to discover
bugs. That is one reason why we recommend using the m_ prefix for class
fields (data members).
As you can see in the examples presented in this chapter, you can access
the class fields from within the constructor. That is, you can set the value of
m_name, for example, from the constructor method. What this implies is that
the constructor method has knowledge of these fields, by the fact that it is
part of the class. As you will see in more detail in Chapter 15, this is one of
the major features of the object-oriented paradigm: to couple the data with
the methods that operate on it under one entity called a class.
What’s Next
You have learned in this chapter the basic elements of object-oriented pro-
gramming: how to access and use classes, objects, and class fields. You
learned about constructors and how to overload them. You also learned how
to represent a class with attributes.
In the next chapter you will learn about the class properties. You have seen
that classes have fields, but you will learn of a better way to express (get
and set) the properties of an object. You will learn the syntax and semantics
related to class properties using (as always) a number of examples.
NOTE
The answers to the “Reviewing It,” “Checking It,” and “Applying It,” are available on our
Web site.
Checking It 253
Reviewing It
This section presents a review of the key concepts in this chapter. These
REVIEW
questions are intended to gauge your absorption of the relevant material.
1. What is a class, and what is an object? Explain the difference.
2. What is a class field?
3. What is a constructor?
4. What is a method?
5. What does it mean to overload a constructor?
6. What is a default constructor?
Checking It
Select the correct answer to the following questions.
CHECK
Multiple Choice
1. The relationship between class and object is similar to the relationship
between:
a. Mammal and horse.
b. Mammal and rock.
c. Horse and Bucefalus.
d. Rock and Bucefalus.
2. If you have a friend class field, it can be accessed from:
a. Anyone in this assembly and outside it.
b. Anyone in this assembly.
c. Anyone in the same namespace.
d. Anyone in the same class.
3. When a new object is constructed using an empty constructor:
a. Fields get initialized before the constructor is executed.
b. Fields get initialized after the constructor is executed.
c. Fields do not get initialized; the constructor must do that.
d. Fields do get initialized only if the constructor fails.
254 Chapter 13: Objects and Classes
True or False
Select one of the two possible answers and then verify on our Web site that
you picked the correct one.
1. Classes are user-defined (custom) data types.
True/False
2. Objects and variables are the same thing.
True/False
3. A class can have fields of the same type as itself (a class A can have a
field m_a declared of type A).
True/False
4. The default value of an object variable is Nothing.
True/False
Applying It 255
Applying It
Try to complete the following exercises by yourself.
A P P LY
Independent Exercise 1
Draw the UML class diagram for the class Foo presented in code earlier in
this chapter.
Independent Exercise 2
Write a class that corresponds to the following UML diagram (see
Figure 13.3).
Person
+m_name: String
+m_dob: Date
+m_photo: Byte()
+New()
+New(name:String, dob:Date)
First you will look at what class properties are, why you need them, and a
comparison between properties and fields. Next you will look at details on
how to implement properties in a class declaration. You will also look at
property access modifiers and their relation to visibility of a property. You
will continue with a few examples of read-only, read-write, and write-only
properties. You will look at parameterized properties, or how to implement
properties to access data represented as arrays. You will conclude the chap-
ter with a short discussion and examples on how to combine efficiently the
properties and fields of a class, as well as a few guidelines and conventions
used commonly.
258 Chapter 14: Properties
In the constructor you are forcing the height to be a valid height for a horse
(between 1 and 2.5 meters). That will ensure that your horse is a valid
object. Well, actually, not quite so. The user can set the m_height field
(which is a Single variable) to any value within the Single domain. That is,
it can be negative, 0, and so on. For example:
Dim h As Horse = New Horse(“Bucefalus”, “black”, 2)
h.m_height = -250.34
If the user would set the height of the horse to a negative value, it would
make your horse an invalid object. It is also said about an invalid object
that it has an inconsistent state, meaning that there are mismatches or
incorrect values among the class fields (data members).
At this point you need to make a short digression to explain the distinction
between class attributes (which we mentioned briefly before when speaking
of UML) and class fields. Class attributes are the characteristics of a class
from a logical point of view. For example, you can say that name, color, and
height are attributes of class Horse. Fields are the physical way you imple-
ment these attributes in your code. In this case you have three public fields
that correspond to the three attributes: m_name implements the name
attribute, m_color implements the color attribute, and m_height implements
the height attribute. By implements here we understand that it is the phys-
ical representation of the logical attribute.
The Property Statement 259
The problem is that, if you use a public field (m_height) to represent the
height attribute of the class, the users of the class may inadvertently
change the value of height to an invalid value. There is no way to prevent
this, if you use fields to represent class attributes. You may limit access to
the field by making it Friend, and in this case only the code in the current
assembly can damage the class. But then no one outside the package can
find out what the height of the horse is! This is a severe limitation in func-
tionality. To overcome this type of problem, the notion of class properties
was introduced.
From a conceptual point of view, fields and properties are very similar:
They both are used to implement the value of an attribute of the class. The
way this feat is achieved is different. You have seen that fields are just
variables that hold data. Properties are a special form of procedure that
allows you to customize the way a value for a class attribute is get or set by
the users of the class. It normally uses a private or protected field to hold
the data. Next we will illustrate the implementation of properties in Visual
Basic .NET.
The first thing to observe is that the m_height field is now private; it can be
accessed from the members of the class, but it will be invisible to anyone
outside the class.
Then you have added the Property statement, which is somewhat similar
to that of a Function statement. It has a type, which indicates the prop-
erty type. In this case the type is Single. The Property statement is com-
posed of two parts (blocks of statements): a Get block and a Set block. At
least one of the two blocks must be present. You will see shortly when one
of them can be omitted.
V B 6 C O M PAT I B I L I T Y
Users of previous versions of Visual Basic are familiar with Property Get and Property
Set statements. These two statements have been combined into one Property state-
ment with two blocks Get and Set as explained next. The Property Get and Property Set
are no longer supported in Visual Basic .NET.
The Get block is the one that is executed when the user accesses the prop-
erty. This is also known as a read block. The block is delimited by the Get
and End Get statements. This block can contain any regular statements and
should end with returning the value of the property. The return value must
match the property type. In this case you return the value of the private
field m_height.
The Set block is used to set the value for the property. This would happen
when the user intends to change this value. It is expected that the value set
will be stored someplace (for example in a private field, like we do) and
when read later, will be returned. Like the Get block, the Set block is delim-
ited by the keywords Set and End Set. Inside the block you can have regu-
lar statements. Normally you have code that verifies that the value set by
the user is valid. It is important to understand that this value is of the
same type as the property type (Single) and it is represented by the key-
word Value. This keyword is not declared anywhere, and it must be
accessed only inside the Set block. In the example you verify that the Value
is within the correct range for a horse height, and if it is you modify the
private field to the new value.
NOTE
If the value is not correct you do nothing. That is not what you would do in a real-life
program; it is done so in the example to avoid complications. You would normally raise
an exception, telling the user that the property value the user set was incorrect.
Using Properties 261
Normally a property uses a field to store and retrieve the value of the prop-
erty. The field is usually declared as private or protected. The use of proper-
ties satisfies one of the fundamental OO principles known as encapsulation.
The encapsulation principle states that the way a specific attribute of a
class is implemented should not be exposed outside the class. That means
that the class fields should be declared as private, and properties should be
used to access them. The most important reason for doing so is illustrated
in the next paragraph.
If you implement an attribute as a public field of a type and later on decide
to change the field type to some other type to improve the class in a way,
this change would break the user code that has used that field. For exam-
ple, in a class Account you decide to implement the balance attribute using
a Double field m_balance. You develop the class and publish it so that others
(or even you) can use it to develop an application. After one year you dis-
cover that there can be rounding errors using a Double, and decide that you
must change the type of m_balance to Decimal. If you do this, you will need
to go through all the code that uses your class and change it so that it uses
Decimal variables when using the m_balance. That can be a lot of work and
can be also dangerous. The easy solution would have been to have Double
private field and a public Double property. If you need to change the field,
change it, but keep the property, and add a conversion routine to it so that
it converts from Decimal to Double.
The properties in Visual Basic .NET can have the access modifiers as func-
tions and procedures (Public, Protected, Friend, or Private). Usually prop-
erties are not declared as Private. Private properties would be accessible
only from the class, but that means you can use directly the field that
underlies the property.
The last thing to notice in the class is that you used the property also in
the constructor to ensure that the height is properly initialized. You needed
to use MyClass here because you have already an argument called height.
Also observe that you can access any member of a class from inside the
class itself by using the MyClass keyword.
Using Properties
Properties can be used exactly as the fields are used. For example, if you
use the class you defined previously, you could write code as shown:
Module Module1
Sub Main()
Dim h As Horse = New Horse(“Bucefalus”, “black”, 2)
h.height = 1.9
262 Chapter 14: Properties
You construct a new Horse object and then you set its height to 1.9, and you
output the value of the height property to the console. The second line in
Sub Main (h.height = 1.9) will call the property procedure and execute its
Set block. The Value implicit variable will be set to 1.9. That means it
would pass verification using the If statement and will set the m_height
field value to be 1.9.
Next you read the value (execute the get) of the height property (h.height)
and output it to the console. This will execute the property procedure again,
this time the Get block. This will simply return the value of the field
m_height, which you set previously to 1.9.
You can (and should) use the debugger to step through these few lines of
code; step into the property procedure to see how it works.
Properties are also useful if you have a property that is read-only or (sel-
dom) write-only. Often you would like to prevent users from directly chang-
ing a property. If you have a class Person that models a person with a name
and a date of birth, you may choose to initialize the person’s name and date
of birth upon creating a new object and disallow the users to change them
later. This can be achieved using a read-only property. This is a property
that the users can read (get) but not set:
Public Class Person
Private m_name As String
Private m_dob As Date
Both properties of this class are using the ReadOnly modifier to indicate
that there is only a Get block defined—that this property cannot be set
(assigned to). An example of usage is shown here:
Module Module1
Sub Main()
Dim p As Person = New person(“John G.”, #7/4/1960#)
Console.Out.WriteLine(“The name is {0} and dob is {1}”, p.name, p.dob)
End Sub
End Module
If the user would write code like p.name = “Ragnar D.”, it would not com-
pile (the IDE would flag it as a syntax error). This is a very useful mecha-
nism, employed in encapsulating (protecting) the data for the instances of a
class.
You can use a write-only property by using the WriteOnly modifier for the
property and implementing only a Set block. This will force the property to
only accept assignments to it, but disallow reading from it, the opposite of a
ReadOnly property. Write-only properties are used seldom and normally for
volatile data (for example in implementing output streams, like an out con-
sole). For example:
Public Class OutTextStream
Public WriteOnly Property outText() As String
Set
Console.Out.WriteLine(Value)
End Set
End Property
End Class
You create a class that allows you to output text to the console by setting a
property named outText. This time there is no field to store the data, so it
makes no sense to have a Get (what would you return?). This can be used
as shown:
Module Module1
Sub Main()
Dim o As OutTextStream = New OutTextStream()
o.outText = “This goes to the console!”
End Sub
End Module
rather the property value is calculated from other fields. For this reason
calculated properties are often read-only properties. For example if you
were to implement a property called age for your Person class, you would
not need another field for age. You have one for the date of birth, so you can
easily calculate the age of the person using the Date functions. We illustrate
the modified person class in the next example.
Public Class Person
Private m_name As String
Private m_dob As Date
You have added the read-only age property, which is going to return the age
of the person in years. In the implementation of the Get block, you use the
built-in object Now to get the current date and time, and then the year prop-
erty of the Date type to access the year of Now and of the m_dob variable. The
difference between the two is the age, and you return it. You can now use it
as illustrated:
Module Module1
Sub Main()
Dim p As Person = New person(“John G.”, #7/4/1960#)
Console.Out.WriteLine(“The name is {0} and dob is {1}”, p.name, p.dob)
Console.Out.WriteLine(“The age is {0}”, p.age)
End Sub
End Module
Because it is a read-only property, you cannot set it; you can only read it.
Parameterized Properties
You know you can have array fields in structures and classes. You also can
have attribute of type array, or more generally parameterized attributes.
How can you implement these attributes using properties? Let’s look at an
example. Assume that your Person class can have a number of accounts
with a financial institution. You plan to store the balances of these accounts
in the Person class. You can further assume (for simplification) that the
maximum number of accounts is five. You decide to implement this
Parameterized Properties 265
attribute using an array field of five Decimal values. If you were to use the
public array field, you could write the class as follows:
Public Class Person
Private m_name As String
Private m_dob As Date
Public m_balances() As Decimal
We have omitted the properties because they are not changed. We illustrate
how to set up an array field and how to allocate it in the constructor (the
bold code). To access it you could write code like the following example:
Module Module1
Sub Main()
Dim p As Person = New person(“John G.”, #7/4/1960#)
‘ we assume we get these values from some place
p.m_balances(0) = 2100
p.m_balances(1) = 10000
There is nothing new here: You access each element of the array field as
though it would be a normal array, except that it is a member of the object
p. Therefore, you prefix it with the object variable, similar to any regular
field access. However, this poses a problem. You break the encapsulation
principle by allowing users direct access to the implementation of the class!
You should use a property to expose the balances, not a public field. Let’s
modify the code to make the class obey the encapsulation principle. Make
the m_balances array private, create a new property called balances, and
use a parameterized property this time because it is an array that you wish
to expose to your users.
Public Class Person
Private m_name As String
Private m_dob As Date
Private m_balances() As Decimal
266 Chapter 14: Properties
The property statement is very similar to the ones you have seen previ-
ously, except that now the property procedure has an argument, the index
argument (some call it a parameter, hence the name parameterized proper-
ties). This argument is used to identify which item of the array you wish to
get or set, and as such can be accessed by both the Get and Set blocks. You
simply return the value of the requested balance in the Get block and set
its value to the implicit Value in the Set block. If the value of the index
argument is out of bounds (less than 0 or greater than 4) an out of bounds
exception will be thrown by the .NET Framework runtime.
Now you can access the new property the same way you would access a reg-
ular field, as illustrated by the next example.
Module Module1
Sub Main()
Dim p As Person = New person(“John G.”, #7/4/1960#)
‘ we assume we get these values from some place
p.balances(0) = 2100
p.balances(1) = 10000
However the programmers using your classes do not have access to the
underlying array field, and therefore, they cannot make mistakes like delet-
ing the whole array, or resizing it. In the previous version (with the public
m_balances field) a user could write code like
Parameterized Properties 267
Module Module1
Sub Main()
Dim p As Person = New person(“John G.”, #7/4/1960#)
This code would break the class code that relies on the fact that the size
of the array is 5! In the better version of the class (using the parameter-
ized property) the only actions they can perform are set and get the val-
ues of the elements in the array. You can make the property read-only if
you wish to restrict write access, the same way you did it for a regular
(non-parameterized) property.
It is a good idea to combine a parameterized property with another prop-
erty that can indicate to the users the valid bounds (indices) for the prop-
erty, such as a count calculated property. In our example this would simply
return the number of elements in the array. For example the noOfBalances
property shown here:
Public Class Person
Private m_name As String
Private m_dob As Date
Private m_balances() As Decimal
You can have properties that have multiple indices (for example to access a
multi-dimensional array). Also the types of the indices are not restricted to
Integer or numeric types. You can have a property indexed by a String,
such as a phone list indexed by the person name.
A somewhat advanced feature is that you can have overloaded parameter-
ized properties—properties with the same name but different parameters.
You can have another balances property that uses a String as an index (for
example to identify the balance by some sort of ID string). For example:
Public Class Person
Private m_name As String
Private m_dob As Date
268 Chapter 14: Properties
The use of the Overloads keyword is not required in this case. This is some-
what inconsistent with the methods, which require it. This fact proves that
all languages, even the best, have their own set of inconsistencies.
To use the new property you could write code such as
p.balances(“0”) = 2100
Note the use of the string “0” as a parameter to the property. This allows
for more powerful constructs than the arrays because you can define the
type of the indices. We will look into this more when you learn about collec-
tion classes.
In UML notation, the class attributes normally represent both the property
and the field. The attribute specification will indicate whether a combina-
tion of property and field, or just a field, or just a property, should be used
to implement the attribute. Each UML element (such as classes and attrib-
utes) has a specification attached to it that describes some of its properties.
For an attribute this specification includes how to implement it, what is its
access modifier (public, private), if it is parameterized, and so on.
As a general naming guideline, you use the attribute name as the property
name, starting with a lowercase letter and then using mixed case. For the
field you use the same name as the attribute, but with a prefix of m_ as
illustrated by all your examples.
It is a good idea to use a plural form for the name of a parameterized prop-
erty (such as “balances” not “balance,” or “items” not “item”). It is more sug-
gestive for the user, and because there is no indication in the drop-down
IntelliSense box that a property is or is not parameterized, it can help with
usability of your classes.
What’s Next
In this chapter you studied another member of a class: properties. You have
seen what they are and how to implement and use regular and parameter-
ized properties. You learned how to code read-only, write-only, and calcu-
lated properties. You also learned about the important OO principle of
encapsulation.
Next you will study the class methods. You will learn what methods are
and how to declare and use them. You will learn more about overloading
methods in general (not only class constructors). You will also learn about
method parameters and in general how to use methods to implement class
behavior.
NOTE
The answers to “Reviewing It,” “Checking It,” and “Applying It” are available on our Web
site.
Reviewing It
This section presents a review of the key concepts in this chapter. These
questions are intended to gauge your absorption of the relevant material.
REVIEW
1. What is a class attribute?
2. What is a property?
270 Chapter 14: Properties
Checking It
Select the correct answer to the following questions.
CHECK
Multiple Choice
1. Which of the following statements is true?
a. An attribute is implemented using a property.
b. An attribute is implemented using a field.
c. An attribute is implemented using a property and a field.
d. An attribute is implemented using a property, field, or both.
2. A friend property can be accessed from:
a. Anyone in the same assembly and outside it.
b. Anyone in the same assembly.
c. Anyone in the same namespace.
d. Anyone in the same class.
3. A read-only property has:
a. A Set block only.
b. A Get block only.
c. A Get block and sometimes a Set block.
d. Both a Get and a Set block.
4. A calculated property is normally used to:
a. Calculate the return value of a property.
b. Implement a read-only attribute through a property.
c. Implement an attribute that can be calculated based on other
attributes.
d. Implement a computing-intensive property.
Applying It 271
True or False
Select one of the two possible answers and then verify on our Web site that
you picked the correct one.
1. Attributes are the abstract representation of a class characteristic;
whereas properties and fields are concrete implementation of these
attributes.
True/False
2. Read-only properties can be parameterized properties at the same
time.
True/False
3. Read-write properties have optional Get and Set blocks.
True/False
4. The Value keyword can be used both in the Get and the Set properties.
True/False
5. The MyClass keyword can be used in a parameterized property.
True/False
6. The use of a field is optional when implementing a property.
True/False
Applying It
Try to complete the following exercises by yourself.
A P P LY
Independent Exercise 1
Implement the class illustrated in the following diagram, noting the specifi-
cations for each attribute.
272 Chapter 14: Properties
Person
+name: String
+dob: Date
+age: Integer
+balances: Decimal()
+New()
+New(name:String, dob:Date)
Independent Exercise 2
Implement the class illustrated in the following diagram, noting the
specifications for each attribute.
Account
+id: String
+balance: Decimal
+type: Integer
+New()
+New(id:String, iType:Integer)
We will start by formally defining the syntax of a method and give some
examples to illustrate different types of methods. Next you will look in
more detail at method overloading—what it is and how and when can you
use it. This will include some examples, hints, and good practices of method
overloading. We will conclude the chapter with a few examples that illus-
trate the concepts you learned and how to use them efficiently, as well as
how to represent methods in UML.
276 Chapter 15: Methods
End Set
End Property
You are using a slightly modified version of your Horse class. You have all
fields as private members now, and you also have public properties for all
the attributes. The name and color must be provided when constructing a
Horse object because the name and color properties are declared as read-
only. The height is optional and can be modified later.
The new function Jump is a method of the class that returns the height the
horse jumps. In this very simple example, this is always 75 percent of its
height. This value is calculated, converted to a Single, and returned.
NOTE
You have learned before that a constructor is also a method, albeit a special type of
method, used only to construct a new object.
Class methods have access modifiers, similar to the fields and properties.
These can be Public, Private, Protected, or Friend. The meanings of the
modifiers are the same as for the properties and fields. Public methods can
be called by anyone; private methods can be called only by other methods or
properties of the same class.
As you see from the previous example, methods have access to the other
class members. For example your Jump method uses the m_height field to
perform its task. Some methods may alter some of the object attributes,
either through the use of properties (such as in the constructor, where you
use the height property) or through the use of the class fields.
If you were to create two Horse objects, each with its own height, and then
call Jump on each, the return values would be different because in each case
the method will return 75 percent of the height of the object you are invok-
ing it on. For example:
Module Module1
Sub Main()
Dim h As Horse = New Horse(“Bucefalus”, “black”, 2)
Dim g As Horse = New Horse(“Lightning”, “brown”, 1.75)
Console.Out.WriteLine(“The horse (0) jumps {1} meters!”, _
h.name, h.Jump()) ‘ 1.75
Console.Out.WriteLine(“The horse (0) jumps {1} meters!”, _
g.name, g.Jump()) ‘ 1.3125
End Sub
End Module
It is important to understand that the class methods use the data of the
object on which they are invoked. This is one of the powerful paradigms of
object-oriented programming: The data (fields, properties) and the methods
that operate on it are represented as a unit—the class. If you were to use
structured programming, you would define a structure and a number of
functions that operate on that structure, but which are in no way associ-
ated with it. They could be in different modules or even in different pro-
grams. This leads to a very fragile architecture because changes to the
structure can affect parts of the program that you do not know about. When
using classes, the data and methods are all in the same place. This allows
for better encapsulation (no need to expose implementation details) and a
more robust architecture (all changes go in one place only).
In summary you can say that a method is a subroutine or function defined
in the class body that you can call on an object (using the dot-notation) to
ask the object to perform a specific task.
Method Overloading 279
Method Overloading
There are cases when a class needs to achieve the same task starting with
different input values—that is, with different arguments. You have seen
examples of this behavior when you learned about constructors. The same
rules apply to regular method overloading. The overloading of regular
methods is less common than the constructor overloading, which is used in
almost every class. A class that models a calculator could have a method
called Add that can be overloaded to take different types of numeric values
(Short, Integer, Long, and so on).
Public Class Calculator
Public Overloads Function Add(ByVal x As Short, ByVal y As Short) As Long
Return x + y
End Function
Public Overloads Function Add(ByVal x As Integer, ByVal y As Integer) As Long
Return x + y
End Function
Public Overloads Function Add(ByVal x As Long, ByVal y As Long) As Long
Return x + y
End Function
End Class
The Overloads keyword modifier is used to indicate that the method is over-
loaded. You can now use the class to calculate the sum of two integers,
longs, and so on. For example you could use the Calculator class as follows:
Module Module1
Sub Main()
Dim result As Long
Dim calc As New Calculator()
The use of the Overloads keyword is required for all methods that have the
same name. Also, overloaded methods must differ in their argument list:
They must have different number or different types of arguments, or have
them in a different order.
280 Chapter 15: Methods
Overloaded methods should be used to perform tasks that are very similar
but can have different input parameters. You should not use overloaded
methods to perform tasks that are semantically different, that is, tasks that
do not perform the same action.
You will learn more about overloading methods when you learn about
inheritance and interfaces in the next chapters.
Using Methods
Class methods can be used as you would use any function or subroutine,
except that you need a valid object on which to invoke the method. Use the
dot-notation to invoke the method and place the parameters (if any) in
parentheses after the method name. If the method is a function, you can
assign the result value to a variable of the appropriate type or use the func-
tion in an expression.
You have probably noticed that the properties and methods are relatively
similar from the implementation point of view. For example you could eas-
ily rewrite the Horse class presented previously to replace all properties
with functions and subroutines, as shown in the example:
Public Class Horse
Private m_name As String
Private m_color As String
Private m_height As Single
You have replaced the name and color properties with functions with the
same name. The property height you replaced with a getHeight function to
get the value and a setHeight subroutine to set the value. The class func-
tionality is unchanged. You can use it in the same way you did the original
version:
Module Module1
Sub Main()
Dim h As Horse = New Horse(“Bucefalus”, “black”, 2)
h.setHeight(1.9)
Console.Out.WriteLine(“The height is {0}!”, h.getHeight())
End Sub
End Module
You need to replace the use of the height property with the getHeight and
setHeight methods.
As a general set of guidelines you should use properties strictly to get or set
the value of an attribute (either a field or a calculated property) and even-
tually to validate the input value provided for the property. You should use
methods whenever the object performs other tasks (calculations affecting
multiple fields, interaction with other objects and the environment, and so
on). Adhering to these two simple guidelines will make your code readable
and easier to understand for others and for yourself.
Methods can invoke other methods or properties on the same object. You
have seen an example of this invocation in the constructor. This can be
done by either directly calling the method (without the dot-notation) or
using the MyClass keyword and the dot-notation to call the method.
You will now look at a more complicated example, which consists of two
classes that interact with each other. You will analyze each step you took to
implement this example. You have to implement a class named Person,
which models a person entity in a banking application, having a number of
accounts. Some of the methods you need for this person will be to deposit a
sum into an account, to withdraw an amount, and to transfer money from
one account to the other. The Account is also a class, but a very simple one,
having only a balance and an account identifier. The Account class is shown
next.
Public Class Account
Private m_id As String
Private m_balance As Decimal
The Account class has two private fields to store the account ID and bal-
ance, two properties that allow you to get the account ID, and get and set
the balance. You also have a constructor that takes an account ID and a
starting balance. The account ID cannot be changed after the Account object
is created, but the balance can. Let’s have a look at the Person class. We
will split the class definition in a few parts, so that we can better discuss
the methods. First implement the fields, a get property for the name, and
the constructor:
Public Class Person
Private m_name As String
Private m_accounts() As Account
You have a field and a property for the Person name, both String. The
name once set in the constructor will not change. You also have an array of
Account objects named m_accounts. These accounts will hold the banking
information for this person. In the constructor you set the m_name field and
then you create a new array that can hold two Account objects. This is sepa-
rate from creating the actual objects in the array, which is a separate step.
Then you create the two Account objects and assign them to the correspond-
ing array element. You create an account with the ID “Checking” and a bal-
ance of 2100 and assign it to the first element of the array (m_accounts(0)).
Next you create the second Account object that will hold the “Savings”
information. In real life you would read this information from a database,
but the code to do this is beyond the level you are at currently, so you just
fake it.
You now need to add a property for the users of the class person to access
their account balances. You could simply expose the Account objects in the
m_accounts array as a property. But this will allow the users to change their
balances, and this is not something you want to do. Therefore, you add a
284 Chapter 15: Methods
Loop through the accounts in the m_accounts array until you find the one
that has an ID that matches the accountId argument that was passed in
(the account for which the user wants the balance). When you find it,
return the balance and exit the property procedure.
You are going to use this type of code (which finds an account in the array
based in its ID) also in the deposit, withdraw, and transfer methods. So you
decide to make a private function that will do this finding for you, instead
of repeating the same for loop over and over. This is another fundamental
object-oriented principle, known as the principle of reusing. You will write a
method that can be reused whenever that task is needed, rather than hav-
ing a piece of code repeated all over. It is a commonsense way to code, if you
think about it. So rewrite the code:
Public ReadOnly Property balance(ByVal accountId As String) As Decimal
Get
Dim a As Account = GetAccountById(accountId)
Return a.balance
End Get
End Property
The utility function GetAccountById will return an account from the array
of accounts of this object (m_accounts), which matches the accountId
Using Methods 285
Withdraw(accountIdFrom, amount)
Deposit(accountIdTo, amount)
End Sub
Both Deposit and Withdraw are using identical mechanisms: find the
account requested and then increment/decrement the account by the
amount specified. The Transfer method is even simpler, as it calls first
Withdraw and then Deposit to execute the transfer.
You can now use the classes you developed. The next example illustrates a
possible scenario.
Module Module1
Sub Main()
Dim p As Person = New Person(“Dagny T.”)
p.Deposit(“Savings”, 1200)
p.Transfer(“Savings”, “Checking”, 450)
End Module
What’s Next 287
You have seen an example that is more involved and which illustrates most
of what you learned so far in the realm of objects and classes. It would be a
good idea to implement this example yourself and step through it to see
how the properties and methods work. Look at the local variables in every
method and property and try to understand what happens under the hood
(when are objects created, and so on).
You have learned how to represent properties and fields in design using
UML. Methods are also represented in design, using the third (and lower-
most) compartment of the class container. The same notation is used to
denote the visibility of the methods, as for the regular attributes (+ for
Public, # for Protected, - for Private, or nothing for Friend). Figure 15.1
illustrates the Person and Account classes you have implemented
previously.
Person
+name: String
-accounts: Account()
+balance: Decimal
+New(name: String)
+Deposit(accountId:String, amount:Decimal)
+Withdraw(accountId:String, amount:Decimal)
+Transfer(accountIdFrom:String, accountIdTo:String, amount:Decimal)
-GetAccountById(accountId:String) : Account
Account
+id: String
+balance: Decimal
+New()
+New(id:String, balance:Decimal)
The two classes are shown with all their methods and attributes. Notice the
way the return type of a method (if present) is displayed in UML.
What’s Next
In this chapter you looked at class methods in detail. You now know how to
overload methods and how to use methods to implement the class behavior.
You also know what the differences are between methods and properties
and when to use one or the other.
288 Chapter 15: Methods
In the next chapter you will study special types of properties and methods,
known as shared or static. You will see when shared methods and proper-
ties are useful, and you will, of course, do this by using a number of
examples.
NOTE
The answers to “Reviewing It,” “Checking It,” and “Applying It” are available on our Web
site.
Reviewing It
This section presents a review of the key concepts in this chapter. These
questions are intended to gauge your absorption of the relevant material.
REVIEW
1. What is a method?
2. What are the possible access modifiers for methods (that you learned
so far)?
3. What means to overload a method?
4. What are the differences between regular (module) subroutines and
functions and class methods?
Checking It
Select the correct answer to the following questions.
CHECK
Multiple Choice
1. A class method is a way to model:
a. Class attributes.
b. Object state.
c. Object state and behavior.
d. Class behavior.
2. A public method can be invoked from:
a. Anyone in this assembly or outside it.
b. Anyone in this assembly.
c. Anyone in the same namespace.
d. Anyone in the same class.
Checking It 289
True or False
Select one of the two possible answers and then verify on our Web site that
you picked the correct one.
1. A class method is a function or subroutine that can be invoked on any
object of the class, given that the caller has visibility (access).
True/False
290 Chapter 15: Methods
Applying It
Try to complete the following exercises by yourself.
A P P LY
Independent Exercise 1
Extend the methods Withdraw and Transfer of the Person/Account example
presented previously to include verification of overdraft (to make sure that
there is enough money before making a withdrawal—that the balance after
withdrawal is always ≥ 0).
Independent Exercise 2
Modify the balance property of the Person class to deal with the case when
an invalid account ID is provided in a better fashion (i.e., detect the error
and warn the user).
16
Shared Class Members
You have learned about class members such as fields, properties, and meth-
ods. In this chapter you will study a special type of class members named
shared members. The chapter is structured as follows:
• Shared members definition
• Shared methods
• Hints and tips regarding shared members
The shared member is a new concept in Visual Basic .NET; it did not exist
in the previous versions of the language. For those familiar with other
object-oriented languages, it is similar to the concepts of static members.
You will start with some definitions and an easy example that illustrates a
shared field and property. Next you will look at some more complex exam-
ples to illustrate the usage of shared methods, in combination with proper-
ties and fields.
The chapter concludes with a general discussion on shared members,
namely on when and how to use them. You will also learn some hints and
guidelines for coding.
294 Chapter 16: Shared Class Members
This is a perfectly valid class that would perform the task for which it was
designed. However, if you think about the way it is going to be used, you
will find a problem with this implementation. The tax rate is the same for
all products in the shop (assuming a flat tax rate). This means that in each
object you store the same value for the field m_taxRate. This is a waste of
memory because each instance of the class allocates the eight bytes (for
Double) required to hold the tax rate. Moreover, the users of the class must
specify the same value for the tax rate every time, when they construct an
instance of the class. You could place the tax rate into a global variable in
the program, but this raises encapsulation issues. Because only this class
(Product) uses the value, it should not be made public so that anyone could
get at it. It would be much better if you could somehow have a variable or
field that would be common for all objects of this class.
This is exactly what shared fields are: variables that are declared at class
level and shared among all instances of the class. In other object-oriented
languages these variables are called static, and you will find them defined
as static in parts of the .NET Framework documentation. They are also
known as class variables (or methods), in the sense that they are declared
and can be used at class level, as compared to the regular fields, which are
considered to be at the object or instance level. We will call them shared
fields, properties, and methods. They are declared using the special modi-
fier Shared, which can be used only inside classes.
Let’s rewrite the example to take advantage of the shared members:
Public Class Product
Private m_name As String ‘ product name
Private m_listPrice As Decimal ‘ the list price
The first change that you notice is that the field m_taxRate is now Shared
and was renamed to s_taxRate (the s_ is our convention, used to mark
shared fields to distinguish them from regular m_ member fields). The fact
that s_taxRate is Shared means that any object of the class Product can now
access the value of s_taxRate, and if anyone is changing it, the changes
will be reflected immediately to all objects that use it. This is a very good
reason to keep it private, so that only objects of this class have direct access
to it.
Another change you did is to have a shared property, which will allow con-
trolled access to the value of the shared field. Normally for shared fields
you implement shared properties. A shared property is not different from a
normal property, with the exception of the keyword Shared. It can be
Readonly, Writeonly, or both read and write (as in the example, where it
has both a get and a set). One difference between the shared and regular
properties is that a shared property cannot access fields or properties that
are not shared themselves. The reason for this is that the shared properties
are not invoked on any particular instance of the class. No instances means
no fields; therefore, the compiler will prevent you from accessing any non-
Shared Methods 297
The user uses the dot-notation on the class name itself (Product.taxRate =
0.08) to access the shared members. The reason for this is that the shared
members are not “part” of any particular object from the set, but rather
they apply to the whole set of objects (the class). The statement in bold sets
the value s_taxRate to be 0.08, which can subsequently be accessed by any
instance of the class.
The rest of the code is virtually unchanged, except that you removed the
argument taxRate from the constructor and now use the s_taxRate field
instead of the m_taxRate in the GetPrice function.
Notice that the class is now easier to use and understand from a coding
perspective: You have only one variable that holds the tax rate for all the
objects of the class. You initialize it only once during the lifetime of the pro-
gram, and then it stays at that value.
The lifetime of the static fields is the duration of the program. The value of
the variable may change in this time. If it is an object then, it may be allo-
cated with New at some point, or the field may be Nothing.
Shared Methods
Shared methods are similar to shared fields and properties in the fact that
they are not actions performed on an object, but rather actions performed
on the class level that do not require the existence of an object.
If you continue with the example, you may want to add a function that will
calculate the price for an unknown product. As it happens in any shop, you
might find a product without a label, or with a deteriorated label. In this
case the cashier will assign it a list price and will ask for the final price.
But because there is no product object that matches the description, you
need to provide a mechanism to calculate the price that is not based on an
existing product. The solution is to create a shared function that takes the
298 Chapter 16: Shared Class Members
list price assigned by the cashier (instead of, say, the product code or ID)
and calculates the final price.
You can add this function (shown in the next example) to the class Product
you developed previously.
Shared Function GetPriceUnknown(ByVal price As Decimal) As Decimal
Return CDec(price + price * s_taxRate)
End Function
The method is declared with the modifier Shared, as you did before for
methods and properties. It does calculate the final price based on the
assigned price (passed in as an argument) and the shared field s_taxRate.
It is important to notice that you do not access any instance members
(fields starting with m_, or properties). This is not allowed in a shared
method, and attempting to do so will cause the IDE and compiler to signal
a syntax error (Cannot access non-shared class members from shared
method).
You can also have overloaded shared methods. You can use the exact syntax
you used for regular methods, except that you must add the Shared key-
word to indic