100% found this document useful (6 votes)
4K views977 pages

1

The by example series teaches programming using the best method possible. The book covers some of the essential background material necessary for developing Visual Basic.NET applications.

Uploaded by

api-19641877
Copyright
© Attribution Non-Commercial (BY-NC)
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
100% found this document useful (6 votes)
4K views977 pages

1

The by example series teaches programming using the best method possible. The book covers some of the essential background material necessary for developing Visual Basic.NET applications.

Uploaded by

api-19641877
Copyright
© Attribution Non-Commercial (BY-NC)
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd

Introduction

The by Example Series


How does the by Example series make you a better programmer? The by
Example series teaches programming using the best method possible. After a
concept is introduced, you’ll see one or more examples of that concept in use.
The text acts as a mentor by figuratively looking over your shoulder and show-
ing you new ways to use the concepts you just learned. The examples are
numerous. While the material is still fresh, you see example after example
demonstrating the way you use the material you just learned.
The philosophy of the by Example series is simple: The best way to teach com-
puter programming is using multiple examples. Command descriptions, format
syntax, and language references are not enough to teach a newcomer a pro-
gramming language. Only by looking at many examples in which new
commands are immediately used and by running sample programs can
programming students get more that just a feel for the language.

Who Should Use This Book


Anyone who wants to learn Visual Basic .NET should read this book. The pre-
requisites include having a basic understanding of Microsoft Windows. As long
as you understand some of the simple concepts such as files and directories,
the Internet, and applications and programs, you should not have a problem
reading this book.
The book covers some of the essential background material necessary for devel-
oping Visual Basic .NET applications. This includes an overview of the develop-
ment environment, the language itself, object-oriented concepts, database
concepts, and XML.
This book is for you if you can answer true to one of the following statements:
• I know how to use Microsoft Windows (95, 98, NT, or 2000) and want to
learn how to program.
• I am a C++ and/or Java developer and I want to learn how to develop
applications for Microsoft .NET.
• I am a Visual Basic 6.0 developer and want to learn the new Visual Basic
.NET language.
• I design and build enterprise applications and want to learn a language
that can help me.
2 Introduction

This Book’s Organization


This book is presented in six parts. The first part gives a basic overview of
Microsoft .NET and Visual Studio .NET. This sets the context for the reader
in developing Visual Basic .NET applications. The reader is then presented
with his/her first view of a very simple application. This application is then
built and executed to acquaint the user with building an application using
Visual Studio .NET.
The second part covers the Visual Basic .NET language basics. This is the
first step in understanding the language itself and covers such things as
data types, variables, and language statements.
The third part moves into object-oriented concepts. This is necessary due to
the language improvements of Visual Basic .NET. Prior versions of Visual
Basic do not require any object-oriented knowledge. With this new version,
it is a must and this book tries to present the material in order to make you
a very good Visual Basic .NET developer.
The fourth part covers user interface development using Visual Basic .NET.
This includes developing forms and controls as part of your application.
The fifth part covers data access. Most applications today deal with some
form of data. ADO.NET and XML are popular ways of dealing with data. As
a result, these technologies are covered to show how these can be used from
Visual Basic .NET. This part also includes a basic overview of SQL, which
is used in database access provided by ADO.NET.
The sixth part covers developing Web applications using Web Forms. Here
we discuss the issues involved in developing Web applications and actually
how to do it using Visual Basic .NET.
At the end of the book, there is an appendix that covers UML (Unified
Modeling Language) in a quick crash course. The Web site includes migrat-
ing Visual Basic 6.0 to Visual Basic .NET applications, XML (eXtensible
Markup Language), and a reference of the Visual Basic .NET language.

Conventions Used in This Book


Examples are indentified by the icon shown at left of this sentence.
The source code listing is printed in a monospace font, for example:
Module Module1
Sub Main()
EXAMPLE System.Console.Out.WriteLine(“An Example”)
End Sub
End Module
Introduction 3

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.

CHANGES FROM VISUAL BASIC 6.0


These messages indicate the changes in Visual Basic from Visual Basic 6.0 to Visual
Basic .NET.

NEW IN VISUAL BASIC .NET


These messages indicate the additional features added to Visual Basic .NET

On the Web Site


Code examples in the book, the answers to the “Checking,” “Reviewing,”
and “Applying” questions at the end of each chapter, and additional refer-
ences are available at www.quepublishing.com.

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

First Steps in Visual Studio .NET Environment


Overview of the Environment
Creating the First Application
Compiling and Running the Application
Visual Basic .NET Project Types
1
Overview of the Environment
This chapter introduces Visual Basic .NET by presenting an overview of
the development environment. The goal here is to allow you to become
acquainted with the development environment before actually jumping into
learning the Visual Basic language itself.
In this chapter, you will
• Be presented with an overview of Microsoft .NET, Visual Studio .NET,
and Visual Basic .NET
• Take a tour of Visual Studio .NET
8 Chapter 1: Overview of the Environment

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.

Figure 1.1: A simple application.

Developers then started using VB to write applications that needed to


store data in a database. This way the application could store data in a
structured format and the data would remain on the computer when it was
turned off. The next time you turned on the computer and ran the applica-
tion you would be able to view the data again and add new data. The data-
bases started out by existing on the same computer as the application.
Later, the databases were moved to a central location on a network where
computers on the same network could talk to the same database. This way
Introduction 9

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

Figure 1.2: A client-server application.

As of Visual Basic 6, this client-server paradigm is still being used by


many developers. The successor to client-server is called an n-tiered appli-
cation (shown in Figure 1.3) and involves developing an application in
layers. Today’s typical application uses three distinct layers: the presenta-
tion layer, application logic layer, and data services layer. Each layer pro-
vides a specific function and is used by a layer above it. Assuming an
online e-commerce–type application, the presentation layer of an applica-
tion displays useful information to the application’s user, such as the
user’s account information and order form. The presentation layer com-
municates with the application logic layer, which provides the application
with specific functionality, such as how much to decrement the user’s
account based on the products they purchased. The application logic layer
communicates with the data services layer for reading and writing persis-
tent data, such as storing the order information in a database. Now, in
terms of an n-tiered application, each layer of an application could poten-
tially be running on a separate computer. If all the layers are running on
the same computer, the application is considered a standalone applica-
tion, or single tiered. If the application is running on three separate com-
puters (each layer running on a separate machine), the application is
considered a three-tiered application, and so on. Another way of express-
ing layers and tiers is that layers represent a logical separation of code
within an application. A tier represents where the code actually runs.
For the layers to talk to other layers running on different computers they
need a way of communicating across a network. Many Web applications fol-
low the n-tiered paradigm as part of their architecture. Examples of Web
applications are www.cnn.com, www.yahoo.com, and www.amazon.com. The com-
munication mechanism on the Microsoft Windows platform is based on
COM (Component Object Model) technologies.
10 Chapter 1: Overview of the Environment

Network

Database

User’s Computer User’s Computer

User’s Computer User’s Computer

Figure 1.3: An n-tiered application.

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.

What Is Microsoft .NET?


Microsoft .NET is a new platform for building distributed Web applications.
In Web development today, the focus is on building a Web site that runs an
application specific to the business. There is little thought (as a whole) to
integrating the Web site with other services provided on the Web. The
result is the development of Web-enabled applications that enable users to
perform very specific tasks. These applications are not very flexible as they
are only intended to fulfill the specific business needs related to the Web
site. With Microsoft .NET this no longer needs to be the case.
Microsoft .NET is the platform for the development of a new breed of appli-
cations. These applications no longer need to be specific to a single com-
puter or set of computers. You are able to build software services that run
in a Web environment. These building block services can then be invoked
by Web applications or bundled with other services as part of an even
richer application. Using Microsoft .NET, these services and applications
can run on any number of computers and the user interface for the applica-
tions can be displayed on different types of devices.
Along these lines, Microsoft is developing a set of services that can be used
as part of building a Web site. One of the sample services is Microsoft
Passport. This service enables you to visit http://www.passport.com and
obtain your own passport ID using your e-mail address and a password.
When you obtain a valid passport ID, it can be used to automatically log
you in to any Web site that supports Microsoft Passport. Participating Web
sites would invoke a call to the Passport service for verification. The result
is that you have a single sign-in capability for the Web.
There are several components to Microsoft .NET. They are .NET Infra-
structure and Tools, XML Web Services, .NET device software, and .NET
User Experience.
The .NET Infrastructure and Tools includes Visual Studio .NET, the .NET
Enterprise Servers, the .NET Framework, and Windows .NET. Visual
Studio .NET is, of course, the development tool of choice for building .NET
applications and services. Visual Studio .NET presently supports 20+ lan-
guages. This allows you to develop software in the language in which you
are most comfortable. The really interesting (and innovative) part here is
that code written in any of the supported languages is first compiled into
Intermediary Language (IL). This means that .NET is essentially language
neutral. IL then is executed as part of the Common Language Runtime
12 Chapter 1: Overview of the Environment

(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

What Is Visual Studio .NET?


Visual Studio .NET is “the” development environment for creating software
solutions targeted for the Microsoft .NET platform. You use Visual Studio
.NET to write your application code, build the solution, debug the code
to find your errors, and to help in deploying your application to other
computers.
If you are familiar with previous development tools from Microsoft, you
might be familiar with Visual Studio. Visual Studio is the development
environment for Visual C++ 6.0. Visual Basic 6 had its own separate devel-
opment environment for building Visual Basic applications. With the
advent of Visual Studio .NET, you can build applications using Visual
Basic, C# (pronounced see-sharp), and 18 or so other languages.
The advantage with Visual Studio .NET is that you, as a developer, only
need to learn one development tool. This will save you time if you ever get
to the point of having to develop an application using multiple languages.
This may seem unnecessary to you now but this is becoming more common
in the software industry. Having a tool like Visual Studio .NET, where you
can develop applications in multiple languages, is a huge step forward in
the world of software development.

What Is Visual Basic .NET?


Visual Basic .NET is the successor to Visual Basic 6. It is a software lan-
guage used to build applications targeted for the Microsoft .NET platform.
It has undergone some major changes in order for the language to support
the Microsoft .NET platform.

Tour of Visual Studio .NET


Now let’s take a tour of the development environment so that you can begin
to know your way around. The goal, at this point, is to allow you to become
familiar with the most common windows in the Visual Studio .NET devel-
opment environment. Because it would be overwhelming to present all the
windows at this point, we shall tour the most common ones now and then
cover the rest later in the book as they become relevant.
Let’s now start our tour of Visual Studio .NET.

Visual Studio .NET


If you are reading this book next to your computer, you may want to open
Visual Studio .NET at this point so that you can get a better feel for it.
Click Start, Programs, Microsoft Visual Studio .NET 7.0. When Visual
14 Chapter 1: Overview of the Environment

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

Figure 1.4: Visual Studio .NET 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

Figure 1.5: The File menu.

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.

Figure 1.6: List of available Visual Studio .NET toolbars.

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.

Working with Windows


You will find that after working with Visual Studio .NET for awhile, you
may want to display only a specific set of windows. Fortunately, Visual
Studio .NET allows you to customize your environment so that you can
choose to show only the windows that you use most frequently. In addition
to setting the options in My Profile to set the basic layout of the windows,
you can further specify which windows to show and hide as well as their
position. To show a particular window click on the View menu. This shows
a list of windows, as shown in Figure 1.7, that you can display as part of
the environment.
The View menu contains a list of the most common windows plus a menu
item for Other Windows. Clicking this menu item displays the remaining
list of windows available to you. As an example, click View, Other Windows,
Output to display the output window. Figure 1.8 shows the output window
now visible to you, docked below the Get Started window.
Tour of Visual Studio .NET 19

Figure 1.7: View menu.

Figure 1.8: Output window.

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.

Figure 1.9: Contents window.


Tour of Visual Studio .NET 21

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.

Figure 1.10: 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

Figure 1.11: Search window.

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

Figure 1.12: Dynamic Help window.

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

c. Set up some default settings for Visual Studio .NET.


d. All of the above.
5. The Solution Explorer window:
a. Contains output messages informing you of the success or failure
of building your project.
b. Allows you to directly edit properties of elements in your project.
c. Contains all the elements contained within your project and
allows you to navigate to them.
d. None of these.

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.

Creating a New Project


You can create a new project in Visual Studio .NET at any time by clicking
on the File, New Project menu (or by pressing Ctrl+N). The dialog shown in
Figure 2.1 is displayed as the initial step in creating a new project.
Here you would select the type of application you wish to create and specify
the name and location of the project. Select Visual Basic Projects as the
project type and select Windows Application as the desired template. You
can specify any name you want for your project and the location is typically
somewhere on your computer or on an accessible network drive.
Creating a New Project 29

Figure 2.1: New Project dialog box.

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.

Figure 2.2: A simple application.

A Tour of the Generated Project


The Solution Explorer displays all of the different types of elements that
are part of the solution. A solution is a grouping of one or more projects. If
you are just starting to use Visual Studio .NET most of your solutions are
probably going to contain just one project. As you become more experienced
you may develop many projects as part of one overall solution.
Figure 2.2 shows this solution contains one project. You can create another
project and add it to this solution by selecting File, Add Project, New
Project. This displays the Add New Project dialog box shown in Figure 2.1.
After you select the type of project you want to create, name it, and give it
a location, the new project is added to the solution that is currently open. If
you select the Close Solution, the current solution is closed and a new solu-
tion is created that contains the new project.
Under the project in the Solution Explorer, you can see the References
(which is explained later) and the default form created as part of the new
project.
A Tour of the Generated Project 31

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.

Figure 2.3: Solution Explorer and 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.

The Properties window could contain many properties based on an element


selected. If you click once on the form displayed in Figure 2.2, you will see
the form’s properties as shown in Figure 2.4. The Properties window has an
icon for displaying the properties in a categorical grouping or alphabeti-
cally. You have the option of switching between these two displays, allowing
you to list the properties in whichever way is most appealing to you. Figure
2.4 shows the properties in alphabetical order and Figure 2.5 shows the
properties grouped by category.
A Tour of the Generated Project 33

Figure 2.4: Properties in alphabetical order.

Figure 2.5: Properties grouped by category.

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

Public Class Form1


Inherits System.Windows.Forms.Form

#Region “ Windows Form Designer generated code “

Public Sub New()


MyBase.New()

‘This call is required by the Windows Form Designer.


InitializeComponent()

‘Add any initialization after the InitializeComponent() call

End Sub

‘Form overrides dispose to clean up the component list.


Protected Overloads Overrides Sub Dispose(ByVal disposing As Boolean)
If disposing Then
If Not (components Is Nothing) Then
components.Dispose()
End If
End If
MyBase.Dispose(disposing)
End Sub

‘Required by the Windows Form Designer


Private components As System.ComponentModel.IContainer

‘NOTE: The following procedure is required by the Windows Form Designer


‘It can be modified using the Windows Form Designer.
‘Do not modify it using the code editor.
<System.Diagnostics.DebuggerStepThrough()> Private Sub InitializeComponent()

‘Form1

Me.AutoScaleBaseSize = New System.Drawing.Size(5, 13)
Me.ClientSize = New System.Drawing.Size(292, 273)
Me.Name = “Form1”
Me.Text = “Form1”

End Sub

#End Region

End Class
36 Chapter 2: Creating the First Application

Notice the use of the System.Windows.Forms.Form. This represents a refer-


ence to a predefined class that is provided as part of the Microsoft .NET
Framework Library. In every program or application that you are going to
develop in Visual Basic .NET, you will not want to write everything your-
self. You will want to use code that you have previously written or take
advantage of code that someone else has written. For example, if you want
to draw a line on a form you would not want to write code to draw every
pixel that exists in a direct line between two points. You would never get
your application finished if you took this approach. The best approach is to
leverage as much existing code as possible so that you are not reinventing
the wheel (so to speak).
Visual Studio .NET provides a Framework Library of code that you can use
in building your software. Namespaces are used to avoid naming collisions
(such as classes) in code. For example, using namespaces you could name a
class “Form” in your own namespace named “MyCode” and refer to the
Form class in your code as MyCode.Form. This allows your Form class to
coexist with the System.Windows.Forms.Form class provided with the
.NET Framework Library since they are in different namespaces. For
example:
Dim form as MyCode.Form = new MyCode.Form()

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()

Namespaces are partitioned into assemblies. An assembly is simply a


prepackaged container of code. Specifically, an assembly is a DLL contain-
ing managed code that runs in Microsoft .NET. The meaning of managed
code versus unmanaged code is explained later in this book. For now, recog-
nize that namespaces allow you to segment your code to avoid naming colli-
sions with pre-existing classes and types. Assemblies are the deployable
units in which your code resides (i.e., a DLL). You will learn more about
namespaces and assemblies as well as the Microsoft .NET framework
throughout this book.
When a namespace is imported or referred to in code, the assembly which
contains the namespace is shown in the Solution Explorer under the
“References” element. This way you can easily figure out which assemblies
are being referenced by the project. Figure 2.7 shows the references defined
A Tour of the Generated Project 37

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.

Figure 2.7: Assembly References for a project.

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

4. The #Region and #End Region statements are used to delineate


comments in your code.
True/False
5. Bold property values in the Properties window represent properties
that have been modified from their original value.
True/False
6. Property values can only be viewed in alphabetical order.
True/False

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

Building the Project


Once you have typed in your source code, using the source code editor in
Visual Studio .NET, you probably want to run it to verify that it works.
Unfortunately, your computer does not understand how to execute or run
your program using the source code directly. Your computer can only run
software that is written in a language called machine code. Machine code is
a format that is directly understood by your computer and is not humanly
comprehensible (at least not for most of you).
Most software developers use a language such as Visual Basic to write code
and then use a tool such as Visual Studio to convert this code into machine
code for the purpose of having the computer understand it. This allows you
to develop software in a format that is comprehensible to humans and then
convert it to a format that a computer can process.
In order to build your project, you would use the Build Solution menu item
on the Build menu in Visual Studio .NET.
Figure 3.1 shows the result of building the project you created in Chapter 2,
“Creating the First Application.”

Figure 3.1: Building the Project.

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

code contains extra information for use by the debugger. A debugger is a


tool used by software developers to execute software step by step. Using a
debugger, you can stop at any point in your software and inspect it to see if
it is behaving as you expected. In Release mode, there is no extra informa-
tion created as part of the generated code. The resulting code is lean and
optimized for faster and better performing code.
Most developers build their project in Debug mode until the project is
nearly finished. Once the project is fairly stable in its development, you
may want to start building it in Release mode to further test it and verify
that the project continues to run normally. The build mode (Debug or
Release) is set using the Configuration Manager on the Build menu.

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

Figure 3.2: Building a project with errors.

Figure 3.3: Output window containing build errors.


Running the Application 47

Building and Rebuilding


You may have noticed that there is a Build and a Rebuild menu item. After
you build your project for the first time, selecting Build will only build the
files that have changed since the last build. This way if you have many files
in one project only the files that changed would be built again. This saves
time if you have large projects containing hundreds of files and you only
make a single change to one file. Only that file would be built when you
select the Build menu item from the Build menu.
The Rebuild menu item is available for the situation where you want to
rebuild the whole project no matter what. Selecting the Rebuild option does
not take into account which files have changed and which have not. They
are all rebuilt regardless.

Running the Application


If I remove the erroneous text I just added so that the project is back to the
way it was originally I can build the project and run it. If you have built
the project in Debug mode you can execute the project in the debugger.
If you are like most developers, you will probably want to start running
your newly built projects in the debugger. At some point, your project
becomes stable and is free of notable errors. This is when you would start
to run it outside the debugger. You can run a project that was built in
Debug mode or Release mode outside the debugger.

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.

Figure 3.4: Sample project running.

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

computer. This tends to give your program a professional polish to it and


helps the user install it in a much more elegant way. There are a number of
different types of deployment options available to you (besides copying the
files) and these are discussed later in the book.

Under the Covers


I sort of skimmed over the details of what happens under the covers during
the build process on purpose so that you could focus more on understanding
the process of building rather than low-level details of what’s happening.
Now that you have gone through the process of building and running the
application let’s take a look at what’s happening so that you can appreciate
some of the major improvements of Microsoft .NET.
Existing Visual Basic developers are aware that they can build their pro-
jects into P-Code or directly into Native code. P-Code is an intermediate
step between your Visual Basic code and Native code. P-Code is then com-
piled at runtime by the Visual Basic runtime services into Native code.
Native code is the format that is directly understood by the processor on
your computer.
With Visual Basic .NET, P-Code is no longer used and you no longer have
the capability to generate Native code directly. Instead, Visual Basic .NET
source code is compiled into the Intermediary Language (or IL for short).
This applies to all of the other available languages in Visual Studio .NET
as well. The compilation process checks the code for correct syntax as
defined by the specific language.
The IL that gets generated contains managed code and metadata. Managed
code is a term used to express code that is generated by Visual Studio .NET
and managed by the Microsoft .NET Framework. The metadata is language
neutral type information used to describe the generated code and data
types, location of references to other objects, and exception handling tables.
The Common Language Runtime (CLR), which is part of the Microsoft
.NET Framework, loads the IL code (and metadata) at runtime and com-
piles it to Native code using a Just-In-Time (JIT) compiler before the code
is executed by the computer’s processor. The code is compiled the first time
the code is accessed. Subsequent accesses of the same code use the already
compiled code created by the JIT.
Managed code is intended to be safer and more reliable since it is being
“managed” by the Microsoft .NET Framework, which handles the execution,
versioning, security, and deployment issues. Managed code does not require
any registration unlike COM dlls generated with Visual Basic 6.0 or Visual
50 Chapter 3: Compiling and Running the Application

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

Figure 4.1: Windows Application project.

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

Figure 4.2: Class Library project.

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

Figure 4.3: Project Property Pages.

Windows Control Library


A Windows Control Library project is used to create a customized control
that can be used by other projects. A Windows Control is a user interface
artifact that usually has a unique look and feel to it. It may also provide
the capability of user interaction such that the user could possibly click on
it or enter some values.
Windows provides a set of Common Controls that you can immediately use
in your development. This includes a Label control for displaying text on a
form, a Textbox control for allowing the user to enter data onto a form, and
a Button control for providing the capability for the user to click on some-
thing visual which then performs a task. Most of you are familiar with
these types of controls.
60 Chapter 4: Visual Basic .NET Project Types

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.

Figure 4.4: Windows Control library project.

ASP .NET Web Application


A Web Application project allows you to develop applications for the Web
that are accessed through a Web browser. If you are currently familiar with
ASP, think of this project type as ASP development on steroids. This type of
project is actually based on ASP.NET using Visual Basic as the develop-
ment language.
ASP .NET Web Application 61

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.

Figure 4.5: Web Application.

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

ASP.NET Web Service


A Web Service project allows you to develop an entirely new brand of soft-
ware. From a high-level standpoint, a Web Service is basically a component
that can be invoked across the Web. The service itself can be developed by
you and would reside on a server somewhere on the Web waiting for con-
sumers of it. Along with Web Services, there is a mechanism for the discov-
ery of Web services enabling users to quickly find out the details and use
the service.
For example, wouldn’t it be nice if there were an easy way to add simple
local weather forecasts to an application you are building for the Web? This
could be provided as a Web Service and published so that developers would
be able to utilize it. An XML message would be constructed that included
the zip code of the user (including other optional data) and dispatched to
the Web Service. The Web Service would receive the message, process it,
and send back an appropriate response containing the current day’s local
weather report. The client that initiated the call to the Web Service would
then process the response and display the data appropriately.
As a Web Service, this functionality can be included in any web application
without having to rewrite the server code to get the relevant data. As more
and more interesting building block services are built, applications will
become richer and more rewarding since there will be a lot to offer without
the traditional expense incurred to make these features available.
It is true that invoking components remotely is not a new concept; however,
you now have the capability to develop software that can be called over the
Web. And because it uses SOAP (Simple Object Access Protocol, see http://
www.w3.org/TR/SOAP/ for more information) as the protocol it can be
accessed from any other computer. This includes computers running UNIX.
So, essentially you can now develop a service that is accessible by any other
computer. The additional benefit is that Web Services can be invoked with-
out having to download or install any software on the client computer. This
further supports the accessibility of future Web Services as they become
available.
The types and number of services that will be developed using this technol-
ogy is unclear at this point. This is going to be left up to developers like you
to provide these services to the marketplace. A good place to start, as a
developer, is http://www.gotdotnet.com. This place provides lot of .NET
information as well as interesting code samples.
The initial structure of this project includes several different files similar to
the files you may have seen in the Web Application project. These files are
discussed in Part VI when we talk about developing for the Web.
Console Application 63

Web Control Library


Along the same idea as a Windows Control Library project, the Web Control
Library project allows you to develop a control that is intended for use on
Web Forms. This type of project enables developers to create customer user
interface components that are meant to be used specifically for Web appli-
cations or an Internet device.
The initial structure of this project includes the default Web control and
any project references as a result of importing assemblies.

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.

Figure 4.6: Command Prompt window.

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.

Figure 4.7: Administrative Tools folder in the Control Panel.

Figure 4.8: My computer’s list of installed services.


Reviewing It 65

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.

Empty Web Project


This is along the same lines as the Empty Project. The difference here is
that this project is going to be Web-related whereas the Empty Project type
is not Web-related.
You would create a project of this type if you were starting out by creating a
solution in which you are going to then add more than one other project to
it. Otherwise, it is just as easy to create one of the other project types such
as Web Application, Web Service, or Web Control Library.

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.

By software we understand a program that can execute (run) on the hard-


ware. The software program (or program, in short) consists of a set of
instructions expressed in a language the CPU can understand (called
machine code).
The way this execution (running) of a program occurs is (in a simplified
version): the program is loaded from permanent memory into working
memory. Then the CPU executes sequentially all instructions in the pro-
gram. These instructions may require some input data and may produce
output data. For example, a word processor program would normally
require input from the user (the user must enter some text from the key-
board) and the program may output the document to a printer or save it to
a file.
Introduction to Programming 73

It is important to understand that the whole program execution takes place


in working memory, which is manipulated by the CPU according to the
instructions provided in the program. The program itself may use addi-
tional resources such as disk files, and so on.
You probably are wondering how the program is loaded in working memory
and who is managing the miscellaneous resources that the multitude of
software programs requires. One special type of software, which is known
as the operating system, does all this (and much more). The operating sys-
tem (OS) loads a program in response to a request from the user, for exam-
ple. It also provides a variety of resources to the programs that run, from
simple input/output (IO) to network and database services. Examples of
operating systems include the Windows family, Linux, and Solaris.
One of the most important concepts that you need to understand is how the
working memory (RAM) is structured because it is in this memory where
all software runs. The working memory is a sequence of bits. A bit is the
fundamental type that computers use to represent data and software, and
it can have two possible values: 0 and 1. These bits are organized in bytes—
each byte consists of 8 bits. Therefore you can represent the working mem-
ory as a sequence of bytes. A memory address is the number (index) of that
byte in the sequence. The term memory address is commonly used as the
shorthand address, when speaking of software and programming. See
Figure 5.1 for a diagram of how working memory is organized.

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

Figure 5.1: Working memory (RAM) organization in a computer.


74 Chapter 5: Language Description

All data and software that a computer uses is represented in memory as


bytes—single bytes or bytes grouped together to represent more complex
data. For example a UNICODE character requires 2 bytes of memory. A
normal Integer value requires 4 bytes of memory. The contiguous memory
where a piece of data is stored is known as a memory location. We will use
this term frequently in the rest of the book.

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

maintenance. In both cases a final (but easy) translation step is required to


transform the intermediary code into machine instructions.
BASIC stands for Beginner’s All Purpose Symbolic Instruction Code and
it is a system developed at Dartmouth College beginning in 1964. It was
originally meant to be a very simple language both from a learning and
translation perspective. Indeed the first generations of BASIC were quite
simplistic, lacking a lot of features that more powerful languages of the day
(like Fortran and Algol) had.
Both Microsoft and IBM provided a very successful interpreted version of
BASIC for the PC (known as GWBASIC and BASICA). Later on Microsoft,
realizing the potential of the new language, provided a compiler for it,
known as QBasic (for Quick-Basic) and a very short-lived professional ver-
sion (PDS Basic). Some competition came from Borland with its version of
TurboBasic, which was also quite popular in the late eighties.
The first version of Visual Basic become available at the beginning of the
nineties, and evolved through version 3 for Windows 3.x, and then from
version 4 and up to today’s Visual Basic .NET, for 32-bit versions of
Windows. Microsoft currently still supports Visual Basic 6.
Visual Basic was (and is) a very successful language for the same reason
as its venerable ancestor BASIC was: it has a simpler syntax and faster
learning curve for beginners, while at the same time allowing advanced
programmers to achieve complex tasks with ease. That said, one has to
understand that, apart from the name and some syntax constructs, there
is little resemblance from the original BASIC and the current component-
oriented Visual Basic .NET. There are a lot of new features that make this
popular language the language of choice for some 4 million programmers
across the world. In the rest of the book you will learn some of the most
important of these features.

Structure of a Visual Basic Project


You have seen in the previous chapters what are the mechanics of creating
a new Visual Basic project. In this section we will discuss this topic in more
detail. You will create a simple project that does only one thing: it displays
a “Hello World!” message to the console.

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.

Figure 5.2: New project dialog for HelloWorld.

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.

Figure 5.4: Running the HelloWorld application.


Identifiers, Literals, Keywords, and Whitespace 79

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.

Identifiers, Literals, Keywords, and Whitespace


Now that you have seen what a Visual Basic program looks like, you can
define some of the fundamental language components.
An identifier is what is commonly referred to as a name in programming. It
can be the name of a project, module, variable, object, method, and so on.
You have seen some identifiers; you will see much more as you go along. An
identifier in Visual Basic must conform to some naming rules: it must start
with a letter and it must not contain any other symbol than letters, digits
and the _ (underscore) character. Valid identifier names are Module1, Main,
80 Chapter 5: Language Description

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

code to extend (improve) it or is just reading it trying to understand what


different parts of it are doing, or as input for a documentation generation
tool.
In programming, these are called comments and all high-level languages
have them, although the way they are marked differs. The compiler
removes the comments when the code is compiled.
In Visual Basic the comments are delimited by the single quote (‘), and end
at the end of the line. Let’s add the bold line from the code snippet below in
your program and run the program again.
Module Module1

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

A comment can be also placed at the end of a line of code (normally a


shorter comment) as shown below:
Console.In.ReadLine() ‘ waits until the user presses Enter

As you have seen by running the program, no changes in behavior occurred


because of the added comments—the compiler stripped them away from the
compiled code, as you have expected.

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

As you have seen, a computer program is a series of instructions that tell


the computer how to operate on some input data to produce output data.
You have also seen that the data (both input and output) is usually repre-
sented in the working memory of the computer. This memory is organized
in bytes. You could use bytes and memory addresses of these bytes to repre-
sent any form of data that you need, and indeed that is the way the low-
level languages operate. However, it is not an easy task to deal with data in
this raw format: it is easy to make mistakes and hard to track them down,
to name just a few issues. Therefore, all high-level languages (Visual Basic
included) have a predefined set of data types that the programmer can use,
to ease data manipulation. Most of these languages also allow the program-
mer to define new data types, as required.
A data type can be thought as a common way to represent the same type of
value in the working memory of the computer. We will extend this concept
further when you will learn of classes. For example, an Integer value
requires a memory location of four bytes in size, whereas a Short value
requires only 2 bytes (simply said, Short has a storage size of 2 bytes, or it
takes 2 bytes). Some data types use a fixed memory size (as the Integer)
while others (like String) take a variable amount of space in memory.
88 Chapter 6: Fundamental 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.

Numeric Data Types


The Visual Basic language defines the numeric types as described in
Table 6.1.

Table 6.1 Numeric Data Types in Visual Basic .NET


Name Size Value Range and Description
Byte 1 byte 0 to 255. An unsigned byte.
Short 2 bytes –32,768 to 32,767. Integer value.
Integer 4 bytes –2,147,483,648 to 2,147,483,647.
Integer value.
Long 8 bytes –9,223,372,036,854,775,808 to
9,223,372,036,854,775,807. Integer
value.
Decimal 12 bytes +/–79,228,162,514,264,337,593,
543,950,335 with no decimal point;
+/–7.92281625142643375935439
50335 with 28 places to the
right of the decimal; smallest
non-zero number is +/–0.0000000
000000000000000000001.
Single 4 bytes 3.402823E38 to –1.401298E-45 for
negative values; 1.401298E-45 to
3.402823E38 for positive values.
Floating point decimal value.
Double 8 bytes –1.79769313486231E308 to
–4.94065645841247E-324 for nega-
tive values; 4.94065645841247E-
324 to 1.79769313486232E308 for
positive values. Floating-point decimal
value.
Numeric Data Types 89

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.

Variable Declaration and Assignment


Now that you have seen the main numeric types you can start using them.
Let’s create a new console project (follow the same instructions as for the
previous chapter and name the new project DataTypes). In the Sub Main of
Module1 add the following lines of code in bold:
Module Module1

Sub Main()
Dim i As Integer
i = 6
Console.Out.WriteLine(“The value of i is {0}”, i)

Console.Out.WriteLine(“Press the <Enter> key to end the program”)


Console.In.ReadLine()
End Sub

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

Or on the same line:


Dim i As Integer = 6, 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.

Arithmetic Operators on Numeric Values


The arithmetic operators are used to perform simple arithmetic calculations
on the values that your program uses. They are the regular arithmetic
operators (addition, subtraction, multiplication, and division) with the addi-
tion of some special operators: modulo (or remainder of integer division)
and exponentiation. The following example can be used to illustrate these
operators. Change the code in the example to look like
Module Module1

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...

Console.Out.WriteLine(“Press the <Enter> key to end the program”)


Console.In.ReadLine()
End Sub

End Module

Save and run the program. Your output should match the one in Figure 6.1.

Figure 6.1: Output of running the DataTypes sample program.

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

Another interesting operator for integral data types is modulo or the


remainder of integer division, written as mod. The result of 11 modulo 3 will
be 2.
Normal division can be used for non-integral data types (either floating
point or fixed precision decimal numbers). You can also note the difference
in precision between the Decimal and Double data types.
Finally the exponentiation operator (^) is used to compute 231.

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 Data Type


The Boolean data type can hold two values, True and False; both True and
False are keywords in Visual Basic. For example:
Dim b As Boolean = True

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.

String and Char Data Types


Individual characters (letters, digits, symbols) can be represented using
the Char data type, which takes 2 bytes of memory, and represents a
UNICODE character.

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.

Date Data Type


Dates and times are represented in Visual Basic using the Date data type.
A Date value takes 8 bytes of memory and can represent dates and times
between January 1, 1 CE to December 31, 9999. The precision of the date is
up to milliseconds. Following are a few examples of declaring and initializ-
ing a date variable:
Dim d As Date = #2/2/2001#
Dim dt as Date = #January 1 1900 12:32:45 PM#
Reviewing It 95

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).

Other Data Types


There are many other predefined data types that can be used in Visual
Basic—all of which come from the .NET Framework. We have UInt32,
UInt64, and so on. All the data types you have learned, as well as the ones
that you will see later, are actually classes or structures defined in the
.NET Framework. You will understand better what the meaning of the pre-
vious statement is as you learn more about the data types and then classes
and objects.

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

c. The initial value specified in the Dim statement. 0.0 if no initial


value is specified.
d. The initial value specified in the Dim statement. Infinity, if no
initial value is specified.
6. What is the difference between the \ and the / operators?
a. / is used for division and \ is used for fractions.
b. / is used for division and \ is used for string concatenation.
c. / is used for integer division and \ is used for floating point divi-
sion.
d. / is used for division of decimal types and \ is used for integer
division.
7. To concatenate strings “A” and “B” into a new variable s you would
write a statement like:
a. s = “A” + “B”
b. s = “A” & “B”
c. s = “A” . “B”
d. Strings cannot be concatenated.

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

5. A variable of type Date can be used to represent dates in the


Cretaceous period (when dinosaurs were still roaming the Earth).
True/False
6. Assignment and initialization of a variable is the same thing.
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 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.

Implicit Data Conversion


When the compiler encounters an assignment statement it will ensure that
the data type of the variable being assigned matches the type of the value
being assigned to it. If the two are not of the same type it will verify that
the two types are compatible, that is, the compiler can implicitly convert
the value into the variable data type. This is called an implicit conversion.
If this is not the case a syntax error will be raised—the program is invalid
(cannot be compiled).
For example the following code will compile and run correctly:
Dim i As Integer, d As Double
d = i

While the next lines of code will not compile:


Dim i As Integer, d As Double
i = d

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

Figure 7.1: Error message attempting to convert a Double to an Integer.

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

You will see a few examples of implicit conversion shortly, immediately


after you learn about explicit conversions.

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.

Explicit Data Conversion


What happens if you need to convert a Double to an Integer, and you know
that the magnitude of the Double value is within the range of acceptable
values for the Integer data type? If the implicit conversions would be the
only mechanism available, you would be stuck. But they are not. An explicit
conversion is a transformation function that takes a data type and trans-
forms it into another data type. There are a number of conversion functions
available in the Visual Basic language, some of which are in Table 7.1.

Table 7.1: Conversion Functions in Visual Basic .NET


Name Converts To Comments and Parameter Range
CByte Byte 0 to 255 (same as for Byte data type)
CShort Short Same as for Short data type
CInt Integer Same as for Integer data type
CLng Long Same as for Long data type
CDec Decimal Same as for Decimal data type
CSng Single Same as for Single data type
CDbl Double Same as for Double data type
CBool Boolean String (“True”/”False”) or numeric (0 will be con-
verted to False, anything else will be converted to
True)
CChar Char Cannot be numeric, may be String
CStr String Anything that can be converted to a String
CDate Date A string that holds a valid date/time
representation

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.

An obvious question here is what happens if the value of d is greater than


it would fit into an Integer (it is larger that 2,147,483,647 or smaller than
–2,147,483,648), or if the value passed in is of a type incompatible with
Integer. The compiler has no means of knowing what the value of d is until
the program is run, so there is no way of warning you during program com-
pilation. What is going to happen is this: when the program is executed (at
runtime) the function CInt will check the value passed in and if it is outside
the range acceptable for the return value (Integer) it will throw an excep-
tion. You will learn more about exceptions later on. For now what you need
to understand is that an error message will be displayed, and then the run-
ning program will be stopped prematurely.
There are two ways to avoid this premature termination. One would be to
ensure that the value passed to the conversion function is within the cor-
rect bounds, and if it is not, you should let the user know somehow and
correct the problem. The other (which you will learn later on in the book)
is to handle the exception so that the program will continue.
106 Chapter 7: Data Conversions and Expressions

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)

Console.Out.WriteLine(“Press the <Enter> key to end the program”)


Console.In.ReadLine()
End Sub

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.

Figure 7.2: Output of running the DataConversion example.

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)

Console.Out.WriteLine(“Press the <Enter> key to end the program”)


Console.In.ReadLine()
End Sub

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.

Figure 7.3: Output of running the modified DataConversion example.

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)

Dim d As Double = 33.27


d /= i ‘ d is now 11.09 (i is still 3)
Console.Out.WriteLine(“The Double value d is {0}”, d)
110 Chapter 7: Data Conversions and Expressions

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)

Console.Out.WriteLine(“Press the <Enter> key to end the program”)


Console.In.ReadLine()
End Sub

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

The expression i < 5 on the right side of the assignment operator = is a


relational expression, and < is the comparison operator known as “less
than.” It has the same meaning as its mathematical counterpart. The
expression will be evaluated to True since i is 3 and therefore, is less than
5. The result of this evaluation (the Boolean value True) will then be
assigned to the variable b. The Table 7.2 lists the comparison operators in
Visual Basic and their mathematical counterparts (if any are existing).

Table 7.2 Comparison Operators in Visual Basic .NET


Operator Mathematical Comments
= ≡ Equality, a equals b
<> ≠ Inequality, a is not equal to b
< < Less than, a is less than b
<= ≤ Less than or equal to, a is less than or
equal to b
> > Greater than, a is greater than b
Boolean Operators 111

Table 7.2 continued


Operator Mathematical Comments
>= ≥ Greater than or equal to, a is greater
than or equal to b
Like Special operator for strings, used for pat-
tern matching
Is Special operator for objects, True if
object a is the same as object b

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.

Expressions and Operator Precedence


The arithmetic, comparison, and Boolean operators, as well as data conver-
sion and other types of functions, can be used to create powerful expres-
sions that can be used in your computations and programs.
An expression is a combination of values and operators. The values can be
literals or variables, the operators can be any combination of known opera-
tors, and a few more that you will learn later on in the book.
The type of an expression is the data type of the result of the evaluation of
an expression. An expression 2 + 3 is a numeric (Integer) expression. i > 5
is (as you have seen) a logical or boolean expression. An expression that
evaluates to a String will be a String expression. By evaluating an expres-
sion we understand replacing all the variables with their current values,
and then performing all the calculations (according to the operators in the
expression) in the appropriate order.
An expression can be as simple as i + 3 and as complicated as required by
the computations in your program. Similar to mathematical expressions,
the operators have different operator precedence, which will determine the
order in which the expression is evaluated. For example in the following
expression:
i = 5 + 3 * 2

i will be assigned the value of the expression 5 + 3 * 2. The compiler will


first multiply 3 with 2, will then add 5 to the result (6) and will assign the
total result (11) of this expression to i. Operator precedence indicates to the
compiler in what order the operations should take place. In your example
multiplication has a higher precedence than the addition, as you have
probably expected based on elementary mathematics. Again, as in math,
you can use parentheses to change the order of evaluating any given
expression. For example, reusing the same code, if you intended that the
Expressions and Operator Precedence 113

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.

Table 7.3 Operator Precedence in Visual Basic .NET


Operator Type Comments
^ Arithmetic Exponentiation
- Arithmetic Negation –i (this is not the same as
subtraction)
* and / Arithmetic Multiplication and division
\ Arithmetic Integer division
mod Arithmetic Modulus
+ and - Arithmetic Addition and subtraction
bitwise Arithmetic Bitwise operators (you will study these
operators later)
& and + Special String concatenation (not to be con-
fused with addition)
= Comparison Equality
<> Comparison Inequality
< Comparison Less than
> Comparison Greater than
<= Comparison Less than or equal to
>= Comparison Greater than or equal to
Like, Is Comparison Specialized comparison operators
Not Boolean Unary not
And Boolean And
Or Boolean Or
Xor Boolean Exclusive or

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

The first statement declares an array of Decimals having five elements


(indexes from 0 to 4). The next statement is assigning the literal value 100
to the first element of the array. The last statement assigns the value 250 to
the last element of the array. Note the way an individual element of the
array is accessed is by specifying in parentheses the index of the element
you mean to access. Therefore balance(0) will represent the first element
in the array, while balance(4) will represent the last element in the array.
If you were to try to access an element that is not in the array—say ele-
ment 7, as in balance(6) you would get a runtime exception and the pro-
gram would be terminated. This type of exception is known as an
out-of-bounds array access exception and is not uncommon.
The values at any given index in the array may be used in an expression,
the same as any other regular variable. And indeed they are (from the point
of view of the compiler) just a regular variable, just the notation is differ-
ent. For example:
Dim balance(4) As Decimal
balance(0) = 100
Dim b As Boolean
b = balance(0) <= 250

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

Console.Out.WriteLine(“Press the <Enter> key to end the program”)


Console.In.ReadLine()
End Sub

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.

Figure 8.1: Array example output.

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

balance = New Decimal(4) {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)

Console.Out.WriteLine(“Press the <Enter> key to end the program”)


Console.In.ReadLine()
End Sub

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 declaration declares a two-dimensional array of Decimals. The upper


bound of the first dimension is 2; the upper bound of the second dimension
is 4. This is similar to a matrix of 3×5 elements, where each matrix element
124 Chapter 8: Arrays, Enumerations, and Structures

corresponds with an array element (a Decimal value in our example). If you


needed the array to have more dimensions, the sizes for the dimensions are
separated with commas, exactly as in the previous example. A three-dimen-
sional array declaration would look like:
Dim coordinates(9, 9, 9) As Double

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)

Console.Out.WriteLine(“Press the <Enter> key to end the program”)


Console.In.ReadLine()
End Sub
Enumerations 125

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) {}

This example creates a new two-dimensional array of 3×5 Decimals.


Most of the examples that you use are going to be one-dimensional arrays,
although the use of two-dimensional arrays is quite common also.

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

Dim cs As CardSuit = CardSuit.hearts


Console.Out.WriteLine(“The value cs is {0}”, cs)

Dim cr As CardRank = CardRank.queen


Console.Out.WriteLine(“The value cr is {0}”, cr)

Dim bUsed As Boolean


bUsed = deck(cs, cr)
Console.Out.WriteLine(“The value bUsed is {0}”, bUsed)

bUsed = deck(CardSuit.spades, CardRank.ace)


Console.Out.WriteLine(“The value bUsed is {0}”, bUsed)
128 Chapter 8: Arrays, Enumerations, and Structures

Console.Out.WriteLine(“Press the <Enter> key to end the program”)


Console.In.ReadLine()
End Sub

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)

Console.Out.WriteLine(“Press the <Enter> key to end the program”)


Console.In.ReadLine()
End Sub

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

Console.Out.WriteLine(“The value r.topLeft.x is {0}”, r.topLeft.x)


Console.Out.WriteLine(“The value r.topLeft.y is {0}”, r.topLeft.y)

Console.Out.WriteLine(“Press the <Enter> key to end the program”)


Console.In.ReadLine()
End Sub

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

There are many other issues related to declaring structures in addition to


what you have learned in this chapter. You will learn them as you get a
deeper understanding of the Visual Basic language and of some basic
object-oriented concepts.

Using the Structured Data Types


Arrays, enumerations, and structures can be grouped together under the
label structured types. They are custom and/or complex data types, based on
the fundamental data types.
Variables of these types can be declared and used in the same way as any
fundamental type variable can be used. There are some differences that
need to be understood before you proceed with your learning. One of the
most important is the way the assignment works between different vari-
ables of the same type.
In the case of fundamental data types, the assignment is said to occur by
value (ByVal). That means that when you assign an Integer variable i to
another Integer variable j, the compiler will copy the contents of the mem-
ory location that the variable i refers to into the memory location to which j
refers to.
Alternatively, the compiler could have the variable j refer to the same mem-
ory location as the variable i. This behavior is known as assignment by ref-
erence (ByRef) because the only thing that is assigned is the reference to a
new memory location, no values are copied as in the by value case. The
implication of this type of behavior is that, after an assignment by refer-
ence, modifying the value of the i variable will modify also the j variable
(because they both refer to the same location in memory).
It is very important to understand these two fundamental behaviors
because all data types in Visual Basic (and in the .NET Framework for that
matter) use one or the other. Figure 8.2 summarizes the two behaviors and
the preceding comments.
All the data types you have seen so far, with the exception of arrays, are
using ByVal behavior. The arrays use ByRef behavior. The following example
will illustrate this for some of the fundamental types, arrays, and struc-
tures. Create a new console project and name it AssignExample, and then
enter the following code:
Using the Structured Data Types 133

Memory locations before Memory locations after

Variable i 6 Variable i 6
ByVal Assignment: j = i
Variable j 0 Variable j 6

Memory locations before Memory locations after

Variable i 6 Variable i 6
ByRef Assignment: j = i
Variable j 0 Variable j

Figure 8.2: ByVal versus ByRef assignment behavior.

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)

Dim c1 As Card, c2 As Card


c1.name = “Video card”
c1.pcid = 0
c2.name = “Audio card”
c2.pcid = 6
Console.Out.WriteLine(“BEFORE c1.name is {0} and c1.pcid is {1}”, _
c1.name, c1.pcid)
Console.Out.WriteLine(“BEFORE c2.name is {0} and c2.pcid is {1}”, _
c2.name, c2.pcid)

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

Console.Out.WriteLine(“AFTER c2.name is {0} and c2.pcid is {1}”, _


c2.name, c2.pcid)

Dim a1() As Integer = {1, 2, 3, 4, 5}


Dim a2() As Integer = {6, 7, 8, 9, 0}

Console.Out.WriteLine(“BEFORE a1(3) is {0} and a2(3) is {1}”, _


a1(3), a2(3))
a1 = a2
a1(3) = -1
Console.Out.WriteLine(“AFTER a1(3) is {0} and a2(3) is {1}”, _
a1(3), a2(3))

Console.Out.WriteLine(“Press the <Enter> key to end the program”)


Console.In.ReadLine()
End Sub

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

2. An array element can be accessed by:


a. Its name.
b. Its index in the array.
c. Dot-notation using the array name followed by its index.
d. Specifying its position using an index for each dimension of the
array.
3. How many elements hold an array declared as Dim a(2, 3, 4) As
Integer?

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

a. It remains unchanged, it is a different array.


b. The value of A(0) is copied in B(0) too.
c. A(0) and B(0) refer to the same element, therefore they have the
same (changed) value.
d. A(0) and B(0) refer to the same element, but when assigned a
new value A(0) will be copied to a different memory location.
8. Array index values start at:
a. 0.
b. 1.
c. You define it when you declare the array.
d. 0 for fixed arrays, 1 for dynamic arrays.

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())

Console.Out.WriteLine(“Enter a value for j and press <ENTER>: “)


Dim j As Integer
j = CInt(Console.In.ReadLine())

If i < j Then
Console.Out.WriteLine(“i is less than j”)
End If

Console.Out.WriteLine(“Press the <Enter> key to end the program”)


Console.In.ReadLine()
End Sub

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

Figure 9.1: If example output 1.

If i is greater than or equal to j then the output will look like the one in
Figure 9.2.

Figure 9.2: If example output 2.

The conditional expression used in an If statement is a Boolean expres-


sion, and can be as complex as required. We recommend keeping it simple
and clear to improve the readability of your programs.
There is another (less common) form of the If statement that is sometimes
used, called a single-line If statement because it is written on a single line.
For distinction, the form we have used is called a block-If statement. You
could rewrite the If statement as:
If i < j Then Console.Out.WriteLine(“i is less than j”)

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.

Any statement can be placed in the block of statements inside a block-If


statement, including other If statements. If you had an If statement inside
another If statement, you would call the interior If statement nested. This
term is often used to indicate a construct or statement within other con-
structs or statements. You will encounter it later in the chapter when you
learn about loop statements.
What would happen with your example if you wanted to distinguish
between the case when i is equal to j and the other two cases? You would
need somehow to have the program branch in three cases: i is less than j, i
is equal to j, and finally i is greater than j. You can achieve this by using
The If Statement 145

another form of the If statement, presented in the following example.


Modify the code of the If to look like this:
If i < j Then
System.Console.Out.WriteLine(“i is less than j”)
ElseIf i = j Then
System.Console.Out.WriteLine(“i equals j”)
Else
System.Console.Out.WriteLine(“j is less than i”)
End If

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.

The Select Case Statement


The Select Case statement is used as a convenient replacement for an If
statement with a large number of ElseIf branches. Let’s write a simple
example to illustrate the use of a Select Case. Your task is to develop a
funny oracle that will guess the gender of the user, based on its first name.
Create a new console project and name it SelectCaseExample, and then
enter the code as shown in the following example.
Sub Main()
Console.Out.WriteLine(“I am the Oracle and I will guess your gender”)
Console.Out.WriteLine(“Enter your first name and press <ENTER>: “)
Dim s As String
s = Console.In.ReadLine()

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

Console.Out.WriteLine(“Press the <Enter> key to end the program”)


Console.In.ReadLine()
End Sub

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.

Figure 9.3: Select Case sample output.


148 Chapter 9: Control Statements

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

Console.Out.WriteLine(“Press the <Enter> key to end the program”)


Console.In.ReadLine()
End Sub

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

Console.Out.WriteLine(“Between 7 and 11, or >= 15”)


Case Else
Console.Out.WriteLine(“Other number”)
End Select

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

The <select-expression> is a placeholder for a numeric or String expres-


sion. You have one or more Case branches, each with its expression and set
of statements that will be executed if the expression matches the select-
expression. Optionally you have a Case Else branch (also known as a
default branch) that will be used if none of the case-expressions match the
select-expression.

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

The answer is yes, you could. It is entirely up to you which version of


branching you use; both the If and Select Case statements offer similar
functionality.
150 Chapter 9: Control Statements

The For Loop


You have seen how to selectively execute statements based on some condi-
tions. Another frequently used feature in programming is to repeat a group
of statements for different values of one or more variables. For example, to
sum all the values in an array of numbers into one variable, you could use
code like this:
Dim vals As Integer() = {1, 2, 3}
Dim total As Integer
total = vals(0) + vals(1) + vals(2)

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}

Console.Out.WriteLine(“Enter the start index and press <Enter>:”)


Dim index As Integer
index = CInt(Console.In.ReadLine())

If index < 0 Or 9 < index Then


Console.Out.WriteLine(“Invalid index, must be between 0 and 9”)
Console.Out.WriteLine(“Press the <Enter> key to end the program”)
Console.In.ReadLine()
End
End If

Dim i As Integer, total As Integer


For i = index To 9
total += vals(i)
Next
Console.Out.WriteLine(“The total value is {0}”, total)

Console.Out.WriteLine(“Press the <Enter> key to end the program”)


Console.In.ReadLine()
End Sub
The For Loop 151

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.

Figure 9.4: For loop sample output.

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

Dim i As Integer, j As Integer


For i = 0 To n – 1
For j = 0 To m – 1
‘ statements
Next
Next

But the code is not correct, and will not compile:


Dim i As Integer, j As Integer
For i = 0 To n – 1
For j = 0 To m – 1
‘ statements
Next i
Next j

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.

Using the Step


If you would like the counter to be incremented by two at each iteration of
a For loop, you would use Step 2. The following example illustrates a sim-
ple program that computes the sum of all odd numbers between 1 and 31:
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 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)

Console.Out.WriteLine(“Press the <Enter> key to end the program”)


Console.In.ReadLine()
End Sub

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

Figure 9.5: Do loop sample output.

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

This can be written better as:


Do While Not <condition>
‘ any statements
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

The Do loop can also be written using a slightly different form:


Sub Main()
Dim sContinue As String

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)

can be rewritten as a Do loop:


Dim i As Integer = 1, t As Integer
Do While i <= 31
t += i
i += 1
Loop
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.

The While Loop


The While loop is a less used variation of the Do loop, and was maintained
in the language mostly for historical reasons (in our opinion). It is totally
superseded in functionality by the Do loop. We will present it for complete-
ness, but recommend that you do not use it.
The formal syntax is
While <conditional-expression>
<statements>
End While

The last example could be re-written using a While loop as shown:


Dim i As Integer = 1, t As Integer
While i <= 31
t += i
i += 1
End While
Console.Out.WriteLine(“The final value of t is {0}”, t)

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

Another important thing to remember is that the While loops cannot be


exited using an Exit Do statement. There is no equivalent Exit While. This
means an infinite While loop cannot be exited, short of interrupting the pro-
gram in some fashion. You will learn about this later on in the book.

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

3. The Select Case is by far more efficient (in terms of performance)


than an If statement with many ElseIf branches.
True/False
4. A For loop can be executed 0 times.
True/False
5. A Do loop can be executed 0 times regardless of the Do format used.
True/False
6. It is better to use an Exit Do and Exit For to exit a loop than to spec-
ify a clear loop termination condition.
True/False

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.

Introduction to Structured Programming


As you have seen in the previous chapters, a software program consists of a
sequence of statements that the computer executes. There is a start point
(the first statement that will be executed) and an end point (the last state-
ment of the program). In the Visual Basic examples you have seen so far,
the start point is the Sub Main statement and the end point is the End Sub
statement. The statements between the start and end points are executed
sequentially. The currently executing statement is known as the current
statement or the execution point. You have seen that there are statements
that allow you to control which statements are executed (the branching
statements, like If and Select Case) and statements that allow you to
repeat some statements a number of times (the loop statements, like For
and Do). These statements are, in effect, controlling the execution flow of
the program by determining which statement gets to be executed next
based on some specific criteria that you supply.
There are cases when a program must be split into smaller units, called
procedures, which execute a specific task. The reasons to split a program
are that a program could become too large to understand and, most impor-
tantly, there may be parts of a program that do the same (or a very similar)
task, over and over. If you have a procedure that is able to execute a spe-
cific task, you could call this procedure every time that task needs to be
executed. The alternative would be to write the code for that task in every
place in your main program where this task needs to be executed. Let’s
take an example to illustrate better what we have described so far.
Module Module1
Sub Main()
Dim vals() As Integer = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}

Console.Out.WriteLine(“Enter the start index and press <Enter>:”)


Dim index As Integer
index = CInt(Console.In.ReadLine())

If index < 0 Or 9 <= index Then


Console.Out.WriteLine(“Invalid index, must be between 0 and 9”)
Console.Out.WriteLine(“Press the <Enter> key to end the program”)
Console.In.ReadLine()
Introduction to Structured Programming 167

End
End If

Dim i As Integer, total As Integer


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)

Console.Out.WriteLine(“Press the <Enter> key to end the program”)


Console.In.ReadLine()
End Sub

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}

Console.Out.WriteLine(“Enter the start index and press <Enter>:”)


Dim index As Integer
index = CInt(Console.In.ReadLine())

If index < 0 Or 9 <= index Then


Console.Out.WriteLine(“Invalid index, must be between 0 and 9”)
WaitForEnter()
168 Chapter 10: Subroutines and Functions

End
End If

Dim i As Integer, total As Integer


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)
WaitForEnter()
End Sub

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}

Console.Out.WriteLine(“Enter the start index and press <Enter>:”)


Dim index As Integer
index = CInt(Console.In.ReadLine())

If index < 0 Or 9 <= index Then


WaitForEnter(“Invalid index, must be between 0 and 9”)
End
End If

Dim i As Integer, total As Integer


For i = index To 9
total += vals(i)
Console.Out.WriteLine(“The total value is {0} at i = {1}”, _
total, i)
Next
WaitForEnter(“The final total value is “ & CStr(total))
End Sub

Sub WaitForEnter(ByVal message As String)


Console.Out.WriteLine(message)
Console.Out.WriteLine(“Press the <Enter> key to end the program”)
Console.In.ReadLine()
End Sub

End Module
Subroutines 171

You have modified the Sub WaitForEnter to accept an argument. An argu-


ment is a variable that is declared on the subroutine declaration line, and
which will have its value allocated by the caller of this subroutine. In your
case the argument is named message and it is of type String (like any other
variable it must have a type). The keyword ByVal in front of the variable
name indicates how is the value passed—we will return to this shortly. The
caller of the subroutine is said to be the subroutine that invoked this one
(Sub Main here).
Inside the subroutine you can use the argument (sometimes called formal
argument) as you would use any normal variable. In your case you will out-
put it to the console, using the Console.Out.WriteLine().
The definition of your subroutine now includes one argument of type
String. This definition is called the signature of the subroutine, and tells
the potential callers how this subroutine should be called. Because you
have an argument of type String, the caller must provide a value for this
argument whenever it makes the subroutine call. You have modified the
calls to the subroutine WaitForEnter to provide the String value required.
In one case you supply the String “Invalid index, must be between 0 and
9”, to let the user know what went wrong. In the other case you use a
String expression resulted by concatenating the literal String “The final
total value is “ with the value of the total variable converted to String.
At runtime the compiler will take the value and, when starting the subrou-
tine WaitForEnter, will pass it as the value of the argument message. The
values passed to a subroutine are known as parameter values, or in short
parameters.

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.

Multiple Arguments and ByVal versus ByRef


You have seen how to define a subroutine with one argument. In many
cases you will find that you need to pass two or more values to a subrou-
tine.
The argument list of a subroutine is defined as the sequence of arguments
between the ( (open parenthesis) and ) (close parenthesis) that follow the
172 Chapter 10: Subroutines and Functions

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())

Console.Out.WriteLine(“Enter a value for j and press <Enter>:”)


Dim j As Integer
j = CInt(Console.In.ReadLine())

Console.Out.WriteLine(“In Main before calling Add. j is {0}”, j)


Add(i, j)
Console.Out.WriteLine(“In Main after calling Add. j is {0}”, j)
WaitForEnter(“The final value of j is “ & CStr(j))
End Sub

Sub Add(ByVal i As Integer, ByVal j As Integer)


Console.Out.WriteLine(“In Add before addition. j is {0}”, j)
j += i
Console.Out.WriteLine(“In Add after addition. j is {0}”, j)
End Sub
Subroutines 173

Sub WaitForEnter(ByVal message As String)


Console.Out.WriteLine(message)
Console.Out.WriteLine(“Press the <Enter> key to end the program”)
Console.In.ReadLine()
End Sub

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.

Figure 10.1: Sample output for ByVal.

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())

Console.Out.WriteLine(“Enter a value for j and press <Enter>:”)


Dim j As Integer
j = CInt(Console.In.ReadLine())

Console.Out.WriteLine(“In Main before calling Add. j is {0}”, j)


Add(i, j)
Console.Out.WriteLine(“In Main after calling Add. j is {0}”, j)
WaitForEnter(“The final value of j is “ & CStr(j))
End Sub

Sub Add(ByVal i As Integer, ByRef j As Integer)


Console.Out.WriteLine(“In Add before addition. j is {0}”, j)
j += i
Console.Out.WriteLine(“In Add after addition. j is {0}”, j)
End Sub

Sub WaitForEnter(ByVal message As String)


Console.Out.WriteLine(message)
Console.Out.WriteLine(“Press the <Enter> key to end the program”)
Console.In.ReadLine()
End Sub

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

Figure 10.2: Sample output for ByRef.

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.

Next you will look at a special form of procedures called functions.

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())

Console.Out.WriteLine(“Enter a value for j and press <Enter>:”)


Dim j As Integer
j = CInt(Console.In.ReadLine())
176 Chapter 10: Subroutines and Functions

Dim sum As Integer


sum = Add(i, j)
WaitForEnter(“The value of i + j is “ & CStr(sum))
End Sub

Function Add(ByVal i As Integer, ByVal j As Integer) As Integer


‘ Add i to j and return the result
Return j + i
End Function

Sub WaitForEnter(ByVal message As String)


Console.Out.WriteLine(message)
Console.Out.WriteLine(“Press the <Enter> key to end the program”)
Console.In.ReadLine()
End Sub

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())

Console.Out.WriteLine(“Enter a value for j and press <Enter>:”)


Dim j As Integer
j = CInt(Console.In.ReadLine())

Dim sum As Integer


sum = Add(i, j)
WaitForEnter(“The value of i + j is “ & CStr(sum))
End Sub

Function Add(ByVal i As Integer, ByVal j As Integer) As Integer


Dim sum As Integer
sum = i + j

‘ if sum is negative return 0


If sum < 0 Then
Return 0
End If

‘ Otherwise return the sum


Return sum
End Function

Sub WaitForEnter(ByVal message As String)


Console.Out.WriteLine(message)
Console.Out.WriteLine(“Press the <Enter> key to end the program”)
Console.In.ReadLine()
End Sub

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

‘ if sum is negative return 0


If sum < 0 Then
Add = 0
Exit Function
End If

‘ Otherwise return the sum


Add = sum
End Function

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

Scope and Lifetime


The scope of a variable is the part or parts of the program in which a vari-
able can be accessed by code. It is also known as the visibility of the vari-
able. When we say that a variable is visible in a specific procedure, for
example, we say that the code in that procedure can access the variable.
We can also say the scope of the variable is that procedure—and mean the
same thing. We are going to use both terms in the rest of this book.
Normally the scope of any variable declared with Dim inside a subroutine or
function is from the line following its declaration, up to the end of the subrou-
tine or function. These variables are known as local variables. However, the
scope is not extended to the code before the declaration (Dim) line. For example:
Sub Main()
‘ code before the declaration cannot use i
Dim i As Integer = 0
i = 5

‘ any code after the declaration can access i
End Sub

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

This modification (adding = 0 to the declaration of j) will ensure the value


of j is set to 0 for each iteration of the loop.
In short, if a variable is declared inside a block statement that is inside a
subroutine or function, the compiler will allocate memory for it when the
subroutine or function is entered (and not every time the loop is executed,
as it may appear). That memory will not be initialized until the block state-
ment where the variable is declared is entered. If an explicit initialization
is provided, this will be executed every time the block statement (loop) is
executed. Do not worry if this seems complicated. Your code will be all right
if you declare variables at the subroutine level and not inside loops.
Scope and Lifetime 181

Module Level Variables and Constants


So far you have seen variables declared inside subroutines and functions.
However, there are cases when a variable must be accessed by more than
one subroutine or function in a given module. This is especially the case
with constant values. A constant value (abbreviated as constant) is a special
type of variable that is declared and initialized, but which cannot be modi-
fied after this declaration. Constants are useful to represent values that do
not change during the execution of the program. For example, a program
that would deal with trigonometric calculations will use the value π a lot.
Instead of using the numeric approximate value 3.141592 in every expres-
sion that use π, a smart programmer would define a constant value for it,
and use that value in the whole program. The declaration must be placed at
module level:
Module Module1
Public Const PI As Double = 3.141592
Sub Main()
‘ any code can use PI
End Sub
End Module

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

If a constant is only accessed by procedures from this module, it is better to


declare it as Private, as in the next example:
Module Module1
Private Const PI As Double = 3.141592
Private outputBuffer As String
Sub Main()
‘ only code in this module can use PI
‘ code in this module can use and
‘ modify outputBuffer
End Sub
End Module

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

Argument Visibility and Lifetime


The same rules that apply to variables and constants apply to the argu-
ments to subroutines and functions. An argument is visible in the proce-
dure in which it is declared, and its lifetime is the same as the lifetime of
the procedure. The compiler will allocate the memory for it when the proce-
dure starts and will de-allocate the memory when the procedure finishes
execution. This applies to arguments that are passed by value.
In the case of the arguments that are passed by reference, the actual value
will exist as long as the caller of the procedure has a variable that refers to
it, potentially long after the procedure has finished execution.
It is important to remember that there is a relationship between the type of
the argument (by value or by reference) and the effect of the ByVal and
ByRef argument modifier. If the argument data type is of by-value type,
either ByVal or ByRef can be used and they will have the expected behavior.
However, in the case of data types that are by-reference, the ByVal modifier
has no influence whatsoever. They will always be treated by value.
Consider the following example:
Module Module1
Structure Test
Public x As Double
End Structure
184 Chapter 10: Subroutines and Functions

Sub Main()
Dim o As Test
o.x = 4
TestS(o)
Console.Out.WriteLine(o.x)

Dim a() As Integer = {1, 2, 3}


TestA(a)
Console.Out.WriteLine(a(2))
End Sub

Sub TestS(ByRef o As Test)


o.x = 6
End Sub

Sub TestA(ByVal a() As Integer)


a(2) = 7
End Sub

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

Dim c() As Integer = CopyArray(a, 4)


Dim d() As Integer = CopyArray(a, 4, 9)
‘ c and d are now identical clones of elements 4-9 of a
End Sub

‘ This function will make a copy of the elements from


‘ the array of Integers a() passed in, starting at
‘ startAt position, up to endAt position
‘ If endAt is not specified, will copy to the end of the array
Function CopyArray(ByRef a() As Integer, _
ByVal startAt As Integer, _
Optional ByVal endAt As Integer = -1) As Integer()
If endAt < 0 Then
endAt = a.Length() - 1
End If

‘ Determine the size of the new array


Dim n As Integer
n = endAt - startAt + 1
If n <= 0 Then
Return Nothing
End If

‘ Create the new array


Dim cpy() As Integer = New Integer(n) {}

‘ Copy elements from a to the cloned array cpy()


Dim i As Integer
For i = 0 To n - 1
cpy(i) = a(startAt + i)
Next

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 third argument of the function is preceded by the specifier Optional,


which indicates that the value may be specified or not when the function is
called. You need to provide a default value for the argument—this is the
value that the argument will have if no other value is specified. We have
chosen –1; this is also an invalid value, therefore it is easy to determine in
the function body if a value was supplied for the argument or not.
The logic of the function is simple. First determine if the optional argument
endAt has a valid value. If not, set its value to be the last element of the
array (which is the length of the array minus 1). Then you determine the
number of elements to copy in the new array (its size), and allocate it using
the syntax that you have seen in the previous chapters.
Finally you use a For loop to copy each element from position startAt + i of
the source array a into the cloned array cpy at position i. You then return
the cpy array as the return value of the function.
In Main you create a source array a, and initialize its elements. Then you
call the CopyArray function twice, once specifying the optional argument,
once not specifying it, to illustrate that your code works.
We leave it as an exercise for you to add trace statements to ensure the
results are correct.
There are a few rules involving optional arguments:
• If you have only one optional argument, it must be the last argument
in the list.
• If you have more than one optional argument, all the arguments after
the first optional argument must also be optional. Optional arguments
are always grouped at the end of the argument list.
• A default value must be specified for all optional arguments.
• There are some restrictions on what the optional argument types can
be (for example, structures cannot be used as optional arguments). You
will learn a few more in the next few chapters.

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

Visibility of Procedures and Functions


The Public and Private modifiers also can be applied to subroutines and
functions, with similar effects as for the module-level variables and con-
stants. A public procedure is visible outside the module—that means that
anyone who can see the module can call that procedure. In contrast the pri-
vate subroutines and functions can only be called from the module in which
they were declared. By default subroutines and functions in modules are
Public. The following example illustrates this.
Module Module1

Sub Main()
‘ code
End Sub

Public Sub PublicSub()


‘ can be called from other modules
End Sub

Private Sub PrivateSub()


‘ cant be called from other modules
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

3. What can you say about the return value of a function?


a. Cannot be an array.
b. Cannot be a structure.
c. Must be a fundamental data type.
d. Can be any data type.
4. If private function F of module Module1 has an argument named arg,
its scope (visibility) is:
a. The body of F.
b. The body of Module1.
c. Neither; being a private function no one can access its argu-
ments.
d. Both a and b.
5. What is the lifetime of a regular variable declared inside a For loop?
a. The loop.
b. The subroutine containing the loop.
c. The whole project.
d. Being a local variable of the loop has no lifetime.
6. If an array is passed to a function using ByVal, and one of the array
elements is modified inside the function, which of the statement(s) is
true?
a. The local copy of the array is modified; the original array from
the caller is not affected.
b. Both copies are modified and kept in synch by the compiler.
c. The ByVal is ignored for by-reference types, therefore there is
only one instance of the array (and it is modified).
d. No modifications are made to the array until the function
returns.
7. An optional argument is:
a. An argument that can be omitted when the function is called.
b. An argument that has optional semantics, either by-value or by-
reference.
190 Chapter 10: Subroutines and Functions

c. A hint for the compiler to optimize the passing of this argument.


d. All of the above.

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

You will start by understanding the basic concepts of debugging a program


(what is debugging and why do you need it), and then you will learn the
fundamentals: how to step through code, set breakpoints, look at the value
of variables, and more.
Next you will learn what errors and exceptions are and what are the mech-
anisms the .NET Framework provides to describe and deal with exceptions.
You will look at examples of how to deal with exceptions in a structured
manner.
In the last part of this chapter you will look briefly at the older (unstruc-
tured) method for exception handling.
194 Chapter 11: Introduction to Debugging and Exception Handling

Preparing to Debug a Program


A “bug” in programmer dialect is a code defect that can cause anomalous
behavior. Bugs are normally caused by errors in the code; for example, you
type + when you actually meant to type *. This would result in addition
instead of multiplication and a totally different result from what you had
expected. Other bugs are cause by mistakes in the program logic (the algo-
rithm that underlies your program). An algorithm is a series of steps that
are required to execute a task. These steps are (in your case) statements
that a computer can execute.

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).

A bug, therefore, is an error in the algorithm. The process to eliminate


these bugs is called debugging. You may think that careful planning and
analysis of the algorithm before coding (a process that is called analysis
and design) can eliminate all the bugs. Although it is certain that a good
analysis and design phase will reduce (sometimes drastically) the number
of bugs in a program, it is also proven that for any real-life program no
amount of analysis and design can eliminate all the bugs, as anyone work-
ing in the software industry will tell you. That is the reason that you need
to learn to debug programs.
It turns out that the debugging process can be helped a lot by a good debug-
ging tool. Microsoft’s Visual Studio .NET is such a tool—it is very good in
helping you eliminate the bugs from your code, as you will see shortly.
Historically, debugging was performed by executing the program in a test
environment and comparing the actual output of the program with the
expected output, for as many sets of input variables as possible. For exam-
ple, if you had a program to compute the exponential of a decimal number,
you would try as many combinations of numbers and exponents as possible,
with care to ensure the limits of the domains were tested—0, 1, and very
large numbers. The issue with this approach is that the expected output
was quite often computed by hand, and if it failed, it was hard to say what
caused the failure.
To help this process, the programmers started using trace statements.
Trace statements are simply outputting the values of some of the important
variables at some crucial points in the execution of the program, so that the
programmer can then look at them and determine the cause of a bug. This
Stepping through Code 195

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.

Stepping through Code


The modern debuggers (normally integrated with the IDE) are much better
than this. As you will see shortly, they will allow you to step through your
program (execute one statement at a time) and look at the values of vari-
ables. Also the debugger will allow you to set breakpoints, which are state-
ments in your programs that you mark and tell the debugger to suspend
program execution when it gets there, so that you can have a look at what
is happening. Let’s try an example. Create a new console project and enter
the code as shown:
Module Module1

Sub Main()
Dim a() As Integer = {1, 6, 6, 9}

Dim s As String = “The array has “


s += CStr(Count6es(a))
s += “ elements that have a value of 6”

Console.Out.WriteLine(s)
End Sub

‘ This function will count all sixes in ints(), and return it


Private Function Count6es(ByRef ints() As Integer) As Integer
Dim count6 As Integer = 0 ‘ sixes counted so far
Dim n As Integer = ints.Length() ‘ array size
Dim i As Integer ‘ loop counter
For i = 0 To n - 1
If ints(i) = 6 Then count6 += 1
Next
Return count6
End Function

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.

Red dot Run icon

Figure 11.1: Setting a breakpoint.

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.

Figure 11.2: Stop at the breakpoint.

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

Figure 11.3: Stepping through code.

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

Figure 11.4: Stepping into the function.

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.

Figure 11.5: Debugging the function.

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

Figure 11.6: Quick watch of an expression.

Figure 11.7: The watch window.

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 summary of the main functions and commands of the debugger.


You will learn a few more advanced techniques later on in the book.

Structured Exception Handling (SEH)


The errors in a software program can be classified as syntax errors, runtime
errors, and logical errors.
The syntax errors are caught by the compiler and signaled by the IDE. You
are by now familiar with the underlining of an undeclared variable name or
invalid expression with the blue line. If you keep the mouse cursor hovering
over the respective expression, the actual error message will be shown. The
errors are also shown in the output window (at the bottom of the Visual
Studio .NET IDE) when you try to compile a program with syntax errors.
The runtime errors (most commonly known as exceptions) are problems that
arise when the program is executed. For example, let’s assume that you
have a statement like:
result = x / y

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

If your code is prepared to handle the exception, the appropriate handler is


called. You will look at what the exact meaning of this statement is in the
next example. To be prepared to deal with an exception you need to use a
special language construct, named a Try-Catch statement.
Module Module1
Sub Main()
Dim i As Integer = 5
Dim j As Integer = 0 ‘ Explicit
Dim result As Integer

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

This changes the example so that now it will handle a DivideByZeroException,


as well as any other type of exception. The Catch e As Exception is a generic
catchall. When an exception is thrown, the runtime will check the Catch
clauses in the order they are in code. If it finds a Catch block for the type of
exception being thrown, it will execute it; otherwise it will continue the search
with the next Catch. In your example, the following statement will cause what
is known as an overflow exception—an attempt to assign to a type a value
that is larger than it can store:
result = Integer.MaxValue * i

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

Function MultiplyInts(ByVal i As Integer, ByVal j As Integer) As Integer


Dim result As Integer
result = i * j
Unstructured Exception Handling 207

Return result
End Function
End Module

The function MultiplyInts is used to illustrate how exceptions are propa-


gated on the call stack. If passed invalid (too large) values, the statement
result = i * j will throw an exception. The function does not have a Try-
Catch statement that will deal with the error. The runtime will look at the
procedure that called this function and check whether it does have a Try-
Catch statement that will handle this type of exception. If it does, the
appropriate Catch block in the calling procedure will be called. This is the
case with our example.
Fundamentally the rule is this: The runtime will look on the call stack for
the first suitable handler (a Catch that can handle the type of exception
being thrown). It will start with the top of the stack (the currently execut-
ing procedure) and move down the stack to the caller, until it can find a
suitable handler. If none can be found the program is terminated (or in
Debug mode a dialog box will inform you of an unhandled exception).
You have learned the basis of structured exception handling. We will come
back to exception handling later on, after you learn about classes and
objects.

Unstructured Exception Handling


This section will explain the older technique of dealing with exceptions,
used in previous versions of Visual Basic. We strongly recommend that you
use the structured exception handling (Try statements) as you just learned.
This section is included for those who need to understand or migrate pro-
jects from previous versions of Visual Basic.
In Visual Basic there is a unique global object named Err. You can think of
this as being a public variable of a special structure type. This object repre-
sents the last exception that has occurred anywhere in the program. It has
a number of properties (fields), among which the most important are the
Number and Description of the exception. We will explain what these are
soon.
When an exception occurs, the runtime will set the properties for this
object. Then it will look for an active error handler. An error handler is a
statement that tells the runtime what to do if an error occurs in a portion
of code. Note that this is different from an exception handler (the Catch
block). The most commonly used one is On Error GoTo <label> as illus-
trated here:
208 Chapter 11: Introduction to Debugging and Exception Handling

Module Module1
Sub Main()
Dim i, j As Integer

On Error Goto Main_Failed


i = i \ j
Exit Sub

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

The On Error GoTo 0 statement is used to disable error handling. It also


clears the Err object, resetting all its properties to blank (empty) values. It
is used to disable a previous On Error.
Although the preceding mechanism may appear to offer slightly more func-
tionality than the structured handling of exceptions, programming practice
proved the Try-Catch blocks to be easier to use and more solid. We strongly
recommend that you use the Try-Catch blocks whenever possible.

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

c. Since no handler is available, the runtime will ignore it and


continue.
d. a or b depending whether the IDE is available.
6. If an exception occurs in a function with no SEH, but its caller has a
Try-Catch block, what is the outcome?

a. The program is terminated (or stopped if in the IDE).


b. The exception is caught by the handler in the caller.
c. The exception is caught by the handler in the caller, but only if
the caller has the appropriate handler type and the function was
called from within the Try block.
d. A trace message is outputted to the console, and the program
ends.

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

To help you better understand the structure of an application, we also give


a succinct overview of the development life cycle for a software product.
Then you will look at an example of an assembly and its properties in
detail. Next you will look at what a namespace is and some examples. You
will also build a more complex example that consists of two projects, one
project (client) using the other project’s procedures and functions (server).
This will illustrate the use of the Namespace and Imports statement.
In the final part of the chapter you will look at some of the commonly used
namespaces that come with the .NET Framework and Visual Studio .NET.
216 Chapter 12: Microsoft .NET Framework—Assemblies and Namespaces

Software Development Life Cycle


A software product is the final goal of software development, and it is an
application that a user can interact with to resolve a specific problem (or
set of problems). As a very simple example you have the venerable Notepad
application, which can be used to read or write simple text from or to com-
puter files. A complicated example would be a distributed application with a
Web front-end and mobile clients, with Web and application servers, using
several heterogeneous databases and legacy systems (mainframes) as a
back-end.
An application’s user(s) do not have to be human(s); the term user can also
include non-human users such as other applications. This is quite common
actually, because most applications use the services offered by other exist-
ing applications. This is done mostly to save work and not reinvent the
wheel. For example, Notepad uses the graphical and text services (func-
tions) offered by some system-level libraries to draw its window and
manipulate the text, fonts, and so on. The whole idea behind software
development is reusing the existing services and combining them to solve
a problem and create new functionality.
The software development is the process of creating one of these applica-
tions. It normally goes through a series of steps (phases):
• Analysis—This is the process of gathering the requirements about the
application (defining what the input and output should be).
• Design—Drawing the blueprints for the application, (determining
structure and how different parts are interacting with one another).
Normally a modeling tool is used. Most modern tools are based on the
Unified Modeling Language (UML).
• Development—Build all components that make up the application and
link them together. This is the part upon which you are concentrating.
• Testing—Make sure the application performs as required in as many
cases as possible. Unfortunately the importance of this step is very
often overlooked.
• Deployment—Provide the means to install and configure the applica-
tion on the user’s computer. This step is also quite often ignored.

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

concentrate on development—the actual implementation of the design, but


you will use some elements of design, especially in the next few chapters.

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.

Figure 12.1: Assembly example project.


218 Chapter 12: Microsoft .NET Framework—Assemblies and Namespaces

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.

Figure 12.2: Properties of a referenced assembly.

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

Figure 12.3: Assembly common properties—General.

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

Figure 12.4: Assembly common properties—Build.

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

Figure 12.5: Assembly configuration-specific properties—Debugging.

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.

Figure 12.6: Assembly configuration-specific properties—Optimizations.

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

Figure 12.7: Assembly configuration-specific properties—Build.

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

components of an assembly. For large projects the number of these compo-


nents can be quite large. To ease the use of these components by further
grouping them into smaller categories, a new construct was introduced. It
is known as a namespace. A namespace is a group of components that are
somehow related. These components can be type declarations, constants,
procedures, functions, classes, and so on.
Namespaces also resolve naming ambiguity issues with which program-
mers in older languages were confronted. Let us assume your program uses
an external function called WriteError to log an error to a file. Let’s further
assume that this function comes from a software library called A. You will
add to your application a reference to A, and the function WriteError
becomes available to your application. At some point you decide to extend
the functionality of your program, and you need to add another reference to
another software library B (for example to gain access to some mathemati-
cal routines). It just so happens that the developer of B decided to define its
own function WriteError. At this point your program will not build properly
because the compiler will not know which function WriteError you refer to
when calling it: the one in A or the one in B.
The namespaces resolve this problem by allowing you to call either func-
tion, if they are grouped in a namespace. The next example will illustrate
the concept of namespaces and their usage. You will construct two console
projects, NamespaceExample and NamespaceExampleClient. The latter is using
the services of the former. Follow these steps to create the two projects:
1. First create a new console project and call it NamespaceExample.
Change the default name of Module1 to ModMain in the code. Then
change the name of the file from Module1.vb to Main.vb in the proper-
ties window. Figure 12.8 illustrates this step completed.
We will explain shortly why the names of the module and file were
changed.
2. Now change the code in Main.vb to look like this:
Namespace NSEx1

Public Module ModMain

Sub Main()
‘ test the two methods
Println(“A test”)
NSEx2.Println(“A test”)
End Sub

‘ Write the message to the console


Public Sub Println(ByVal message As String)
224 Chapter 12: Microsoft .NET Framework—Assemblies and Namespaces

Console.Out.WriteLine(message)
End Sub

End Module

End Namespace

Namespace NSEx2

Public Module ModAux

‘ 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

Figure 12.8: Namespace example—step 1.


Namespaces 225

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.

Figure 12.9: Namespace example—step 2.

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.

The second namespace is named NSEx2 (standing for NameSpace Example


2) and it contains one module named ModAux.
226 Chapter 12: Microsoft .NET Framework—Assemblies and Namespaces

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

components with a qualified name. The next example illustrates how to do


this:
Imports NamespaceExampleLib
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()

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

The System.Collections namespace contains the definitions for the most


commonly used collection classes, such as arrays, lists, hash-tables, indexed
lists, queues, stacks, and so on.
The System.Data namespace deals with data manipulation when interact-
ing with external data storage, normally with databases. It is the place for
the ADO.NET classes, and it has some namespaces of its own.
System.Diagnostics is useful for debugging, testing, and performance-
monitoring tools. It has classes that deal with debugging, tracing exception
logging, and others.
System.DirectoryServices provides easy access to Active Directory ser-
vices.
System.Drawing is mainly used to access the graphics functions of
Windows. It has classes used to draw lines, fonts, and images, as well as
help with printing and 2D drawing.
The System.IO classes are used to develop applications that read from and
write to streams. A stream can be a file, a network connection, an array of
bytes, the console, and so on.
System.Messaging and System.Net provide components that enable pro-
grams to communicate with other programs on different machines using
messages and network protocols.
The namespace System.Runtime contains components designed for run-
time support. It contains other specialized namespaces for remoting, serial-
ization, compiler, and interoperability services.
The System.Security namespace is designed to provide security and cryp-
tography services to Visual Studio .NET applications.
System.Text is designed for parsing, encoding, and decoding of text
streams, and together with the System.Xml namespace is used to handle
XML documents.
System.Threading and System.Timers offer access to operating system-
level functions regarding thread handling and timer components.
The System.Web is used to offer a variety of components that will be
needed to develop and deploy Web-enabled applications.
And finally the System.WinForms namespace is the basis for the user
interface developed in Visual Basic .NET and one that you will study in
great detail.
Reviewing It 231

Another namespace that is very useful in Visual Basic .NET is the


Microsoft.VisualBasic namespace. This namespace contains a large number
of useful enumerations that most programmers familiar with older versions
of Visual Basic will recognize. It also contains some useful structures and
global functions. You will encounter these in most sample projects from
now on.

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

Working with Objects


Objects and Classes—Introduction to Object-Oriented Programming
Properties
Methods
Static Class Members
Inheritance
Interfaces
Collections
Advanced 00 Topics
13
Objects and Classes—Introduction to
Object-Oriented Programming
This chapter presents the fundamental concepts that constitute the basis of
object-oriented programming (OOP). The chapter is broken down into the
following topics:
• Introduction to objects and classes
• Defining a class in Visual Basic .NET
• Class fields
• Class constructors

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

Introduction to Objects and Classes


You have seen in Part II, “Language Basics,” how programming languages
evolved from assembler to object-oriented languages. We have not explained
then what exactly is an object-oriented programming language. You will
learn this in this chapter and in Part III.
We all know what an object is in day-to-day life: a rock found on the beach,
the oak tree in front of the house, or Bucefalus—the horse of Alexander the
Great. All these are examples of objects, each one of them having its own
characteristics, quite different from those of other objects. We can speak of
an object to someone who has never seen it and still convey an idea of what
that object looks like. For example, I have never seen Alexander’s horse
(nor have you, probably), but reading the description made by one of his
historians, you will have an idea on what Bucefalus looked like. The image
of Bucefalus will form in your mind, based on what you know about horses
from your own experiences plus the description made by the historian,
which details what special characteristics Bucefalus had. That is, you use
your general knowledge of horses and the particular information about this
specific horse (that which distinguishes him from other horses) to construct
your representation of Bucefalus.
This general/particular combination is a very powerful mechanism of trans-
mitting information. It is considered to be one of the fundamental mecha-
nisms that underlie the language (symbolic representation) used by
humans. A similar mechanism (but far more simplistic) is used by the
object-oriented (OO) programming languages.
The general information about a specific set of objects is known as a class.
In your example you know there is a type of objects named horses, which
have four legs, a head, a tail, are used for riding, and so on. If you collect
all the information common to all horses and group this information under
the abstract name of horse, you have an idea what a class is. Horse is then
the generic name for any member of the set of all particular horses.

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).

A class is a way of grouping objects that share a number of characteristics:


attributes (like name, color, height, weight, etc.) and behavior (such as abil-
ity to perform jumps, to run, to swim, etc.). All objects in the class horse
will have an attribute named height, for example. That means that all
objects in that class have a height—the value of the attribute height will be
different for each instance of the class (i.e., for each particular horse). This
is a very important concept that you need to understand: All instances of a
class (objects) have all the attributes defined by the class. Each individual
object has its own value(s) for these attributes.
Formally a class is a set of objects that share a common data structure and
behavior. An object is a data structure (also known as state) and the behav-
ior associated with it.
You will notice in the rest of this chapter that there are similarities
between structures and classes in Visual Basic .NET. We will discuss these
similarities, as well as differences between classes and structures, in the
next two chapters, after you learn about methods and behavior.

Defining a Class in Visual Basic .NET


A class is a user-defined data type. Its declaration is similar to the declara-
tion of structures. You can declare it as part of a module; however, due to
the fact that classes tend to be much larger (have more lines of code) than
structures, they are usually declared in separate files (using the same .vb
extension).
240 Chapter 13: Objects and Classes

Create a new console project and give it the suggestive name


ClassExample1. From the Project menu select Add Class and change
the filename from Class1.vb to Horse.vb. Enter the lines of code shown in
bold in the following example:
Public Class Horse
Public m_name As String
Public m_color As String
Public m_height As Single
End Class

This is a class definition. Apparently there are no major differences


between a class and a structure (except the keyword Class, which replaces
Structure). A class can have fields, which have the same semantics as the
fields in structures. In this example you have three public fields m_name,
m_color, and m_height.

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

Public Class Horse


Public m_name As String
Public m_color As String
Friend m_height As Single
End Class

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

Figure 13.1: Class Horse representation in UML.

The attributes in UML correspond (roughly) to your fields. The convention


to indicate the type of an attribute is to use notation like
attributeName : TypeName

That means that the attribute name attributeName is of type TypeName. We


will be using this notation for examples throughout the book. In addition
to this, the following symbols are used to denote the visibility of an
attribute:
• + is used to indicate Public visibility
• # is used to indicate Protected visibility
• - is used to indicate Private visibility
Class Fields 245

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

CardSuit is assumed to be an enumeration, similar to the one you used ear-


lier in the book. It is important to note that an array of objects must be pop-
ulated in a different way than one of structures. For example in this case
you will need code to create the array (which is itself an object, as you will
see later) and then to create each object and assign it to the array elements.
By default the array elements are Nothing when first created. For example,
to initialize your list of Horse object, you need to follow these steps:
m_list = new Horse(2) {} ‘ create the array
m_list(0) = New Horse() ‘ create the first horse object
m_list(1) = New Horse() ‘ create the second horse object

The fields of a class can be initialized to a default value, as shown for


m_suit in the previous example and the m_height in the next example:
Public Class Horse
Public m_name As String
Public m_color As String
Friend m_height As Single = 1.5
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

Dim h As Horse = New Horse()


Console.Out.WriteLine(“Height of h is {0}”, h.m_height)
End Sub
End Module

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

Console.Out.WriteLine(“Name is {0}”, h.m_name)


Console.Out.WriteLine(“Color is {0}”, h.m_color)
Console.Out.WriteLine(“Height is {0}”, h.m_height)
End Sub
End Module

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

Public Sub New(ByVal name As String, _


ByVal color As String, _
ByVal height As Single)
m_name = name
m_color = color
m_height = height
End Sub
End Class
Class Constructors 247

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)

Console.Out.WriteLine(“Name is {0}”, h.m_name)


Console.Out.WriteLine(“Color is {0}”, h.m_color)
Console.Out.WriteLine(“Height is {0}”, h.m_height)
End Sub
End Module

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

Public Sub New(ByVal name As String, _


ByVal color As String, _
ByVal height As Single)
m_name = name
248 Chapter 13: Objects and Classes

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()

Figure 13.2: Class Horse representation in UML (version with constructor).

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.

Both examples will be illustrated; let’s start with the first.


Public Class Horse
Public m_name As String
Public m_color As String
Friend m_height As Single = 1.5 ‘ in meters

Public Sub New(ByVal name As String, _


Optional ByVal color As String = “”, _
Optional ByVal height As Single = 0)
Class Constructors 249

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

Public Sub New(ByVal name As String, _


ByVal color As String, _
ByVal height As Single)
250 Chapter 13: Objects and Classes

m_name = name
m_color = color
If 1 <= height And height <= 2.5 Then
m_height = height
End If
End Sub

Public Sub New(ByVal name As String, ByVal color As String)


m_name = name
m_color = color
End Sub
End Class

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

Public Sub New()


MyClass.New(“”, “”, 0)
End Sub

Public Sub New(ByVal name As String, ByVal color As String)


MyClass.New(name, color, 0)
End Sub

Private Sub New(ByVal name As String, _


ByVal color As String, _
ByVal height As Single)
m_name = name
m_color = color
If 1 <= height And height <= 2.5 Then
m_height = height
End If
End Sub
End Class

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

Public Class Horse


Public name As String

Public Sub New(ByVal name As String)


MyClass.name = name
End Sub
End Class

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

4. A private constructor can be called 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.
5. A variable of type object has as default value (value that it gets if not
explicitly initialized):
a. An empty object.
b. Nothing.
c. NULL.
d. 0.
6. An overloaded constructor is used to:
a. Hide the default implementation, when not required.
b. Provide alternative ways to build the project.
c. Allow the clients access to the class internals.
d. Allow different ways to construct a new object.

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

5. A class constructor is a method used to create a new object and initial-


ize it in a certain way.
True/False
6. The MyClass keyword can be accessed only inside the class.
True/False
7. An overloaded method cannot have optional parameters.
True/False

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)

Figure 13.3: Class Person in UML.


14
Properties
This chapter continues to build on the previous chapter’s object-oriented
concepts. You will learn about class properties, including the following
topics:
• What are properties
• The Property statement
• Using properties
• Parameterized properties
• Fields and properties

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

What Are Properties?


One of the examples from the previous chapter was the class Horse, which
had three fields: name, color, and height. We are showing only one con-
structor, in order to keep the example simple.
Public Class Horse
Public m_name As String
Public m_color As String
Public m_height As Single = 1.5

Public Sub New(ByVal name As String, _


ByVal color As String, _
ByVal height As Single)
m_name = name
m_color = color
If 1 <= height And height <= 2.5 Then
m_height = height
End If
End Sub
End Class

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 Property Statement


A solution to the problem is given in the following example.
Public Class Horse
Public m_name As String
Public m_color As String
Private m_height As Single = 1.5

Public Property height() As Single


Get
Return m_height
End Get
Set
If 1 <= Value And Value <= 2.5 Then
m_height = Value
End If
End Set
End Property

Public Sub New(ByVal name As String, _


ByVal color As String, _
ByVal height As Single)
m_name = name
m_color = color
MyClass.height = height
End Sub
End Class
260 Chapter 14: Properties

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

Console.Out.WriteLine(“The height is {0}”, h.height)


End Sub
End Module

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

Public ReadOnly Property name() As String


Get
Return m_name
End Get
End Property

Public ReadOnly Property dob() As Date


Get
Return m_dob
End Get
End Property

Public Sub New(ByVal name As String, ByVal dob As Date)


m_name = name
m_dob = dob
End Sub
End Class
Using Properties 263

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

This is an example only for illustrating the write-only properties, it would


make little sense to use a class for something that can be done with the
system stream classes.
Another useful type of property is the calculated property. These are nor-
mally properties that do not have an underlying field to store that data, but
264 Chapter 14: Properties

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

Public ReadOnly Property age() As Integer ‘ in years


Get
Return Now.year - m_dob.year
End Get
End Property

‘ rest of the code omitted


End Class

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

‘ properties code omitted

Public Sub New(ByVal name As String, ByVal dob As Date)


m_name = name
m_dob = dob
m_balances = New Decimal(5) {}
End Sub
End Class

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

Console.Out.WriteLine(“Balance of account 0 is {0}”, p.m_balances(0))


Console.Out.WriteLine(“Balance of account 1 is {0}”, p.m_balances(1))
End Sub
End Module

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

‘ other properties code omitted

Public Property balances(ByVal index As Integer) As Decimal


Get
Return m_balances(index)
End Get
Set
m_balances(index) = Value
End Set
End Property

Public Sub New(ByVal name As String, ByVal dob As Date)


m_name = name
m_dob = dob
m_balances = New Decimal(5) {}
End Sub
End Class

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

Console.Out.WriteLine(“Balance of account 0 is {0}”, p.balances(0))


Console.Out.WriteLine(“Balance of account 1 is {0}”, p.balances(1))
End Sub
End Module

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#)

p.m_balances = New Decimal(2) {} ‘ legal but bad!


End Sub
End Module

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

‘ rest of code omitted


Public ReadOnly Property noOfBalances() As Integer
Get
Return m_balances.Length
End Get
End Property
‘ rest of code omitted
End Class

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

Private m_balances() As Decimal

‘ unchanged code omitted


Public Property balances(ByVal index As Integer) As Decimal
Get
Return m_balances(index)
End Get
Set
m_balances(index) = Value
End Set
End Property

Public Property balances(ByVal index As String) As Decimal


Get
Return m_balances(CInt(index))
End Get
Set
m_balances(CInt(index)) = Value
End Set
End Property
‘ unchanged code omitted
End Class

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.

Fields and Properties


You have seen what a property is and why you need properties. A normal
class should have all its attributes implemented using a combination of pri-
vate fields and public (or friend) properties. In some cases it may be useful
to give access to the class fields to classes in the same assembly as itself. In
this case you can use friend fields and public properties. That would ensure
that no one outside the assembly has access to the class internals.
Using public fields is the only big no-no. It would break the encapsulation
principle, which is one of the most important OO principles.
Reviewing It 269

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

3. What is the difference between a property and a field?


4. What is a read-only property?
5. Enounce the principle of encapsulation.
6. What is a parameterized property?

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

5. A parameterized property is used to:


a. Access array fields.
b. Implement indexed attributes.
c. Enforce encapsulation.
d. All of the above.

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)

Figure 14.1: Class Person in UML.

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)

Figure 14.2: Class Account in UML.


15
Methods
In Chapter 13, “Objects and Classes—Introduction to Object-Oriented
Programming,” you saw briefly what a class method is. In this chapter you
are going to learn more about class methods. The chapter is structured in
the following topics:
• Class methods defined
• Method overloading
• Using methods

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

Class Methods Defined


In the first chapter of Part III we defined a class as being a set of objects
that share common attributes and behavior. Objects that are part of this set
are known as instances of the class. You have so far learned that the attrib-
utes of a class are implemented as fields and properties. You know now that
fields hold the data for an object (the object state) and properties provide
controlled access to this state.
In this chapter you will look at the behavior, which is the second dimension
of classes. Behavior means describing what an instance of the class (an
object) can do. For example a horse can trot, jump, eat, and so on. All
horses can perform these actions. The set of all the actions that the objects
of a class can perform is called behavior. In programming, behavior is rep-
resented by the methods of the class.
A method is a function or subroutine defined inside the class body, which
performs some action when invoked. For example, a method named Jump on
the class Horse could calculate how high the horse can jump based on its
height (for simplification) and return the value to the caller. Let us look at
this example.
Public Class Horse
Private m_name As String
Private m_color As String
Private m_height As Single

Public ReadOnly Property name() As String


Get
Return m_name
End Get
End Property

Public ReadOnly Property color() As String


Get
Return m_color
End Get
End Property

Public Property height() As Single


Get
Return m_height
End Get
Set
If 1 <= Value And Value <= 2.5 Then
m_height = Value
End If
Class Methods Defined 277

End Set
End Property

Public Sub New(ByVal name As String, _


ByVal color As String, _
Optional ByVal height As Single = 1.5)
m_name = name
m_color = color
MyClass.height = height
End Sub

‘ We assume that a horse can jump 75% of its height


Public Function Jump() As Single
Return CSng(0.75 * m_height)
End Function
End Class

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.

To use the new method you defined write a short example:


Module Module1
Sub Main()
Dim h As Horse = New Horse(“Bucefalus”, “black”, 2)
Console.Out.WriteLine(“The horse jumps {0} meters high!”, h.Jump())
End Sub
End Module

The normal methods of a class (not constructors or properties) can be called


using the familiar dot-notation and providing the parentheses after the
method name. If the method would have an argument defined, you would
place the parameter values in parentheses. If you had more than one value,
you need to separate them by commas.
278 Chapter 15: Methods

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()

Dim s1 As Short = 3, s2 As Short = 5


result = calc.Add(s1, s2)

Dim i1 As Integer = 3, i2 As Integer = 5


result = calc.Add(i1, i2)

Dim j1 As Long = 3, j2 As Long = 5


result = calc.Add(j1, j2)
End Sub
End Module

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

CHANGES FROM VISUAL BASIC 6.0


Method overloading was not supported in Visual Basic 6.0 and previous versions.

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

Public Function name() As String


Return m_name
End Function

Public Function color() As String


Return m_color
End Function

Public Function getHeight() As Single


Return m_height
End Function
Using Methods 281

Public Sub setHeight(ByVal v As Single)


If 1 <= v And v <= 2.5 Then
m_height = v
End If
End Sub

Public Sub New(ByVal name As String, _


ByVal color As String, _
Optional ByVal height As Single = 1.5)
m_name = name
m_color = color
setHeight(height)
End Sub

‘ We assume that a horse can jump 75% of its height


Public Function Jump() As Single
Return CSng(0.75 * m_height)
End Function
End Class

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.

Although this example is working, it is not the recommended way of imple-


menting properties. The languages that do not have a separate statement
for properties use this technique (and call the methods used for accessing
the fields accessors). However, Visual Basic .NET supports properties,
therefore it is better to use them. The code is easier to read and understand
if there is a clear distinction between a property (which is meant to access
the value of a field) and a method (which is an action that the object can
perform). You could fall into the other extreme and create properties that
do things other than setting or getting the value of an attribute.
282 Chapter 15: 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

Public ReadOnly Property id() As String


Get
Return m_id
End Get
End Property

Public Property balance() As Decimal


Get
Return m_balance
End Get
Set
m_balance = Value
End Set
End Property

Public Sub New(ByVal id As String, ByVal balance As Decimal)


m_id = id
m_balance = balance
End Sub
End Class
Using Methods 283

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

Public ReadOnly Property name() As String


Get
Return m_name
End Get
End Property

Public Sub New(ByVal name As String)


m_name = name
m_accounts = New Account(2) {}
‘ here we should initialize the accounts from a data source
m_accounts(0) = New Account(“Checking”, 2100) ‘ we just pick a number
m_accounts(1) = New Account(“Savings”, 11000) ‘ we just pick a number
End Sub
End Class

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

calculated parameterized property called balance, which will return the


balance of a specified account. The first version of this property is illus-
trated next:
Public ReadOnly Property balance(ByVal accountId As String) As Decimal
Get
Dim i As Integer
For i = 0 To m_accounts.Length - 1
If m_accounts(i).id.Equals(accountId) Then
return m_accounts(i).balance
End If
Next
End Get
End Property

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

‘ utility function: find the account specified by the accountId


Private Function GetAccountById(ByVal accountId As String) As Account
Dim i As Integer
For i = 0 To m_accounts.Length - 1
If m_accounts(i).id.Equals(accountId) Then
Return m_accounts(i)
End If
Next
End Function

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

parameter passed in to the function. If no account is found that matches,


Nothing will be returned, and the code calling this function will most likely
crash (indicating that the account was not found). You should add exception
handling to this class, but for simplicity reasons we will leave it out.
You also have changed the property balance to take advantage of the new
function. Namely it is trying to find the account and then it returns its bal-
ance. This is simpler than before and easier to understand.
You are now ready to implement the Deposit, Withdraw, and Transfer
methods. Deposit and withdraw should increment or decrement the
balance of the account (specified by accountId) by the amount specified
in the amount argument. The Transfer method will Withdraw from the
accountIdFrom account and Deposit it into the accountIdTo account. You
can now look at the final version of the Person class, with the three
methods shown in bold.
Public Class Person
Private m_name As String
Private m_accounts() As Account

Public ReadOnly Property name() As String


Get
Return m_name
End Get
End Property

Public ReadOnly Property balance(ByVal accountId As String) As Decimal


Get
Dim a As Account = GetAccountById(accountId)
Return a.balance
End Get
End Property

Public Sub Deposit(ByVal accountId As String, ByVal amount As Decimal)


Dim a As Account = GetAccountById(accountId)
a.balance += amount
End Sub

Public Sub Withdraw(ByVal accountId As String, ByVal amount As Decimal)


Dim a As Account = GetAccountById(accountId)
a.balance -= amount
End Sub

Public Sub Transfer(ByVal accountIdFrom As String, _


ByVal accountIdTo As String, _
ByVal amount As Decimal)
286 Chapter 15: Methods

Withdraw(accountIdFrom, amount)
Deposit(accountIdTo, amount)
End Sub

Public Sub New(ByVal name As String)


m_name = name
m_accounts = New Account(2) {}
‘ here we should initialize the accounts from a data source
‘ i.e. read the value of the balances, etc.
m_accounts(0) = New Account(“Checking”, 2100) ‘ we just pick a number
m_accounts(1) = New Account(“Savings”, 11000) ‘ we just pick a number
End Sub

‘ utility function: find the account specified by the accountId


Private Function GetAccountById(ByVal accountId As String) As Account
Dim i As Integer
For i = 0 To m_accounts.Length - 1
If m_accounts(i).id.Equals(accountId) Then
Return m_accounts(i)
End If
Next
End Function
End Class

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.”)

Console.Out.WriteLine(“Checking balance is {0}”, p.balance(“Checking”))


Console.Out.WriteLine(“Savings balance is {0}”, p.balance(“Savings”))

p.Deposit(“Savings”, 1200)
p.Transfer(“Savings”, “Checking”, 450)

Console.Out.WriteLine(“Checking balance is {0}”, p.balance(“Checking”))


Console.Out.WriteLine(“Savings balance is {0}”, p.balance(“Savings”))
End Sub

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)

Figure 15.1: UML diagram of the Person and Account classes

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

3. The Overloads keyword is used to:


a. Indicate that a method is going to be overloaded later.
b. Indicate that the method is overloaded by another method.
c. Indicate that the method overloads another method.
d. Both b and c because they mean the same thing.
4. Overloaded methods must differ by:
a. Name.
b. Number of arguments.
c. Number and/or type of the arguments.
d. Number and/or type and/or order of the arguments.
5. If Elevator is a class, which would be valid candidate for a method?
a. Elevator license number.
b. Move to specified floor.
c. Emergency brake.
d. Interior decoration.
6. If the price of a Product class is computed based on some fields (such
as list price, discounts, tax rate), is the price a property or a method?
a. Property because it is an attribute of the class.
b. Method because it is calculated.
c. Calculated property because it does not model an action of the
class.
d. Parameterized property because it requires other data to be cal-
culated.

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

2. An overloaded method can differ from another method by return type


only.
True/False
3. Overloaded methods must not have optional parameters.
True/False
4. Two overloads of a method can differ by the ByVal/ByRef argument
modifiers.
True/False
5. To invoke a class method from the body of another method or property
of the same class, you must use the MyClass keyword.
True/False

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

Shared Members Definition


To better understand shared members, we will start with an example. Let’s
assume that you have to code a class that models a product sold in a shop
and that the shop is geographically situated in a state or country that has a
sales tax. Your product class will have to calculate the price charged for the
product, based on the list price of the product, the sales tax, any discounts
entered by the sales clerk, and the quantity purchased. You could design
and then implement a class like the one shown here:
Public Class Product
Private m_name As String ‘ product name
Private m_listPrice As Decimal ‘ the list price
Private m_taxRate As Double

Public ReadOnly Property name() As String


Get
Return m_name
End Get
End Property

Public ReadOnly Property listPrice() As Decimal


Get
Return m_listPrice
End Get
End Property

Public ReadOnly Property taxRate() As Double


Get
Return m_taxRate
End Get
End Property

Public Sub New(ByVal name As String, _


ByVal listPrice As Decimal, _
ByVal taxRate As Double)
m_name = name
m_listPrice = listPrice
m_taxRate = taxRate
End Sub

Public Function GetPrice(ByVal discount As Double) As Decimal


Dim price As Double
price = m_listPrice + m_listPrice * m_taxRate - m_listPrice * discount
Return CDec(price)
End Function
End Class
Shared Members Definition 295

One can use this class as in the next example:


Module Module1
Sub Main()
Dim p As Product = New Product(“Coconuts”, 2, 0.08)
Console.Out.WriteLine(“The price is {0}”, p.GetPrice(0))
End Sub
End Module

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

Private Shared s_taxRate As Double

Public ReadOnly Property name() As String


Get
Return m_name
End Get
End Property
296 Chapter 16: Shared Class Members

Public ReadOnly Property listPrice() As Decimal


Get
Return m_listPrice
End Get
End Property

Public Shared Property taxRate() As Double


Get
Return s_taxRate
End Get
Set
s_taxRate = Value
End Set
End Property

Public Sub New(ByVal name As String, ByVal listPrice As Decimal)


m_name = name
m_listPrice = listPrice
End Sub

Public Function GetPrice(ByVal discount As Double) As Decimal


Dim price As Double
price = m_listPrice + m_listPrice * s_taxRate - m_listPrice * discount
Return CDec(price)
End Function
End Class

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

shared member (field, property, or method) from a shared property or


method. The opposite is not valid: any instance of the class can access any
shared field, property, and method, because these are defined at class level.
Another difference between shared properties and regular properties is the
way the user accesses them, as illustrated in the next example.
Module Module1
Sub Main()
Product.taxRate = 0.08
Dim p As Product = New Product(“Coconuts”, 2)
Console.Out.WriteLine(“The price is {0}”, p.GetPrice(0))
End Sub
End Module

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