DOWNLOAD RESOURCE : VB.NET PROGRAMMING
Visual Basic .NET is the next generation of Visual Basic, but it is also a significant departure from previous generations. Experienced Visual Basic 6 developers will feel comfortable with Visual Basic .NET code and will recognize most of its constructs. However, Microsoft has made some changes to make Visual Basic .NET a better language and an equal player in the .NET world. These include such additions as a Class keyword for defining classes and an Inherits keyword for bject inheritance, among others. Visual Basic 6 code can't be compiled by the Visual Basic .NET compiler without significant modification.The good news is that Microsoft has provided a migration tool to handle the task (mostly, anyway)
With its release for the .NET platform, the Visual Basic language has undergone dramatic changes.
- The language itself is now fully object-oriented.
- Applications and components written in Visual Basic .NET have full access to the .NET Framework, an extensive class library that provides system and application services.
- All applications developed using Visual Basic .NET run within a managed runtime environment, the .NET common language runtime.
Source Files
Visual Basic .NET source code is saved in files with a .vb extension. The exception to this rule is when Visual Basic .NET code is embedded in ASP.NET web page files. Such files have an .aspx extension.
Identifiers
Identifiers are names given to namespaces , types (enumerations, structures, classes, standard modules, interfaces, and delegates), type members (methods, constructors, events, constants, fields, and properties), and variables. Identifiers must begin with either an alphabetic or underscore character ( _ ), may be of any length, and after the first character must consist of only alphanumeric and underscore characters. Namespace declarations may be declared either with identifiers or qualified identifiers. Qualified identifiers consist of two or more identifiers connected with the dot character ( . ). Only namespace declarations may use qualified identifiers.
Keywords
Keywords are words with special meaning in a programming language. In Visual Basic .NET, keywords are reserved; that is, they cannot be used as tokens for such purposes as naming variables and subroutines
Keywords are words with special meaning in a programming language. In Visual Basic .NET, keywords are reserved; that is, they cannot be used as tokens for such purposes as naming variables and subroutines
Keyword | Description |
AddHandler | Visual Basic .NET Statement |
AddressOf | Visual Basic .NET Statement |
Alias | Used in the Declare statement |
And | Boolean operator |
AndAlso | Boolean operator |
Ansi | Used in the Declare statement |
Append | Used as a symbolic constant in the FileOpen function |
As | Used in variable declaration (Dim, Friend, etc.) |
Assembly | Assembly-level attribute specifier |
Auto | Used in the Declare statement |
Binary | Used in the Option Compare statement |
Boolean | Used in variable declaration (intrinsic data type) |
ByRef | Used in argument lists |
Byte | Used in variable declaration (intrinsic data type) |
ByVal | Used in argument lists |
Call | Visual Basic .NET statement |
Case | Used in the Select Case construct |
Catch | Visual Basic .NET statement |
CBool | Data-conversion function |
CByte | Data-conversion function |
CChar | Data-conversion function |
CDate | Data-conversion function |
CDec | Data-conversion function |
CDbl | Data-conversion function |
Char | Used in variable declaration (intrinsic data type) |
CInt | Data-conversion function |
Class | Visual Basic .NET statement |
CLng | Data-conversion function |
CObj | Data-conversion function |
Compare | Used in the Option Compare statement |
CShort | Data-conversion function |
CSng | Data-conversion function |
CStr | Data-conversion function |
CType | Data-conversion function |
Date | Used in variable declaration (intrinsic data type) |
Decimal | Used in variable declaration (intrinsic data type) |
Declare | Visual Basic .NET statement |
Default | Used in the Property statement |
Delegate | Visual Basic .NET statement |
Dim | Variable declaration statement |
Do | Visual Basic .NET statement |
Double | Used in variable declaration (intrinsic data type) |
Each | Used in the For Each...Next construct |
Else | Used in the If...Else...ElseIf...End If construct |
ElseIf | Used in the If...Else...ElseIf...End If construct |
End | Used to terminate a variety of statements |
EndIf | Used in the If...Else...ElseIf...End If construct |
Enum | Visual Basic .NET statement |
Erase | Visual Basic .NET statement |
Error | Used in the Error and On Error compatibility statements |
Event | Visual Basic .NET statement |
Explicit | Used in the Option Explicit statement |
False | Boolean literal |
For | Used in the For...Next and For Each...Next constructs |
Finally | Visual Basic .NET statement |
For | Visual Basic .NET statement |
Friend | Statement and access modifier |
Function | Visual Basic .NET statement |
Get | Used in the Property construct |
GetType | Visual Basic .NET operator |
GoTo | Visual Basic .NET statement, used with the On Error statement |
Handles | Defines an event handler in a procedure declaration |
If | Visual Basic .NET statement |
Implements | Visual Basic .NET statement |
Imports | Visual Basic .NET statement |
In | Used in the For Each...Next construct |
Inherits | Visual Basic .NET statement |
Input | Used in the FileOpen function |
Integer | Used in variable declaration (intrinsic data type) |
Interface | Visual Basic .NET statement |
Is | Object comparison operator |
Let | Reserved but unused in Visual Basic .NET |
Lib | Used in the Declare statement |
Like | Visual Basic .NET operator |
Lock | Function name |
Long | Used in variable declaration (intrinsic data type) |
Loop | Used in a Do loop |
Me | Statement referring to the current object instance |
Mid | String-manipulation statement and function |
Mod | Visual Basic .NET operator |
Module | Visual Basic .NET statement |
MustInherit | Used in the Class construct |
MustOverride | Used in the Sub and Function statements |
MyBase | Statement referring to an object's base class |
MyClass | Statement referring to the current object instance |
Namespace | Visual Basic .NET statement |
New | Object-creation keyword, constructor name |
Next | Used in the For...Next and For Each...Next constructs |
Not | Visual Basic .NET operator |
Nothing | Used to clear an object reference |
NotInheritable | Used in the Class construct |
NotOverridable | Used in the Sub, Property, and Function statements |
Object | Used in variable declaration (intrinsic data type) |
Off | Used in Option statements |
On | Used in Option statements |
Option | Used in Option statements |
Optional | Used in the Declare, Function, Property, and Sub statements |
Or | Boolean operator |
OrElse | Boolean operator |
Output | Used in the FileOpen function |
Overloads | Used in the Sub and Function statements |
Overridable | Used in the Sub and Function statements |
Overrides | Used in the Sub, Property, and Function statements |
ParamArray | Used in the Declare, Function, Property, and Sub statements |
Preserve | Used with the ReDim statement |
Private | Statement and access modifier |
Property | Visual Basic .NET statement |
Protected | Statement and access modifier |
Public | Statement and access modifier |
RaiseEvent | Visual Basic .NET statement |
Random | Used in the FileOpen function |
Read | Used in the FileOpen function |
ReadOnly | Used in the Property statement |
ReDim | Visual Basic .NET statement |
Rem | Visual Basic .NET statement |
RemoveHandler | Visual Basic .NET statement |
Resume | Used in the On Error and Resume statements |
Return | Visual Basic .NET statement |
Seek | File-access statement and function |
Select | Used in the Select Case construct |
Set | Used in the Property statement |
Shadows | Visual Basic .NET statement |
Shared | Used in the Sub and Function statements |
Short | Used in variable declaration (intrinsic data type) |
Single | Used in variable declaration (intrinsic data type) |
Static | Variable declaration statement |
Step | Used in the For...Next construct |
Stop | Visual Basic .NET statement |
String | Used in variable declaration (intrinsic data type) |
Structure | Visual Basic .NET statement |
Sub | Visual Basic .NET statement |
SyncLock | Visual Basic .NET statement |
Text | Used in the Option Compare statement |
Then | Used in the If...Then...Else...EndIf construct |
Throw | Visual Basic .NET statement |
To | Used in the For...Next and Select Case constructs |
True | Boolean literal |
Try | Visual Basic .NET statement |
TypeOf | Used in variations of the If...Then...EndIf construct |
Unicode | Used in the Declare statement |
Until | Used in the For...Next construct |
Variant | Reserved but unused in Visual Basic .NET |
When | Used with the Try...Catch...Finally construct |
While | Used with the Do...Loop and While...End While constructs |
With | Visual Basic .NET statement |
WithEvents | Used in variable declaration (Dim, Public, etc.) |
WriteOnly | Used in the Property statement |
XOr | Visual Basic .NET operator |
Literals
Literals are representations of values within the text of a program. For example, in the following line of code, 10 is a literal, but x and y are not:
x = y * 10
Literals have data types just as variables do. The 10 in this code fragment is interpreted by the compiler as type Integer because it is an integer that falls within the range of the Integer type.
- Numeric Literals
Any integer literal that is within the range of the Integer type (-2147483648 through 2147483647) is interpreted as type Integer, even if the value is small enough to be interpreted as type Byte or Short. Integer literals that are outside the Integer range but are within the range of the Long type (-
9223372036854775808 through 9223372036854775807) are interpreted as type Long. Integer literals outside the Long range cause a compile-time error.
Numeric literals can also be of one of the floating point types—Single, Double, and Decimal. For example, in this line of code, 3.14 is a literal of type Double:
z = y * 3.14
In the absence of an explicit indication of type (discussed shortly), Visual Basic .NET interprets floating point literals as type Double. If the literal is outside the range of the Double type (-
1.7976931348623157E308 through 1.7976931348623157E308), a compile-time error occurs.
- String Literals
Literals of type String consist of characters enclosed within quotation-mark characters. For example, in the following line of code, "hello, world" is a literal of type String
Console.WriteLine("hello, world")
- Character Literals
Visual Basic .NET's Char type represents a single character. This is not the same as a one-character string; Strings and Chars are distinct types. Literals of type Char consist of a single character enclosed within quotation-mark characters, followed by the character c. For example, in the following code, "A"c is a literal of type Char:
Dim MyChar As Char
MyChar = "A"c
- Character Literals
Visual Basic .NET's Char type represents a single character. This is not the same as a one-character string; Strings and Chars are distinct types. Literals of type Char consist of a single character enclosed within quotation-mark characters, followed by the character c. For example, in the following code, "A"c is a literal of type Char:
Dim MyChar As Char
MyChar = "A"c
- Date Literals
Literals of type Date are formed by enclosing a date/time string within number-sign characters. For example: ]
Dim MyDate As Date
MyDate = #11/15/2001 3:00:00 PM#
- Boolean Literals
The keywords True and False are the only Boolean literals. They represent the true and false Boolean states, respectively (of course!). For example:
Dim MyBoolean As Boolean
MyBoolean = True
- Nothing
There is one literal that has no type: the keyword Nothing. Nothing is a special symbol that represents an uninitialized value of any type. It can be assigned to any variable and passed in any parameter. When used in place of a reference type, it represents a reference that does not reference any object. When used in place of a value type, it represents an empty value of that type. For numeric types, this is 0 or 0.0. For the String type, this is the empty string (""). For the Boolean type, this is False. For the Char type, this is the Unicode character that has a numeric code of 0. For programmer-defined value types, Nothing represents an instance of the type that has been created but has not been assigned a value.
- Summary of Literal Formats
|
Types
Types in Visual Basic .NET are divided into two categories: value types and reference types. Value types minimize memory overhead and maximize speed of access, but they lack some features of a fully object-oriented design (such as inheritance). Reference types give full access to object-oriented features, but they impose some memory and speed overhead for managing and accessing objects. When a variable holds a value type, the data itself is stored in the variable. When a variable holds a reference type, a reference to the data (also known as a pointer) is stored in the variable, and the data itself is stored somewhere else. Visual Basic .NET's primitive types include both value types and reference types (see "Fundamental Types" in this section). For extending the type system, Visual Basic .NET provides syntax for defining both new value types and new reference types (see "Custom Types" later in this section)
- Fundamental Types
Visual Basic .NET has several built-in types. Each
of these types is an alias for a type supplied by the .NET architecture.
Because Visual Basic .NET types are equivalent to the corresponding underlying
.NET-supplied types, there are no type-compatibility issues when passing
arguments to components developed in other languages. In code, it makes no
difference to the compiler whether types are specified using the keyword name
for the type or using the underlying .NET type name. For example, the test in
this code fragment succeeds:
Dim x As Integer
Dim y As System.Int32
If x.GetType() Is
y.GetType( ) Then
Console.WriteLine("They're the same
type!")
Else
Console.WriteLine("They're not the same
type.") End If
The fundamental Visual Basic .NET types are:
Boolean
The Boolean type is limited to two values: True and False. Visual Basic
.NET includes many logical operators that result in a Boolean type. For
example:
Public Shared Sub
MySub(ByVal x As Integer, ByVal y As Integer)
Dim b As Boolean = x > y
' other code
End Sub ' MySub
The result of the greater-than operator (>) is of type Boolean. The variable b is assigned the value True if the value
in x is greater than the value in y and
False if it is not. The underlying .NET type is
System.Boolean.
Byte
The Byte type can hold a range of integers from 0 through
255. It represents the values that can be held in eight bits of data. The
underlying .NET type is System.Byte.
Char
The Char type can hold any Unicode[1]
character. The Char data type is new to Visual Basic .NET. The underlying .NET
type is System.Char.
Date
The Date type holds values that specify dates and times.
The range of values is from midnight on January 1, 0001 (0001-01-01T00:00:00)
through 1 second before midnight on December 31, 9999 (9999-12-31T23:59:59).
The Date type contains many members for accessing, comparing, and manipulating
dates and times. The underlying .NET type is System.DateTime.
Decimal
The Decimal type holds decimal numbers with a precision of
28 significant decimal digits. Its purpose is to represent and manipulate
decimal numbers without the rounding errors of the Single and Double types. The
Decimal type replaces Visual Basic 6's Currency type. The underlying .NET type
is System.Decimal.
Double
The Double type holds a 64-bit value
that conforms to IEEE standard 754 for binary floating point arithmetic. The
Double type holds floating point numbers in the range -
1.7976931348623157E308 through 1.7976931348623157E308. The
smallest nonnegative number (other than zero) that can be held in a Double is
4.94065645841247E-324. The underlying .NET type is System.Double.
Integer
The Integer type holds integers in the range -2147483648
through 2147483647. The Visual Basic .NET Integer data type corresponds to the
VB 6 Long data type. The underlying .NET type is System.Int32.
Long
The Long type holds integers in the range
-9223372036854775808 through 9223372036854775807. In Visual Basic .NET, Long is
a 64-bit integer data type. The underlying .NET type is System.Int64.
Object
The Object type is the base type from which all
other types are derived. The Visual Basic .NET Object data type replaces the
Variant in VB 6 as the universal data type. The underlying .NET type is
System.Object.
Short
The Short type holds integers in the range -32768 through
32767. The Short data type corresponds to the VB 6 Integer data type. The
underlying .NET type is System.Int16.
Single
The Single type holds a 32-bit value that conforms to IEEE
standard 754 for binary floating point arithmetic. The Single type holds
floating point numbers in the range -3.40282347E38 through 3.40282347E38. The
smallest nonnegative number (other than zero) that can be held in a Double is
1.401298E-45. The underlying .NET type is System.Single.
String
The String type holds a sequence of Unicode characters. The
underlying .NET type is System.String.
Of the fundamental types, Boolean, Byte, Char, Date,
Decimal, Double, Integer, Long, Short, and Single (that is, all of them except
Object and String) are value types. Object and String are reference types.
- Custom Types
Visual Basic .NET provides rich syntax for extending the
type system. Programmers can define both new value types and new reference
types. Types declared with Visual Basic .NET's Structure and
Enum statements are value types, as are all
.NET Framework types that derive from
System.ValueType.
Reference types include Object, String, all types declared with Visual Basic
.NET's Class, Interface, and Delegate statements, and all .NET Framework types that don't derive from
System.ValueType.
Arrays
Array declarations in Visual Basic .NET are similar to
those in Visual Basic 6 and other languages. For example, here is a declaration
of an Integer array that has five elements:
Dim a(4) As Integer
The literal 4 in this
declaration specifies the upper bound of the array. All arrays in Visual Basic
.NET have a lower bound of 0, so this is a declaration of an array
with five elements, having indexes 0, 1, 2, 3, and 4.
The previous declaration is of a variable named a, which is of type "array of Integer." Array
types implicitly inherit from the .NET Framework's Array type (defined in the
System namespace) and, therefore, have access to the methods defined in that
type. For example, the following code displays
the lower and upper bounds of an array by calling the Array
class's GetLowerBound and GetUpperBound methods:
Dim a(4) As Integer
Console.WriteLine("LowerBound
is " & a.GetLowerBound(0).ToString(
))
Console.WriteLine("UpperBound
is " & a.GetUpperBound(0).ToString(
))
The output is:
LowerBound is 0
UpperBound is 4
Note that the upper bound of the array is dynamic: it can
be changed by methods available in the Array type.
Array elements are initialized to the default value of the
element type. A type's default value is determined as follows:
• For
numeric types, the default value is 0.
• For
the Boolean type, the default value is False.
• For
the Char type, the default value is the character whose Unicode value is 0.
• For
structure types (described later in this chapter), the default value is an
instance of the structure type with all of its fields set to their default
values.
• For
enumeration types (described later in this chapter), the default value is an
instance of the enumeration type with its internal representation set to 0, which may or may not correspond to a legal value in
the enumeration.
• For
reference types (including String), the default value is Nothing.
You can access array elements by suffixing the array name
with the index of the desired element enclosed in parentheses, as shown
here:
For i = 0 To 4
Console.WriteLine(a(i))
Next
Arrays can be multidimensional. Commas separate the
dimensions of the array when used in declarations and when accessing elements.
Here is the declaration of a three-dimensional array, where each dimension has
a different size:
Dim a(5, 10, 15) As
Integer
As
with single-dimensional arrays, array elements are initialized to their default
values
- Initializing arrays
Arrays of primitive types can be initialized by enclosing
the initial values in curly brackets ({}). For
example:
Dim a( ) As String = {"First",
"Second", "Third", "Fourth", "Fifth"}
Notice that when arrays are initialized in this manner, the
array declaration is not permitted to specify an explicit size. The compiler
infers the size from the number of elements in the initializer.
To initialize multidimensional arrays, include the
appropriate number of commas in the array-name declaration and use nested curly
brackets in the initializer. Here is a declaration of a two-dimensional array
having three rows and two columns:
Dim a(,) As Integer = {{1,
2}, {3, 4}, {5, 6}}
This declaration produces the following array:
a(0,0)=1 a(0,1)=2 a(1,0)=3 a(1,1)=4 a(2,0)=5 a(2,1)=6
When
initializing multidimensional arrays, the innermost curly brackets correspond
to the rightmost dimension
- Dynamically allocating arrays
Use the New keyword to allocate arrays of any type.
For example, this code creates an array of five Integers and initializes the
elements as shown:
Dim a( ) As Integer
a = New Integer(4) {1, 2,
3, 4, 5}
If the array elements won't be initialized by the
allocation, it is still necessary to include the curly brackets:
Dim a( ) As Integer
' allocates an
uninitialized array of five Integers a = New Integer(5) {}
Curly brackets are required so the compiler won't confuse
the array syntax with constructor syntax.
Note also the meaning of this declaration by itself:
Dim a( ) As Integer
This is the declaration of a reference that could point to
a single-dimensional array of Integers, but doesn't yet. Its initial value is Nothing.
Collections
A collection is any type that exposes the ICollection interface (defined
in the System.Collections namespace). (Interfaces are explained later in this
chapter. Briefly, an interface is an agreement in which the type will expose
certain methods, properties, and other members. By exposing the ICollection interface, a type
ensures that it can be used anywhere a collection is expected.) In general,
collections store multiple values and provide a way for iterating through those
values. Specialized collection types may also provide other means for adding
and reading values. For example, the Stack type (defined in the
System.Collections namespace) provides methods, such as Push and Pop, for
performing operations that are appropriate for the stack data structure
Type
Conversions
Visual Basic .NET provides a variety of ways for values of
one type to be converted to values of another type. There are two main categories
of conversions: widening conversions
and narrowing conversions. Widening
conversions are conversions in which there is no possibility for data loss or
incorrect results. For example, converting a value of type Integer to a value
of type Long is a widening conversion because the Long type can accommodate
every possible value of the Integer type. Narrowing is the reverse
operation—converting from a Long to an Integer—because some values of type Long
can't be represented as values of type Integer.
Visual Basic .NET performs widening conversions
automatically whenever necessary. For example, a widening conversion occurs in
the second line of the following code. The Integer value on the righthand side
of the assignment is automatically converted to a Long value so it can be
stored in the variable b:
Dim a As Integer = 5 Dim b
As Long = a
A conversion that happens automatically is called an implicit conversion.
Now consider the reverse situation:
Dim a As Long = 5
Dim b As Integer = a
The second line of code here attempts to perform an
implicit narrowing conversion. Whether the compiler permits this line of code
depends on the value set for the Option Strict compiler option. When Option
Strict is On, attempts to
perform an implicit widening conversion result in a compiler error. When Option Strict is Off, the compiler
automatically adds code behind the scenes to perform the conversion. At
runtime, if the actual value being converted is out of the range that can be
represented by the target type, a runtime exception occurs.
Option Strict can be set
in either of two ways. First, it can be set in code at the top of a source
file, like this:
Option Strict On ' ...
or:
Option Strict Off ' ...
The other way is to set a compiler switch, which affects
all source files in the application. If you're compiling from the command line,
specify /optionstrict+ on the command line to set Option Strict On. Specify /optionstrict- to set Option Strict Off. For example:
vbc MySource.vb
/optionstrict+
To set Option Strict in Visual
Studio .NET:
1. Right-click
on the project name in the Solution Explorer window and choose Properties. This
brings up the Project Property Pages dialog box. (If the Solution Explorer
window is not visible, choose ViewSolution Explorer from the
Visual Studio .NET main menu to make it appear.)
2. Within
the Project Property Pages dialog box, choose the Common Properties folder.
Within that folder, choose the Build property page. This causes the
project-build options to appear on the right side of the dialog box.
3. Set
the desired value for the Option Strict option.
By default, Option Strict is Off, meaning that
implicit narrowing conversions are allowed. This matches the default setting of
Visual Basic 6. However, most experienced developers consider it beneficial to
set Option Strict On so the compiler
can help detect coding errors before they become runtime errors. Attempting to
assign a Long to an Integer, for example, is usually a sign either that
something was mistyped or that there is a problem with the design of the
program. Setting Option Strict On helps the developer discover such errors at compile
time. On the other hand, there may sometimes be a legitimate need to perform a
narrowing conversion. Perhaps the application is interfacing to another
application that passes a value as a Long, but it is guaranteed that the actual
value passed will never be outside the range of the Integer type. Option Strict could be set to Off to allow implicit narrowing conversions, but a better
alternative is to have Option Strict On (so it can protect the majority of the program) and to
specify an explicit narrowing
conversion. For example:
Dim a As Long = 5
Dim b As Integer = CInt(a)
This is known as an explicit
conversion because the programmer is explicitly requesting a conversion to
Integer. If at runtime a contains a value that is outside the
Integer range, an exception is thrown.
Conversion
function
|
Converts
its argument to
|
CBool
|
A
Boolean
|
CByte
|
A
Byte
|
CChar
|
A
Char
|
CDate
|
A
Date
|
CDbl
|
A
Double
|
CDec
|
A
Decimal
|
CInt
|
An
Integer
|
CLng
|
A
Long
|
CObj
|
An
Object
|
CSng
|
A
Single
|
CStr
|
A
String
|
The functions shown in all take a
single argument. If the argument can't be converted to the given type, an
exception is thrown. Note the following:
• When
converting from any numeric value to Boolean, zero converts to False and nonzero converts to True.
• When
converting from Boolean to a numeric value, False converts to 0 and True converts to -1.
• When
converting from String to Boolean, the string must contain either the word "false", which converts to False, or the word "true",
which converts to True. The case of the string is not
important.
• When
converting from Boolean to String, True converts to "True" and False converts to "False".
• Anything
can be converted to type Object.
It's also possible to convert between reference types. Any
object-reference conversion of a derived type to a base type is considered a
widening conversion and can therefore be done implicitly. Conversely,
conversion from a base type to a derived type is a narrowing conversion. As
previously discussed, in order for narrowing conversions to compile, either Option Strict must be Off
or an explicit conversion must be performed. Explicit conversions of reference
types are done with the CType
function. The CType function takes
two arguments. The first is a reference to some object, and the second is the
name of the type to which the reference will convert. At runtime, if a
conversion is possible, the return value of the function is an object reference
of the appropriate type. If no conversion is possible, an exception is thrown.
Namespaces
Thousands of types are defined in the .NET Framework. In
addition, programmers can define new types for use in their programs. With so
many types, name clashes are inevitable. To prevent name clashes, types are
considered to reside inside of namespaces.
Often, this fact can be ignored. For example, in Visual Basic .NET a class may
be defined like this:
Public Class SomeClass
' ...
End Class
This class definition might be in a class library used by
third-party customers, or it might be in the same file or the same project as
the client code. The client code that uses this class might look something like
this:
Dim x As New
SomeClass( )
x.DoSomething( )
Now consider what happens if the third-party customer also
purchases another vendor's class library, which also exposes a SomeClass class.
The Visual Basic .NET compiler can't know which definition of SomeClass will be
used. The client must therefore use the full
name of the type, also known as its fully
qualified name . Code that needs to use both types might look something
like this:
' The namespace is
"FooBarCorp.SuperFoo2100". Dim x As New
FooBarCorp.SuperFoo2100.SomeClass( )
x.DoSomething( )
' ...
' The namespace is
"MegaBiz.ProductivityTools.WizardMaster". Dim y As New
MegaBiz.ProductivityTools.WizardMaster.SomeClass( )
y.DoSomethingElse( )
Note that a namespace name can itself contain periods (.). When looking at a fully qualified type name,
everything prior to the final period is the namespace name. The name after the
final period is the type name.
Microsoft recommends that namespaces be named according to
the format CompanyName.TechnologyName.
For example, "Microsoft.VisualBasic".
Symbolic Constants
Consider this function:
Public Shared Function
RemainingCarbonMass( _
ByVal InitialMass As Double, _
ByVal Years As Long _
) As Double
Return InitialMass * ((0.5 ^ (Years /
5730))) End Function
What's wrong with this code? One problem is readability. What does it
mean to divide Years by 5730? In this code,
5730 is referred to as a magic number -- one whose meaning is not readily evident from
examining the code. The following changes correct this problem:
Public Const
CarbonHalfLifeInYears As Double = 5730
Public Shared Function
RemainingCarbonMass( _
ByVal InitialMass As Double, _
ByVal Years As Long _
) As Double
Return InitialMass * ((0.5 ^ (Years /
CarbonHalfLifeInYears))) End Function
There is now no ambiguity about the meaning of the divisor.
Another problem with the first code fragment is that a
program filled with such code is hard to maintain. What if the programmer later
discovers that the half-life of carbon is closer to 5730.1 years, and she wants
to make the program more accurate? If this number is used in many places
throughout the program, it must be changed in every case. The risk is high of
missing a case or of changing a number that shouldn't be changed. With the
second code fragment, the number needs to be changed in only one place.
Variables
A variable is an
identifier that is declared in a method and that stands for a value within that
method. Its value is allowed to change within the method. Each variable is of a
particular type, and that type is indicated in the declaration of the variable.
For example, this line declares a variable named i whose type is
Integer:
Dim i As Integer
The keyword Dim indicates a
variable declaration. Dim is short
for dimension and dates back to the
original days of the BASIC programming language in the late 1960s. In that
language, variables were not declared; they were just used where needed (except
for arrays). Because of how arrays were laid out in memory, the BASIC language
interpreter had to be told of the dimensions of an array before the array was
used. This was the purpose of the Dim statement. In
later years, when declaration of all variables was agreed upon to be a good thing, the use of the Dim statement was broadened to include all variable
declarations.
Variable identifiers may be suffixed with type characters that serve to indicate
the variable's type. For example, this line declares a variable of type
Integer:
Dim x%
The effect is precisely the same as for this declaration:
Dim
x As Integer
Data
type
|
|
Type character
|
Example
|
Decimal
|
@
|
|
Dim decValue@ = 132.24
|
Double
|
#
|
|
Dim dblValue# = .0000001327
|
Integer
|
%
|
|
Dim iCount% = 100
|
Long
|
&
|
|
Dim lLimit& = 1000000
|
Single
|
!
|
|
Dim sngValue! = 3.1417
|
String
|
$
|
|
Dim strInput$ = ""
|
Scope
Scope refers to the so-called visibility of identifiers within source code. That is, given a
particular identifier declaration, the scope
of the identifier determines where it is legal to reference that identifier in
code. For example, these two functions each declare a variable CoffeeBreaks. Each declaration is invisible to the code
in the other method. The scope of each variable is the method in which it is
declared.
Public Sub
MyFirstMethod( ) Dim CoffeeBreaks As Integer
' ...
End Sub
Public Sub
MySecondMethod( ) Dim CoffeeBreaks As Long
' ...
End Sub
Unlike previous versions of Visual Basic, Visual Basic .NET
has block scope. Variables declared
within a set of statements ending with End, Loop, or Next are local to
that block. For example:
Dim i As Integer
For i = 1 To 100
Dim j As Integer
For j = 1 To 100
' ...
Next
Next
' j is not visible here
Visual
Basic .NET doesn't permit the same variable name to be declared at both the
method level and the block level. Further, the life of the block-level variable
is equal to the life of the method. This means that if the block is re-entered,
the variable may contain an old value
Access Modifiers
Access modifiers control the accessibility of types
(including enumerations, structures, classes, standard modules, and delegates)
and type members (including methods, constructors, events, constants, fields
[data members], and properties) to other program elements. They are part of the
declarations of types and type members. In the following code fragment, for
example, the keywords Public and Private are access
modifiers:
Public Class SomeClass
Public Sub DoSomething( )
' ...
End Sub
Private Sub InternalHelperSub( )
' ...
End Sub
End Class
Access modifier
|
Description
|
Friend
|
Defines
a type that is accessible only from within the program in which it is
declared.
|
Private
|
Defines
a type that is accessible only from within the context in which it is
declared. For instance, a Private variable declared within a class module is
accessible only from within that class module. A Private class is accessible
only from classes within which it is nested.
|
Protected
|
Applies
to class members only. Defines a type that is accessible only from within its
own class or from a derived class.
|
Protected Friend
|
Defines
a type that is accessible from within the program in which it is declared as
well as from derived classes.
|
Public
|
Defines
a type that is publicly accessible. For example, a public method of a class
can be accessed from any program that instantiates that class.
|
Assignment
In Visual Basic .NET, assignment statements are of the
form:
variable, field, or
property = expression
Either the type of the expression must be the same as that
of the item receiving the assignment, or there must exist an appropriate
implicit or explicit conversion from the type of the expression to the type of
the item receiving the assignment. For information on implicit and explicit
conversions, see earlier in this chapter.
When
an assignment is made to a value type, the value of the expression is copied to
the target. In contrast, when an assignment is made to a reference type, a
reference to the value is stored in the target. This is an important
distinction that is worth understanding well.
Operators and
Expressions
Operators are symbols (characters or keywords) that
specify operations to be performed on one or two operands (or arguments).
Operators that take one operand are called unary
operators. Operators that take two operands are called binary operators. Unary operators use prefix notation, meaning that the operator precedes the operand
(e.g., -5). Binary operators (except for one case) use infix notation, meaning that the operator is between the operands
(e.g., 1 + 2). The TypeOf...Is operator is a binary operator that uses a special form that is neither
prefix nor infix notation- Unary Operators
Visual Basic supports the following unary operators:
+ (unary plus)
The unary plus operator takes any numeric operand. It's not
of much practical use because the value of the operation is equal to the value
of the operand.
- (unary
minus)
The unary minus operator takes any numeric operand (except as noted
later). The value of the operation is the negative of the value of the operand.
In other words, the result is calculated by subtracting the operand from zero.
If the operand type is Short, Integer, or Long, and the value of the operand is
the maximum negative value for that type, then applying the unary minus
operator will cause a System.OverflowException error, as in the following code
fragment:
Dim sh As Short = -32768
Dim i As Integer = -sh
Not (logical
negation)
The logical negation operator takes a Boolean operand. The
result is the logical negation of the operand. That is, if the operand is False, the result of the operation is True, and vice versa.
AddressOf
The AddressOf operator returns a reference to a
method. Two different kinds of references can be obtained, depending on the
context in which the operator is used:
• When
the AddressOf operator is used within the argument list of a
call to a method, which is made available via the Declare
statement, it returns a function pointer that is suitable for such calls.
• When
the AddressOf operator is used in any other context, a
delegate object is returned.
- Arithmetic Operators
The arithmetic operators perform the standard arithmetic
operations on numeric values. The arithmetic operators supported by Visual
Basic .NET are:
*
(multiplication)
The multiplication operator is defined for all numeric operands.
The result is the product of the operands.
/ (regular
division)
The regular division operator is defined for all numeric
operands. The result is the value of the first operand divided by the second
operand.
\ (integer
division)
The integer division operator is defined for integer
operands (Byte, Short, Integer, and Long). The result is the value of the first
operand divided by the second operand, then rounded to the integer nearest to
zero.
Mod (modulo)
The modulo operator is defined for integer operands (Byte,
Short, Integer, and Long). The result is the remainder after the integer
division of the operands.
^
(exponentiation)
The exponentiation
operator is defined for operands of type Double. Operands of other numeric
types are converted to type Double before the result is calculated. The result
is the value of the first operand raised to the power of the second
operand. +
(addition)
The addition operator is defined for all numeric operands
and operands of an enumerated type. The result is the sum of the operands. For
enumerated types, the sum is calculated on the underlying type, but the return
type is the enumerated type. See the discussion of enumerated types in the
"Enumerations" section later in this chapter for more information on
the types that can underlie an enumerated type. See also later in this section.
-
(subtraction)
The
subtraction operator is defined for all numeric operands and operands of an
enumerated type. The result is the value of the first operand minus the second
operand. For enumerated types, the subtraction is calculated on the underlying
type, but the return type is the enumerated type. See the discussion of
enumerated types in later in this chapter for more information on the
types that can underlie an enumerated type- Relational Operators
The relational operators all perform some comparison
between two operands and return a Boolean value indicating whether the operands
satisfy the comparison. The relational operators supported by Visual Basic .NET
are:
= (equality)
The equality operator is defined for all primitive value
types and all reference types. For primitive value types and for the String
type, the result is True if the values of the operands are
equal; False if not. For reference types other than String, the result
is True if the references refer to the same object; False if not. If the operands are of type Object and they
reference primitive value types, value comparison is performed rather than
reference comparison.
<>
(inequality)
The inequality operator is defined for all primitive value
types and for reference types. For primitive value types and for the String
type, the result is True if the values of the operands are not
equal; False if equal. For reference types other than String,
the result is True if the references refer to different
objects; False if they refer to the same object. If the operands
are of type Object and they reference primitive value types, value comparison
is performed rather than reference comparison.
< (less
than)
The less-than operator is defined for all numeric operands
and operands of an enumerated type. The result is True
if the first operand is less than the second; False if not. For
enumerated types, the comparison is performed on the underlying type.
> (greater
than)
The greater-than operator is defined for all numeric
operands and operands that are of an enumerated type. The result is True if the first operand is greater than the second; False if not. For enumerated types, the comparison is
performed on the underlying type.
<= (less
than or equal to)
The less-than-or-equal-to operator is defined for all
numeric operands and operands of an enumerated type. The result is True if the first operand is less than or equal to the
second operand; False if not.
>= (greater
than or equal to)
The greater-than-or-equal-to operator is defined for all
numeric operands and operands of an enumerated type. The result is True if the first operand is greater than or equal to the
second operand; False if not.
TypeOf...Is
The TypeOf...Is operator is defined to take a
reference as its first parameter and the name of a type as its second
parameter. The result is True if the reference refers to an object
that is type-compatible with the given type-name; False
if the reference is Nothing or if it refers to an object that
is not type-compatible with the given type name.
Use the TypeOf...Is operator to determine whether a
given object:
• Is
an instance of a given class
• Is
an instance of a class that is derived from a given class
• Exposes
a given interface
In any of these cases, the TypeOf expression
returns True.
Is
The Is operator is defined for all reference
types. The result is True if the references refer to the same
object; False if not.
Like
The Like operator is defined only for operands
of type String. The result is True if the first
operand matches the pattern given in the second operand; False if not.
The rules for matching are:
• The
? (question mark) character matches any single
character.
• The
* (asterisk) character matches zero or more
characters.
• The
# (number sign) character matches any single digit.
• A
sequence of characters within [] (square
brackets) matches any single character in the sequence.
Within such a bracketed list, two characters separated by a
- (hyphen) signify a range of Unicode characters,
starting with the first character and ending with the second character. A - character itself can be matched by placing it at the
beginning or end of the bracketed sequence.
Preceding the sequence of characters with an ! (exclamation mark) character matches any single
character that does not appear in the sequence.
• The
?, *, #, and [ characters can be matched by placing them within [] in the pattern string. Consequently, they cannot be
used in their wildcard sense within [].
• The
] character does not need to be escaped to be explicitly
matched. However, it can't be used within [].
- String-Concatenation Operators
The & (ampersand) and + (plus) characters signify string concatenation. String concatenation is defined for operands of type String only. The result is a string that consists of the characters from the first operand followed by the characters from the second operand
- Bitwise Operators
It is sometimes necessary to manipulate the individual bits
that make up a value of one of the integer types (Byte, Short, Integer, and
Long). This is the purpose of the bitwise operators. They are defined for the
four integer types and for enumerated types. When the bitwise operators are
applied to enumerated types, the operation is done on the underlying type, but
the result is of the enumerated type.
The bitwise operators work by applying the given Boolean
operation to each of the corresponding bits in the two operands. For example,
consider this expression:
37 And 148
To calculate the value of this expression, consider the
binary representation of each operand. It's helpful to write one above the
other so that the bit columns line up:
00100101 (37)
10010100 (148)
Next, apply the Boolean And operation to
the bits in each column:
00100101
(37)
And 10010100 (148)
--------
00000100
(4)
37 And 148, therefore, equals 4.
The bitwise operators are:
And
Performs a Boolean And operation on
the bits. (The result bit is 1 if and only if both of the source bits
are 1.)
AndAlso
The result is True if and only if
both the operands are True; otherwise, the result is False. AndAlso performs logical short-circuiting:
if the first operand of the expression is False, the second
operand is not evaluated.
Or
Performs a Boolean Or operation on the
bits. (The result bit is 1 if either or both of the source bits are 1.)
OrElse
The result is True if either or
both the operands is True; otherwise, the result is False. OrElse performs logical short-circuiting:
if the first operand of the expression is True, the second
operand is not evaluated.
Xor
Performs a Boolean exclusive
or operation on the bits. (The result bit is 1 if either of the
source bits is 1, but not both.)
Not
Performs a Boolean Not operation on
the bits in the operand. This is a unary operator. (The result is 1 if the source bit is 0 and 0 if the source bit is 1.)
- Logical Operators
Logical operators
are operators that require Boolean operands. They are:
And
The result is True if and only if
both of the operands are True; otherwise, the result is False.
Or
The result is True if either or
both of the operands is True; otherwise, the result is False.
Xor
The result is True if one and
only one of the operands is True; otherwise, the result is False.
Not
This is a unary operator. The result is True if the operand is False; False if the operand is True.
- Operator Precedence
Operator precedence defines the order in which operators are evaluated. For example, the expression 1 + 2 * 3 has the value 9 if the addition is performed first but has the value 7 if the multiplication is performed first. To avoid such ambiguity, languages must define the order in which operations are evaluated. Visual Basic .NET divides the operators into groups and defines each group's precedence relative to the others. Operators in higher-precedence groups are evaluated before operators in lowerprecedence groups. Operators within each group have the same precedence relative to each other. When an expression contains multiple operators from a single group, those operators are evaluated from left to right.
Category
|
Operator
|
Arithmetic and
|
Exponentiation
|
concatenation
|
|
|
Negation
|
|
Multiplication
and division
|
|
Integer
division
|
|
Modulus
arithmetic
|
|
Addition
and subtraction, string concatenation (+)
|
|
String
concatenation (&)
|
Comparison operators
|
Equality,
inequality, greater than, less than, greater than or equal to, less than or
equal to, Is, TypeOf, Like
|
Logical and bitwise operators
|
Negation
(Not)
|
|
Conjunction
(And, AndAlso)
|
|
Disjunction
(Or, OrElse, Xor)
|
Parentheses override the default order of evaluation. For
example, in the expression 1 + 2 * 3, the
multiplication is performed before the addition, yielding a value of 7. To perform the addition first, the expression can be
rewritten as (1 + 2) * 3, yielding a
result of 9.
- Operator Overloading
Operator overloading
is a feature that some languages (C#, for example) provide to allow developers
to specify how the built-in operators (+, -, *, /, =, etc.) should behave when applied to programmerdefined
types. For example, the developer of a type representing complex numbers could
use operator overloading to specify appropriate functionality for the built-in
arithmetic operators when applied to operands of the custom type.
The .NET Framework supports operator overloading, but .NET
languages are not required to do so. The current version of Visual Basic .NET
doesn't support operator overloading, although there's no reason that Microsoft
couldn't add it in the future. Components that are written in other languages
may overload operators, but Visual Basic .NET will not be aware of the
overloads. Well-designed components provide an alternative mechanism for
accessing the functionality provided by the overloads. For example, if a
component written in C# provides a class that overloads the + operator, it should also provide a method that takes
two parameters and returns their sum. Thus, what would be written as:
c = a + b
in a language that supports overloading would be written
as:
c = MyCustomType.Add(a, b)
in Visual Basic .NET.
The
name of the actual method would depend on the component's implementer.
Statements
Visual Basic .NET is a line-oriented language, in which
line breaks generally indicate the ends of statements. However, there are times
when a programmer may wish to extend a statement over several lines or have
more than one statement on a single line.
To extend a statement over several lines, use the
line-continuation character, an underscore (_). It must be the
last character on its line, and it must be immediately preceded by a space
character.
Lines connected in this way become a single logical line.
Here is an example:
Dim strSql As String =
"SELECT Customers.CompanyName," _
& " COUNT(Orders.OrderID) AS
OrderCount" _
& " FROM Customers INNER JOIN
Orders" _
& " ON Customers.CustomerID =
Orders.CustomerID" _
& " GROUP BY Customers.CompanyName"
_ & " ORDER BY OrderCount
DESC"
A line break can occur only where whitespace is allowed.
To place two or more statements on a single line, use the
colon (:) between the statements, like this:
i = 5 : j = 10
- Option Statements
There are three Option statements,
which affect the behavior of the compiler. If used, they must appear before any
declarations in the same source file. They control the compilation of the
source code in the file in which they appear. They are:
Option Compare
The Option Compare statement
controls the manner in which strings are compared to each other. The syntax
is:
Option Compare [ Binary |
Text ]
If Binary is specified, strings are compared
based on their internal binary representation (i.e., string comparisons are
case-sensitive). If Text is specified, strings are compared
based on case-insensitive alphabetical order. The default is Binary.
Option Explicit
The Option Explicit statement
determines whether the compiler requires all variables to be explicitly
declared. The syntax is:
Option Explicit [ On | Off
]
If On is specified, the compiler requires all
variables to be declared. If Off is specified, the compiler considers a
variable's use to be an implicit declaration. It is considered good programming
practice to require declaration of variables. The default is On.
Option Strict
The Option Strict statement
controls the implicit type conversions that the compiler will allow. The syntax
is:
Option Strict [ On | Off ]
If On is specified, the
compiler only allows implicit widening conversions; narrowing conversions must
be explicit. If Off is specified, the compiler allows implicit narrowing conversions as
well. This could result in runtime exceptions not foreseen by the developer. It
is considered good programming practice to require strict type checking. The
default is Off- Branching Statements
Visual Basic .NET supports a number of branching statements
that interrupt the sequential flow of program execution and instead allow it to
jump from one portion of a program to another. These can be either conditional
statements (such as If or Select Case) or unconditional (such as Call
and Exit).
- Call
The Call statement invokes a subroutine or
function. For example:
Call SomeMethod( )
When the invoked subroutine or function finishes, execution
continues with the statement following the Call statement. If
a function is invoked, the function's return value is discarded.
The Call statement is redundant because
subroutines and functions can be invoked simply by naming them:
SomeMethod( )
- Exit
The Exit statement causes execution to exit the
block in which the Exit statement appears. It is generally
used to prematurely break out of a loop or procedure when some unusual
condition occurs.
The Exit statement should be avoided when
possible because it undermines the structure of the block in which it appears.
For example, the exit conditions of a For loop should be
immediately apparent simply by looking at the For statement. It
should not be necessary to read through the entire loop to determine if there
are additional circumstances under which the loop might exit. If a given For loop truly needs an Exit statement,
investigate whether a different loop construct would be better suited to the
task. If a given procedure truly needs an Exit statement,
investigate whether the procedure is factored appropriately.
The Exit statement has a different form for
each type of block in which it can be used, as listed here:
Exit Do
Exits a Do loop. Execution continues with the first
statement following the Loop statement.
Exit For
Exits a For loop. Execution continues with the
first statement following the Next
statement.
Exit Function
Exits a function. Execution continues with the first
statement following the statement that called the function.
Exit Property
Exits a property get or property set procedure. Execution
continues with the first statement following the statement that invoked the
property get or property set procedure.
Exit Sub
Exits a subroutine. Execution continues with the first
statement following the statement that called the subroutine.
Exit Try
Exits
the Try clause of a Try block. If the Try block has a Finally clause, execution continues with the first statement in the Finally clause. If the Try block does not have
a Finally clause, execution continues with the first statement following the Try block.
- Goto
The Goto statement transfers execution to the
first statement following the specified label. For example:
' ...
Goto MyLabel
' ...
MyLabel:
' ...
The label must be in the same procedure as the Goto statement.
The Goto statement is generally avoided in
structured programming because it often leads to code that is difficult to read
and debug.
- If
The If statement controls whether a block of
code is executed based on some condition. The simplest form of the If statement is:
If expression Then statements End If
expression is any expression that can be interpreted
as a Boolean value. If expression is True, the
statements within the If block are executed. If expression is False, those statements are skipped.
To provide an alternative set of statements to execute when
expression is False, add an Else clause, as
shown here:
If expression Then statements Else statements
End If
If expression is True, only the
statements in the If clause are executed. If expression is False, only the statements in the Else
clause are executed.
Finally, a sequence of expressions can be evaluated by
including one or more ElseIf clauses, as shown here:
If expression Then statements ElseIf expression Then statements ElseIf expression Then statements Else statements
End If
The
first If or ElseIf clause whose expression evaluates to True will have its
statements executed. Statements in subsequent ElseIf clauses will not be
executed, even if their corresponding expressions are also True. If none of the
expressions evaluate to True, the statements in the Else clause will be executed. The Else clause can be
omitted if desired.
- If
The If statement controls whether a block of
code is executed based on some condition. The simplest form of the If statement is:
If expression Then statements End If
expression is any expression that can be interpreted
as a Boolean value. If expression is True, the
statements within the If block are executed. If expression is False, those statements are skipped.
To provide an alternative set of statements to execute when
expression is False, add an Else clause, as
shown here:
If expression Then statements Else statements
End If
If expression is True, only the
statements in the If clause are executed. If expression is False, only the statements in the Else
clause are executed.
Finally, a sequence of expressions can be evaluated by
including one or more ElseIf clauses, as shown here:
If expression Then statements ElseIf expression Then statements ElseIf expression Then statements Else statements
End If
The
first If or ElseIf clause whose expression evaluates to True will have its
statements executed. Statements in subsequent ElseIf clauses will not be
executed, even if their corresponding expressions are also True. If none of the
expressions evaluate to True, the statements in the Else clause will be executed. The Else clause can be
omitted if desired.
- RaiseEvent
The RaiseEvent statement fires the given event.
After the event has been fired to all listeners, execution continues with the
first statement following the RaiseEvent
statement. See Section
2.20 later in this chapter for more information.
- Return
The Return statement exits a function and
provides a return value to the caller of the function. Execution continues with
the first statement following the statement that called the function. Here is
an example:
Public Shared Function
MyFactorial(ByVal value As Integer) As Integer
Dim retval As Integer = 1
Dim i As Integer For i = 2 To value retval *= i Next
Return retval
End Function
Another way to return a value to the caller of the function
is to assign the value to the function name and then simply drop out of the
bottom of the function. This is how it was done in Visual Basic 6 (and can
still be done in Visual Basic .NET). Here is an example:
Public Shared Function
MyFactorial(ByVal value As Integer) As Integer
Dim retval As Integer = 1
Dim i As Integer For i = 2 To value retval *= i
Next
MyFactorial = retval
End Function
- Select Case
The Select Case statement chooses a block of
statements to execute based on some value. For example:
Select Case strColor Case "red"
' ...
Case "green"
' ...
Case "blue"
' ...
Case "yellow"
' ...
Case Else
' ...
End Select
If strColor in this example contains "blue", only the statements in the Case "blue" clause are executed. If
none of the Case clauses matches the value in the Select Case statement, the statements in the Case Else clause are executed. If more than one Case clause matches the given value, only the statements
in the first matching Case clause are executed.
Case statements can include multiple values
to be matched against the value given in the Select Case
statement. For example:
Case "red",
"green", "blue", strSomeColor
This case will be matched if the value in the Select Case statement is "red",
"green", "blue",
or the value contained in strSomeColor. The To
keyword can be used to match a range of values, as shown here:
Case "apples" To
"oranges"
This Case statement matches any string value
that falls alphabetically within this range.
The Is keyword can be used for matching an
open-ended range:
Case Is >
"oranges"
Don't
confuse this use of the Is keyword with the Is comparison operator.
Iteration
Statements
Iteration
statements, also known as looping
statements, allow a group of statements to be executed more than once. The
group of statements is known as the body
of the loop. Three statements fall under this category in Visual Basic .NET: Do, For, and For Each
- Do
The Do loop executes a block of statements
either until a condition becomes true or while a condition remains true. The
condition can be tested at the beginning or at the end of each iteration. If
the test is performed at the end of each iteration, the block of statements is
guaranteed to execute at least once. The Do loop can also be
written without any conditions, in which case it executes repeatedly until and
unless an Exit Do statement is executed within the body of
the loop. Here are some examples of Do loops:
Do While i < 10
' ...
Loop
Do Until i >= 10
' ...
Loop
Do
' ...
Loop While i < 10
Do
' ...
Loop Until i >= 10
Do
' ... Loop
- For
The For loop executes a block of statements a
specified number of times. The number of iterations is controlled by a loop
variable, which is initialized to a certain value by the For statement, then is incremented for each iteration of
the loop. The statements in the body of the loop are repeatedly executed until
the loop variable exceeds a given upper bound.
The syntax of the For loop is:
For variable = expression To expression
[ Step expression ] statements
Next [ variable_list ]
The loop variable can be of any numeric type. The variable
is set equal to the value of the first expression before entering the first
iteration of the loop body. Prior to executing each iteration of the loop, the
loop variable is compared with the value of the second expression. If the value
of the loop variable is greater than the expression (or less than the
expression if the step expression is negative), the loop exits and execution
continues with the first statement following the Next
statement.
The step expression is a numeric value that is added to the
loop variable between loop iterations. If the Step clause is
omitted, the step expression is taken to be 1.
The Next statement marks the end of the loop
body. The Next keyword can either appear by itself in the statement
or be followed by the name of the loop variable. If For
statements are nested, a single Next statement can
terminate the bodies of multiple loops. For example:
For i = 1 To 10
For j = 1 To 10
For k = 1 To 10
' ... Next k, j, I
This code is equivalent to the following:
For i = 1 To 10
For j = 1 To 10 For k = 1 To 10
' ...
Next
Next Next
I recommend the latter style, since it is considered more
structured to terminate each block explicitly.
It is interesting to note that the For
loop is equivalent to the following Do loop
construction (assuming that step_expression is nonnegative):
loop_variable =
from_expression Do While loop_variable
<= to_expression statements
loop_variable +=
step_expression Loop
If step_expression is negative, the For loop is equivalent to this (only the comparison in
the Do statement is different):
loop_variable =
from_expression Do While loop_variable
>= to_expression statements
loop_variable +=
step_expression Loop
- For Each
The For Each statement is
similar to the For statement, except that the loop
variable need not be numeric, and successive iterations do not increment the
loop variable. Instead, the loop variable takes successive values from a
collection of values. Here is the syntax:
For Each variable In expression statements Next
[ variable ]
The loop variable can be of any type. The expression must
be a reference to an object that exposes the IEnumerable
interface (interfaces are discussed later in this chapter). Generally, types
that are considered collections expose this interface. The .NET Framework class
library provides several useful collection types, which are listed in Chapter
3. (See Section 2.5.4 earlier in this chapter for an
explanation of what constitutes a collection type.) The type of the items in
the collection must be compatible with the type of the loop variable. The
statements in the body of the loop execute once for each item in the collection.
During each iteration, the loop variable is set equal to each consecutive item
in the collection.
Because all Visual Basic .NET arrays expose the IEnumerable interface, the For Each statement can be used to iterate through the
elements of an array. For example:
Dim a( ) As Integer = {1, 2, 3, 4, 5}
Dim b As Integer
For Each b In a
Console.WriteLine(b) Next
This is equivalent to the following code:
Dim a( ) As Integer = {1, 2, 3, 4, 5}
Dim b As Integer
Dim i As Integer
For i = a.GetLowerBound(0)
To a.GetUpperBound(0) b = a(i)
Console.WriteLine(b)
Next
Because all arrays in Visual Basic .NET implicitly derive
from the Array type (in the System namespace), the a
array in this example has access to methods defined on the Array type
(specifically GetLowerBound and GetUpperBound).
In case you're interested, here is the equivalent code
using a Do loop. This is essentially what the For Each statement is doing under the covers,
although the For Each construct is
likely to compile to faster code.
Dim a( ) As Integer = {1, 2, 3, 4, 5}
Dim b As Integer
Dim e As Object =
a.GetEnumerator( )
Do While
CType(e.GetType(
).InvokeMember("MoveNext", _
Reflection.BindingFlags.InvokeMethod,
Nothing, e, Nothing), Boolean)
b = CType(e.GetType( ).InvokeMember("Current", _
Reflection.BindingFlags.GetProperty,
Nothing, e, Nothing), Integer)
Console.WriteLine(b)
Loop
Mathematical
Functions
Mathematical
functions are provided through the Math class (defined in the System
namespace).
Input/Output
File and Internet I/O features are provided by the .NET
Framework class library and will be briefly touched below. In
addition, Visual Basic .NET provides its own class library that includes
functions for opening, reading, and closing files. File access and
network-protocol programming
Classes
A class is one
form of data type. As such, a class can be used in contexts where types are
expected— in variable declarations, for example. In object-oriented design,
classes are intended to represent the definition of real-world objects, such as
customer, order, product, etc. The
class is only the definition, not an object itself. An object would be a customer, an order, or a product. A
class declaration defines the set of members—fields, properties, methods, and
events—that each object of that class possesses. Together, these members define
an object's state, as well as its functionality. An object is also referred to
as an instance of a class. Creating
an object of a certain class is called instantiating
an object of the class.
Example. A class definition
Public Class Employee
Public EmployeeNumber As Integer
Public FamilyName As String
Public GivenName As String
Public DateOfBirth As Date
Public Salary As Decimal
Public Function Format( ) As String
Return GivenName & " "
& FamilyName
End Function
End Class
The code in Example 2-4 defines a
class called Employee. It has five public fields
(also known as data members) for
storing state, as well as one member
function. The class could be used as shown in Example 2-5.
Example. Using a class
Dim emp As New
Employee( )
emp.EmployeeNumber = 10
emp.FamilyName = "Rodriguez" emp.GivenName = "Celia"
emp.DateOfBirth = #1/28/1965# emp.Salary = 115000
Console.WriteLine("Employee
Name: " & emp.Format( ))
Console.WriteLine("Employee
Number: " & emp.EmployeeNumber)
Console.WriteLine("Date
of Birth: " & emp.DateOfBirth.ToString("D", Nothing))
Console.WriteLine("Salary:
" & emp.Salary.ToString("C", Nothing))
The resulting output is:
Employee Name: Celia
Rodriguez
Employee Number: 10
Date of Birth: Thursday,
January 28, 1965 Salary: $115,000.00
- Object Instantiation and New
Object instantiation is done using the New keyword. The New keyword is, in
effect, a unary operator that takes a type identifier as its operand. The
result of the operation is a reference to a newly created object of the given
type. Consider the following:
Imports System.Collections
' ...
Dim ht As Hashtable ht =
New Hashtable( )
The Dim statement declares a variable that is
capable of holding a reference to an object of type Hashtable, but it doesn't
actually create the object. The code in the line following the Dim statement instantiates an object of type Hashtable
and assigns to the variable a reference to the newly created object. As with
any other variable declaration, the assignment can be done on the same line as
the declaration, as shown here:
Imports System.Collections
' ...
Dim ht As Hashtable = New
Hashtable( )
Visual Basic .NET permits a typing shortcut that produces
the same result:
Imports System.Collections
' ...
Dim
ht As New Hashtable( )
- Constructors
When a class is instantiated, some initialization often
must be performed before the type can be used. To provide such initialization,
a class may define a constructor. A
constructor is a special kind of method. It is automatically run whenever an
object of the class is instantiated. Constructor declarations use the same
syntax as regular method declarations, except that in place of a method name,
the constructor declaration uses the keyword New. For
example:
Public Class SomeClass
Public Sub New( )
' Do any necessary initialization of the
object here.
End Sub End Class
To invoke the constructor, a new object must be
instantiated:
Dim obj As New
SomeClass( )
Note the parentheses (( )) following the
name of the class. Until you get used to it, this method-style syntax following
a class name may appear odd. However, the empty parentheses indicate that the
class's constructor takes no arguments.
Constructors can take arguments, if they are necessary for
the initialization of the object:
Public Class SomeClass
Dim m_value As Integer
Public Sub New(ByVal InitialValue As
Integer) m_value = InitialValue
End Sub
End Class
When objects of this class are instantiated, a value must
be provided for the constructor's argument:
Dim obj As New
SomeClass(27)
Constructors can be overloaded, if desired. For example:
Public Class SomeClass
Dim m_value As Integer
Public Sub New( )
m_value = Date.Today.Day ' for example
End Sub
Public Sub New(ByVal InitialValue As
Integer) m_value = InitialValue
End Sub
End Class
The constructor that is called depends on the arguments that
are provided when the class is instantiated, as shown here:
Dim obj1 As New
SomeClass( ) ' calls parameterless
constructor
Dim obj2 As New
SomeClass(100) ' calls parameterized constructor
Constructors are usually marked Public.
However, there are times when it may be desirable to mark a constructor as Protected or Private. Protected
access prohibits the class from being instantiated by any class other than a
class derived from this class. Private access prohibits the class from being
instantiated by any code other than its own. For example, a particular class
design might require that the class itself be in control of whether and when
instances are created. Example 2-6 shows a
class that implements a crude form of object pooling.
- Fields
Fields, also
known as data members, hold the
internal state of an object. Their declarations appear only within class and
structure declarations. Field declarations include an access modifier, which determines how visible the field is from
code outside the containing class definition. Access modifiers were discussed
earlier in this chapter, under Section 2.10.
The value stored in a field is specific to a particular
object instance. Two instances can have different values in their corresponding
fields. For example:
Dim emp1 As New
Employee( )
Dim emp2 As New
Employee( )
emp1.EmployeeNumber = 10
emp2.EmployeeNumber = 20 ' Doesn't affect emp1.
Sometimes it is desirable to share a single value among all
instances of a particular class. Declaring a field using the Shared keyword does this, as shown here:
Public Class X
Public Shared a As Integer End Class
Changing the field value through one instance affects what
all other instances see. For example:
Dim q As New X( )
Dim r As New X( )
q.a = 10
r.a = 20
Console.WriteLine(q.a) '
Writes 20, not 10.
Shared fields are also accessible through the class name:
Console.WriteLine(X.a)
- Handling Events
When a field is of an object type that exposes events, the
field's enclosing class may define methods for handling those events. For an
explanation of events, see Section 2.20 later in
this chapter.
Here is an example:
Imports
System.Data.SqlClient
Public Class
EventHandlingTest
Private WithEvents m_cn As SqlConnection
Public Sub MySqlInfoMessageEventHandler( _
ByVal sender As Object, _
ByVal e As SqlInfoMessageEventArgs _
) Handles m_cn.InfoMessage
Dim sqle As SqlError
For Each sqle In e.Errors
Debug.WriteLine(sqle.Message)
Next
End Sub
' ...
End Class
This class has a field, m_cn, that holds a database
connection. The field is declared with the
WithEvents keyword, so the class is capable
of receiving and handling events raised by the Connection object. In order to
handle the Connection object's InfoMessage event, the class defines a method
having the appropriate parameter list and a Handles
clause:
Public Sub
MySqlInfoMessageEventHandler( _
ByVal sender As Object, _
ByVal e As SqlInfoMessageEventArgs _
) Handles m_cn.InfoMessage
This
declaration signifies that when the InfoMessage event is raised by the object
referenced in m_cn, the MySQLInfoMessageEventHandler method should be called to
handle it. The body of the event handler in this case simply outputs the
messages received from SQL Server
- Inheritance
Inheritance is
one way to reuse and extend previously written code. A program's design often
requires several classes as variations of a common theme. Consider a drawing
program that deals with many shapes. Such a program would probably define a
class for each kind of shape. However, there would be much in common among such
classes, including many of their fields, methods, and events. Inheritance
allows these common features to be extracted into a base class from which the various specific shape classes are derived. Example 2-7 shows a base
class called Shape, two utility classes used by Shape (Point and Extent), and
two classes derived from Shape (Circle and Square).
- Methods
Methods are
members that contain code. They are either subroutines (which don't have a
return value) or functions (which do have a return value).
Subroutine definitions look like this:
[ method_modifiers ] Sub [ attribute_list
] _
method_name ( [ parameter_list ]
) [ handles_or_implements ]
[ method_body ] End Sub
Function definitions look like this:
[ method_modifiers ]
Function [ attribute_list ] _
method_name ( [ parameter_list
] ) [ As type_name ] _
[ handles_or_implements
]
[ method_body ] End Function
The elements of method definitions are:
method_modifiers
Keywords that affect the accessibility or use of the
method. These include the following:
Access modifiers
Public, Protected, Friend, Protected Friend, or Private, as
described in Table
25. If no access-modifier keyword is given, Public
is assumed. Override modifiers
Overrides, MustOverride, Overridable, or NotOverridable. See Section 2.14.6.6.
Overloads
keyword
Specifies that this method is an overload. See Section
2.14.6.7 later in this section.
Shared keyword
Specifies that this method does not access object state.
That means that the method does not access any nonshared members.
Sub or
Function keyword
Specifies whether this method is a subroutine or a
function.
attribute_list
An optional list of attributes to be applied to the method.
See Section
2.22 later in this chapter.
method_name
The name of the method.
parameter_list
An optional list of formal parameters for the method. See Section
2.14.6.1.
As type_name
For functions only, the data type of the value returned
from this function. If Option Strict is off, the As type_name clause is optional; otherwise, it is
required. If it is omitted, the function's return type defaults to Object.
Subroutine declarations do not have an As type_name
clause.
handles_or_implements
Either the Handles keyword
followed by a list of events from the enclosing class's data members, or the Implements keyword followed by a list of methods from an
interface implemented by the enclosing class. See Section 2.20 and
Section
2.15 later in this chapter.
method_body
Visual Basic .NET statements.
End Sub or End
Function keywords
Indicates
the end of the method definition.
- Interfaces
It is useful to make a distinction between a class's interface and its implementation. Conceptually, the interface of a class is the set
of members that are visible to users of the class—i.e., the class's public
members. The public members are thought of as comprising the class's interface
because they are the only way that code outside of the class can interact
(i.e., interface) with objects of that class. In contrast, the implementation
is comprised of the class's code plus the set of members that are not
public.
It is possible to take this interface concept further and
separate interface definition from class definition altogether. This has
benefits that will be shown shortly. To define an interface, use the Interface statement:
Public Interface
ISomeInterface
Sub SomeSub(
)
Function SomeFunction( ) As Integer
Property SomeProperty( ) As String
Event SomeEvent( _
ByVal sender As Object, _
ByVal e As SomeEventArgs _
)
End Interface
An interface declaration defines methods, properties, and
events that will ultimately be implemented by some class or structure
definition. Because interfaces never include any implementation, the
declarations are headers only—never any implementation code; End Sub, End Function, or End Property statements; or property get or set blocks. There
are no access modifiers (Public, Private, etc.)
because all members of an interface are public by definition. By convention,
interface names start with the letter "I".
To provide an implementation for a given interface, it is
necessary to define a class or structure. For example, the following class
implements the interface defined earlier:
Public Class SomeClass
' This indicates that the class implements
the methods, ' properties, and events
of the ISomeInterface interface.
Implements ISomeInterface
' This method implements the SomeSub method
of the
' ISomeInterface interface.
Private Sub SomeSub( ) Implements ISomeInterface.SomeSub
'
...
End Sub
' This method implements the SomeFunction
method of the
' ISomeInterface interface.
Private Function SomeFunction( ) As Integer _ Implements ISomeInterface.SomeFunction
' ...
End Function
' This property implements the SomeProperty
property of the
' ISomeInterface interface.
Private Property SomeProperty( ) As String _
Implements ISomeInterface.SomeProperty
Get
' ...
End Get
Set
' ...
End Set
End Property
' This event implements the SomeEvent event
of the
' ISomeInterface interface.
Private Event SomeEvent( _
ByVal sender As Object, _
ByVal e As SomeEventArgs _
) Implements ISomeInterface.SomeEvent
End Class
The key elements of this class definition are:
•
The class-declaration header is immediately
followed by the Implements statement, indicating that this
class will expose the ISomeInterface interface:
•
Public Class SomeClass
•
' This indicates that the
class implements the methods,
•
' properties, and events
of the ISomeInterface interface.
Implements ISomeInterface
This information is compiled into the class. Class users
can find out whether a given class implements a given interface by attempting
to assign the object reference to a variable that has been declared of the
interface type, like this:
Dim obj As Object Dim ifce
As ISomeInterface
' ...
' Get an object reference
from somewhere.
obj = New SomeClass( )
' ...
' Try to convert the
object reference to a reference of type
' ISomeInterface. If the
object implements the ISomeInterface
' interface, the
conversion succeeds. If the object doesn't
' implement the
ISomeInterface interface, an exception of
' type
InvalidCastException (defined in the System namespace)
' is thrown. ifce =
CType(obj, ISomeInterface)
• For
each method, property, and event in the interface, there is a corresponding
method, property, or event in the class that has precisely the same signature
and return value. The names don't have to match, although they match in the
example.
• The
declaration header for each method, property, and event in the class that
implements a corresponding item in the interface must have an implements clause. This is the keyword Implements followed by the qualified name of the
interface method, property, or event being implemented.
Additional things to note about implementing interfaces
include:
• The
access modifiers in the class-member declarations need not be Public. Note that in the example all the members are
marked as Private. This means that the members are accessible only
when accessed through the ISomeInterface interface. This will be shown in a
moment.
• The
class definition can include members that are not part of the implemented
interface. These can be public if desired. This results in a class that
effectively has two interfaces: the default
interface, which is the set of members defined as Public
in the class definition; and the implemented
interface, which is the set of members defined in the interface named in
the Implements statement.
• Classes
are permitted to implement multiple interfaces.
To access members defined by an interface, declare a
variable as that interface type and manipulate the object through that
variable. For example:
Dim x As ISomeInterface =
New SomeClass( )
x.SomeFunction( )
This code declares x as a reference to
an object of type ISomeInterface. That's right: interface definitions define
new types. Declared in this way, x can take a
reference to any object that implements the ISomeInterface
interface and access all the members that ISomeInterface defines,
confident that the underlying object can handle such calls. This is a powerful
feature of defining and implementing explicit interfaces. Objects that
explicitly implement an interface can be used in any context in which that
interface is expected; objects that implement multiple interfaces can be used
in any context in which any of the interfaces is expected.
Interface definitions can inherit from other interface
definitions in the same way that classes can inherit from other classes. For
example:
Public Interface
ISomeNewInterface
Inherits ISomeInterface
Sub SomeNewSub( )
End Interface
This
defines a new interface called ISomeNewInterface that has all the members of the ISomeInterface interface plus a new
member, called SomeNewSub. Any class or structure that implements the ISomeNewInterface interface must
implement all members in both interfaces. Any such class is then considered to
implement both interfaces and could be used in any context where either ISomeInterface or ISomeNewInterface is required
- Structures
Structures define value types. Variables of a value type
store an actual value, as opposed to a reference to a value stored elsewhere.
Contrast this with classes, which define reference types. Variables of a
reference type store a reference (a pointer) to the actual value. See the
discussion of value types versus reference types in Section 2.5
earlier in this chapter. Example 2-8 shows a
structure definition.
- Enumerations
An enumeration is
a type whose values are explicitly named by the creator of the type. The .NET
Framework and Visual Basic .NET define many enumerations for their and your
use. In addition, Visual Basic .NET provides syntax for defining new enumerations.
Here is an example:
Public Enum Rainbow
Red
Orange
Yellow
Green
Blue
Indigo
Violet
End Enum
This declaration establishes a new type, called Rainbow.
The identifiers listed within the body of the declaration become constant
values that may be assigned to variables of the Rainbow type. Here is a
declaration of a variable of type Rainbow and an initial assignment to it:
Dim myRainbow As Rainbow =
Rainbow.Blue
Note that the value name is qualified by the type name.
Enumerations are value types that implicitly inherit from
the .NET Framework's System.Enum type (which in turn inherits from System.ValueType).
That means that every enumeration has access to the members defined by
System.Enum. One such member is the ToString method, which returns a string
containing the name of the value. This is handy for printing:
Dim myRainbow As Rainbow =
Rainbow.Blue
Console.WriteLine("The
value of myRainbow is: " & myRainbow.ToString( ))
This code results in the following output:
The value of myRainbow is:
Blue
The values of an enumeration are considered as ordered.
Thus, comparisons are permitted between variables of the enumeration type:
Dim myRainbow As Rainbow
Dim yourRainbow As Rainbow
' ...
If myRainbow <
yourRainbow Then
' ... End If
Variables of an enumeration type can be used as indexes in For...Next statements. For example:
For myRainbow =
Rainbow.Red To Rainbow.Violet
' ...
Next
Internally, Visual Basic .NET and the .NET Framework use
values of type Integer to represent the values of the enumeration. The compiler
starts with 0 and assigns increasing Integer values to each name in the
enumeration. It is sometimes useful to override the default Integer values that
are assigned to each name. This is done by adding an initializer to each
enumeration constant. For example:
Public Enum
MyLegacyErrorCodes
NoError = 0
FileNotFound = -1000
OutOfMemory = -1001
InvalidEntry = -2000 End Enum
It is also possible to specify the type of the underlying
value. For example:
Public Enum Rainbow As
Byte
Red
Orange
Yellow
Green
Blue
Indigo
Violet
End Enum
This could be an important space-saving measure if many
values of the enumeration will be stored somewhere. The only types that can be
specified for an enumeration are Byte, Short, Integer, and Long.
Sometimes enumerations are used as flags, with the idea
that multiple flags can be combined in a single value. Such an enumeration can
be defined by using the Flags attribute. (Attributes are discussed
later in this chapter.) Here is an example:
<Flags( )> Public Enum Rainbow
Red = 1
Orange = 2
Yellow = 4
Green = 8
Blue = 16
Indigo = 32
Violet = 64 End Enum
Note two important things in this definition:
• The
first line of the definition starts with <Flags( )>.
This indicates that values of this type can be composed of multiple items from
the enumeration.
• The
items in the enumeration have values that are powers of two. This ensures that
each combination of items has a unique sum. For example, the combination of
Yellow, Blue, and Violet has a sum of 84, which can't be attained with any
other combination of items.
Individual values are combined using the Or operator.
The ToString method is smart enough to sort out the value
names when creating a string representation of the value. For example, given the
previous assignment, consider the following call to the ToString method:
Console.WriteLine(myRainbow.ToString( ))
This statement produces the following output:
Green, Blue
- Exceptions
Sometimes errors or exceptional conditions prohibit a
program from continuing its current activity. A classic example is division by
zero:
Dim x As Integer = 0
Dim y As Integer = 1 \ x
When the process hits the line containing the integer
division, an exception occurs. An
exception is any occurrence that is not considered part of normal, expected
program flow. The runtime detects, or catches,
this exception and takes appropriate action, generally resulting in termination
of the offending program.
Visual Basic .NET programs can and should be written to
catch exceptions themselves. This is done by wrapping potentially dangerous
code in Try...End Try blocks. shows how to catch the divide-by-zero exception.
- Delegates
A delegate is a
programmer-defined type that abstracts the ability to call a method. A
delegate-type declaration includes the declaration of the signature and return
type that the delegate encapsulates. Instances of the delegate type can then
wrap any method that exposes the same signature and return type, regardless of
the class on which the method is defined and whether the method is an instance
method or shared method of the defining class. The method thus wrapped can be
invoked through the delegate object. The delegate mechanism provides polymorphism
for methods having the same signature and return type.
Delegates are often used to implement callback mechanisms.
Imagine a class that will be used by a program you are writing. This class
provides some useful functionality, including the ability to call in to a
method that you must implement within your program. Perhaps this callback
mechanism is provided to feed your program data as it becomes available in the
class you are using. One way to achieve this capability is through the use of
delegates. Here's how:
1. The
writer of the class you're using (call it a server class) declares a public
delegate type that defines the signature and return value of the method that
you will implement.
2. The
writer of the server class exposes a method for clients of the class to pass in
an instance of the delegate type.
3. You
implement a method having the appropriate signature and return value.
4. You
instantiate a new object of the delegate type.
5. You
connect your method to your delegate instance.
6. You
call the method defined in Step 2, passing in your delegate instance.
7. The
server class now has a delegate instance that wraps your method. The class can
call your method through the delegate at any time.
8. Depending
on the application, it might be appropriate for the writer of the server class
to provide a method that allows the client application to disconnect its
delegate from the server to stop receiving callbacks.
4 comments:
This article is really very interesting and enjoyable. I think its must be helpful and informative for us. Thanks for sharing your nice post
Home Tutors in Lucknow | Home Tuition Service
very informative blog and useful article thank you for sharing with us , keep posting learn
more about Dot net
.NET Online Course Hyderabad
Thank you so much for sharing such a isshtech.com superb information's with us. Your website is very cool. we are impressed by the details that you have on your site.we Bookmarked this website toklaapp.com. keep it up and again thanks.
Good job in presenting the correct content with the clear explanation. The content looks real with valid information. Good Work
Dot Net Training in Chennai | Dot Net Training in anna nagar | Dot Net Training in omr | Dot Net Training in porur | Dot Net Training in tambaram | Dot Net Training in velachery
Post a Comment