8/13/2019 Programming .NET With Visual Basic.net
1/121
Programming .NET With Visual Basic.NET
Copyright 2001 K.M.Hussain - 1 -
Contents
1. Introduction to .NET Framework 2
The Common Language Runtime, The Intermediate Language,Mixed Language Programming
2. VB.NET Language fundamentals . 6Branching and Looping, Basic and User Defined Types,User Defined Methods.
3. Object Oriented Programming in VB.NET . 14Classes and Namespaces,Interfaces and Delegates,Raising and Handling Events
4. Reflection 33Exposing assemblies and types,Dynamic instantiation and Invocations,Creating and Using Attributes
5. Multithreading 40Processes and Threads, Thread synchronization and Coordination,Asynchronous Programming Model
6. Streams 49Input and Output Streams, Object Serialization,Working with XML Documents.
7 Sockets .. 60Networking Basics, Client-Server programming with TCP/IP,
Multicasting with UDP.
8 Distributed Programming with Remoting 68Remoting Architecture, Server-activated remoting objects.Client-activated remoting objects.
9. Database Programming with ADO.NET 77Accessing and Updating Data using ADO, Paramaterized SQL and Stored Procedures,Working with Disconnected Datasets.
10 GUI Programming with Windows Forms 88Windows Forms and Controls, Windows Forms and Data Access,Creating Custom Controls.
11 Web Programming with ASP.NET . 97Web Forms and Server Controls, Web Forms and Data Access,Creating Web-Services.
12. Intereop and Enterprise Services . 112Using Native Dlls and COM Components,Messaging with MSMQ,
Creating Serviced Components withCOM+.
8/13/2019 Programming .NET With Visual Basic.net
2/121
Programming .NET With Visual Basic.NET
Copyright 2001 K.M.Hussain - 2 -
Chapter 1: Introduction to the .NET Framework
1.1 Common Language Runtime: The .NET Framework provides a run-time
environment called the Common Language Runtime, which manages the execution of
code and provides services that make the development process easier. Compilers and
tools expose the runtimes functionality and enable you to write code that benefits fromthis managed execution environment. Code that you develop with a language compiler
that targets the runtime is called managed code; itbenefits from features such as cross-language integration, cross-language exception handling, enhanced security, versioning
and deployment support, a simplified model for component interaction, and debugging
and profiling services.
The runtime automatically handles object layout and manages references to objects,
releasing them when they are no longer being used. Objects whose lifetimes are managedin this way by the runtime are called managed data. Automatic memory management
eliminates memory leaks as well as some other common programming errors.
The Common Language Runtime makes it easy to design components and applicationswhose objects interact across languages. Objects written in different languages cancommunicate with each other, and their behaviors can be tightly integrated. For example,
you can define a class, then, using a different language, derive a class from your originalclass or call a method on it. You can also pass an instance of a class to a method on a
class written in a different language. This cross-language integration is possible because
language compilers and tools that target the runtime use a common type system defined
by the runtime, and they follow the runtimes rules for defining new types, as well ascreating, using, persisting, and binding to types.
Registration information and state data are no longer stored in the registry where it can bedifficult to establish and maintain; instead, information about the types you define (and
their dependencies) is stored with the code as metadata, making the tasks of component
replication and removal much less complicated. The Common Language Runtime canonly execute code in assemblies. An assemblyconsists of code modules and resources
that are loaded from disk by the runtime. The assembly may be an executable (exe) or a
library (dll).
The benefits of the runtime are as follows:
Performance improvements.
The ability to easily use components developed in other languages.
Extensible types provided by a class library.
A broad set of language features.
1.2 The Intermidiate Language: Currently Microsoft provides compilers for C#
(Pronounced as C Sharp), VisualBasic.NET, Managed C++ and JScript in their .NET
Framework SDK. These compilers generate the so called Intermediate Language(IL)code which is then assembled to a Portable Executable(PE) code. The PE code is
8/13/2019 Programming .NET With Visual Basic.net
3/121
Programming .NET With Visual Basic.NET
Copyright 2001 K.M.Hussain - 3 -
interpreted at runtime by CLR for execution. Our first example is the traditional Hello
World program written in IL. (ilhello.il)
.assembly Hello{}
.method public static void run() il managed{
.entrypointldstr Hello World.NETcall void [mscorlib]System.Console::WriteLine(class System.String)ret
}
The above code declares Hello as an assembly(unit of code) and defines an il managed
function called run. This function is marked as an entrypoint (the function which the CLRmust invoke when this code is executed). Next it stores a string on the stack and invokes
WriteLine method of Console class (this method displays a line on screen). For resolving
name collisions all classes in .NET library are packaged in namespaces. The Console
class for instance belongs to namespace called System (the root of all the namespaces inthe .NET framework class library). The code for System.Console class is stored in
mscorlib.dll. To execute this code, it must be first assembled to PE code using ilasm.exe
utility available with .NET Framework SDK.
ilasm ilhello.il
The above command will create ilhello.exe which when executed will display
Hello World.NETon the screen. Needless to say that coding in raw IL is pretty difficult. For actual
programming any .NET compliant high level language can be used. Given below
(mcpphello.cpp) is the Hello World program coded ni Managed C++
#using using namespace System;
void main(){
Console::WriteLine(S"Hello World.NET");}
Compile it using command cl /clr mcpphello.cpp
The listing below shows same program coded in VisualBasic.Net(vbhello.vb).
Imports SystemModule Hello
Sub Main()Console.WriteLine(Hello World.NET)
End SubEnd Module
Compile vbhello.vb using command:vbc vbhello.vb
8/13/2019 Programming .NET With Visual Basic.net
4/121
Programming .NET With Visual Basic.NET
Copyright 2001 K.M.Hussain - 4 -
The code below is hello program in JScript (jshello.js)
import System;Console.WriteLine(Hello World.NET);
Compile jshello.js using commandjsc jshello.jsFinally the Hello World program in C# would be (cshello.cs)
using System;class Hello{
public static void Main(){Console.WriteLine(Hello World.NET);
}}
And it can be compiled using CSharp compiler as: csc cshello.cs
1.3 Mixed Language Programming: The .NET framework not only allows you to
write your program in any language but also allows you to use components coded in one
language in a program written in another. Listed below is a component implemented inVB.NET (bizcalc.vb) for calculating the price of a depreciating asset at an end of a given
period:
Namespace BizCalcPublic Class Asset
Public OriginalCost As DoublePublic AnnualDepreciationRate As SinglePublic Function GetPriceAfter(years As Integer) As Double
Dim price As Double = OriginalCostDim n As Integer
For n = 1 To yearsprice = price * (1 - AnnualDepreciationRate/100)
NextGetPriceAfter = price
End FunctionEnd Class
End Namespace
Compile bizcalc.vb to create a dll using command: vbc /t:library bizcalc.vb
A C# program below (assettest.cs) uses the above component:
using BizCalc;using System;class AssetTest{public static void Main(){Asset ast = new Asset();ast.OriginalCost = 10000;
8/13/2019 Programming .NET With Visual Basic.net
5/121
Programming .NET With Visual Basic.NET
Copyright 2001 K.M.Hussain - 5 -
ast.AnnualDepreciationRate = 9;Console.WriteLine("Price of asset worth 10000 after 5 years: {0}",
ast.GetPriceAfter(5));}
}
Compile the above program using: csc /r:bizcalc.dll assettest.cs
8/13/2019 Programming .NET With Visual Basic.net
6/121
Programming .NET With Visual Basic.NET
Copyright 2001 K.M.Hussain - 6 -
Chapter 2: VB.NET Language Fundamentals
1.1 Branching and Looping: Basically a VB.Net program consists of a Module with a
Sub Main (or a Class with a Shared Sub Main). When VB.Net compiler (vbc.exe)
compiles a VB.Net program it marks this Main sub as the entrypoint in the generated IL
code. System.Environment.GetCommandLineArgs()returns an array which containsthe command line arguments passed to the program by its user (first element of this array
is the program name). The program below (hello1.vb) says hello to the first name on itscommand line.
Imports SystemModule Hello1()
Sub MainDim args as String() = Environment.GetCommandLineArgs()Console.WriteLine("Hello {0}", args(1)) args(0) is name of the programConsole.WriteLine("Goodbye.")
End SubEnd Module
After compiling hello1.vb execute it as : hello1 John
The screen will Display
Hello John
Goodbye.
The statement Console.WriteLine(Hello {0}, args(1)) prints a string on the console
with {0} replaced by the second argument ie args(1) of WriteLine. Since args(1) is the
first argument on the command line the output appears as Hello John. Now execute thisprogram without any command line argument ie just: hello1
The output would be:
Exception occurred: System.IndexOutOfRangeException: An exception of type
System.IndexOutOfRangeException was thrown.
at Test.Main(String[] args)
The program crashes with an exception (error). This is obvious because our program
blindly references args(1) without checking for its existence. Also note the next statement
(the one which displays Goodbye) does not execute at all.
The runtime terminates an executing program as soon as an unhandled exception occurs.
If you prefer the remaining code to execute, you must handle or catch the expected
exception. Our next program (hello2.vb) demonstrates how to.
8/13/2019 Programming .NET With Visual Basic.net
7/121
Programming .NET With Visual Basic.NET
Copyright 2001 K.M.Hussain - 7 -
Imports SystemModule Hello2
Sub MainDim args as String() = Environment.GetCommandLineArgs()Try
Console.WriteLine("Hello {0}", args(1))Catch e As ExceptionConsole.WriteLine(e)
End TryConsole.WriteLine("Goodbye.")
End SubEnd Module
Compile and execute hello2.vb. If you execute hello2 without a command line argument,
you will see the exception message as before but now the code will continue to execute
and Goodbye message will be displayed. If any exception occurs in any statement
enclosed within a try block the control moves into the catch block, the code in there isexecuted and the code below is resumed normally.
The program(hello3.vb) below displays hello to the first argument on the command line,
if the argument is missing it prompts the user for a name and then displays hello to theentered name.
Imports SystemModule Hello3
Sub MainDim args as String() = Environment.GetCommandLineArgs()If args.Length > 1 Then
Console.WriteLine("Hello {0}", args(1))Else
Console.Write("Enter your name: ")Dim name As String = Console.ReadLine()Console.WriteLine("Hello {0}", name)
End IfConsole.WriteLine("Goodbye.")
End SubEnd Module
The Length property of an array returns the number of elements in the array. We checkthe Length of the args array and make our decision using the if-elseconstruct. Note
Console.ReadLine() used to input a line of text at runtime.
The program below (hello4.vb) uses a forloop and displays hello to each name on the
command line. Note here the Main accepts an array as String which contains the
command line arguments (args(0) contains the first argument)
8/13/2019 Programming .NET With Visual Basic.net
8/121
Programming .NET With Visual Basic.NET
Copyright 2001 K.M.Hussain - 8 -
Imports SystemModule Hello4
Sub Main(args As String())Dim n As Integer
For n = 0 To args.Length - 1Console.WriteLine("Hello {0}", args(n))NextConsole.WriteLine("Goodbye.")
End SubEnd Module
Lastly hello5.vb uses whileloop to say hello to each name on command line but does itin reverse order.
Imports System
Module Hello5Sub MainDim args as String() = Environment.GetCommandLineArgs()Dim n As Integer = args.Length - 1Do While n > 0
Console.WriteLine("Hello {0}", args(n))n = n - 1
LoopConsole.WriteLine("Goodbye.")
End SubEnd Module
1.2 Basic and User Defined Types: VB.Net is a strongly typed languagethus VB.Net
variables must be declared with an available type and must be initialized with a value (or
reference) of same type. The table below lists all the built-in types available in VB.Net
VB.Net Type .NET Type Description
Boolean System.Boolean Ttrue / False
Byte System.Byte unsigned byte value
Char System.Char a single character
Short System.Int16 16 bit signed integer
Integer System.Int32 32 bit signed integer
Long System.Int64 64 bit signed integerSingle System.Single 32 bit floating-point
Double System.Double 64 bit floating-point
Decimal System.Decimal a high precision double
Date System.DateTimeJanuary 1, 0001 to December 31, 9999
String System.String string of characters
Object System.Object a generic type
8/13/2019 Programming .NET With Visual Basic.net
9/121
Programming .NET With Visual Basic.NET
Copyright 2001 K.M.Hussain - 9 -
At compile-time the VB.Net compiler converts the VB.Net types into their corresponding.NET types mentioned in the above table. Apart from above basic types user may define
his own types usingEnum, Structureand Class. The program below (club1.vb) shows
how and to create user-defined type
Imports SystemEnum MemberType
LionsPythonsJackalsEagles
End Enum
Structure ClubMemberPublic Name As String
Public Age As IntegerPublic Group As MemberTypeEnd Structure
Module TestSub Main()
Dim a As ClubMember() Value types are automatically initializeda.Name = "John"a.Age = 13a.Group = MemberType.EaglesDim b As ClubMember = a ' new copy of a is assigned to bb.Age = 17 ' a.Age remains 13Console.WriteLine("Member {0} is {1} years old and belongs to the group of {2}", _
a.Name, a.Age, a.Group)End Sub
End Module
The Enumkeyword is used to declare an enumeration, a distinct type consisting of a set
of named constants called the enumerator list. Every enumeration type has an underlyingtype, which can be any integral type except Char. The default type of the enumeration
elements is Integer. By default, the first enumerator has the value 0, and the value of
each successive enumerator is increased by one. For example:
Enum MemberType
LionsPythons
Jackals
EaglesEnd Enum
8/13/2019 Programming .NET With Visual Basic.net
10/121
Programming .NET With Visual Basic.NET
Copyright 2001 K.M.Hussain - 10
In this enumeration, Lionsis 0, Pythonsis 1, Jackalsis 2and Eaglesis 3. Enumeratorscan have initializers to override the default values. For example:
Enum MemberTypeLions = 1
PythonsJackals
EaglesEnd Enum
Now Lionsis 1, Pythonsis 2, Jackalsis 3and Eaglesis 4.
The Structurekeyword is used to create a composite type called structure . In aboveexample ClubMember is a structure with three fields Name, Age and Group. Note the
Group field is of type MemberType and as such it can take only one of the four values
defined in MemberType enum. The fields are declared Public so that they are accessible
outside the scope of structure block. A structure is automatically instantiated when avariable of its type is declared. In above example variable a is declared to be of typeClubMember. Next the public fields of ClubMember is set for this instance. Note how
Group field of a is set: a.Group = MemberType.Eagles A structure is a value type i.e
when a variable holding an instance of a structure is assigned to another variable of same
type, a new copy of the instance is created and assigned. Consider statement Dim b As
ClubMember = a Here b contains a copy of a. Thus change in one of the fields of b does
not affect fields of a. Thus output of program prints age of John as 13. In contrast the
Classis a reference type. club2.vb is similar to club1.vb except now ClubMember is a
class instead of structure
Imports SystemEnum MemberTypeLionsPythonsJackalsEagles
End Enum
Class ClubMemberPublic Name As StringPublic Age As IntegerPublic Group As MemberType
End Class
Module TestSub Main()
Unlike value type a reference type must be instantiated with new operatorDim a As New ClubMember()a.Name = "John"
8/13/2019 Programming .NET With Visual Basic.net
11/121
Programming .NET With Visual Basic.NET
Copyright 2001 K.M.Hussain - 11
a.Age = 13a.Group = MemberType.EaglesDim b As ClubMember = a b refers to the instance referred by ab.Age = 17 a.Age becomes 17Console.WriteLine("Member {0} is {1} years old and belongs to the group of {2}", _
a.Name, a.Age, a.Group)End SubEnd Module
Here since ClubMember is a classit must be initialized with New operator (or it willreference Nothing). Secondly The assignment Dim b As ClubMember = a assigns
variable b a reference to instance referenced by variable a. i.e now a and b are both
holding a reference to same instance, any change in field of b will change thecorresponding field of a . Hence the output of program prints age of John as 17.
An array of values can be created in VB.Net using one of the following syntaxes
Dim arr As type() = {val_0, val_1, val_2, val_3, , val_n} arr.Length = n + 1Dim arr As type() = New arr(n){val_0, val_1, val_2,,val_n} arr.Length = n + 1
Dim arr(n) As type arr.Length = n + 1
For example:Dim k As Integer() = {12, 15, 13, 19}
Dim p As Double(2)
p(0) = 9.3: p(1) = 12.8: p(2) = 7.7
1.3 User Defined Methods: In modular programming it is desirable to divide a program
into multiple procedures The program below (maximizer.vb) implements user-definedmethods to obtain maximum of double values. These methods are then called from Main.
Imports SystemPublic Class Maximizer
Public Shared Overloads Function Max(p As Double, q As Double) As DoubleIf p > q Then Max = p Else Max = q
End Function
Public Shared Overloads Function Max(p As Double, q As Double, r As Double) As DoubleMax = Max(Max(p,q),r)
End Function
End Class
Module TestSub Main()
Console.WriteLine("Maximum of 12.8 and 19.2 is {0}", Maximizer.Max(12.8,19.2))Console.WriteLine("Maximum of 21.7, 12.8 ,19.2 is {0}" ,Maximizer.Max(21.7,12.8,19.2))
End SubEnd Module
8/13/2019 Programming .NET With Visual Basic.net
12/121
Programming .NET With Visual Basic.NET
Copyright 2001 K.M.Hussain - 12
Note the above programs defines to Max methods with different set of arguments. This is
called method overloading. Both Max methods are declared Public and Sharedand assuch these methods can be invoked from any class using fully qualified name
Maximizer.Max. (A shared method can be invoked on the class itself, no instance of the
class is required)
The invocation Maximizer.Max(13.5,21.7,12.8,19.2) will not compile since classMaximizer does not define any Max method which takes 4 double values as its
arguments. Well, we could create one more overload of Max but then what about Max
with more than 4 doubles. VB.Net solves this problem using ParamArraykey word.Given below is a version of Max (you can incooperate this in maximizer.vb) which takes
any number of double values as its argument
Public Shared Overloads Function Max(ParamArray list() As Double) As DoubleDim m As Double = list(0)Dim val As DoubleFor Each val In list
If val > m Then m = valNextMax = m
End Function
When user invokes this method as Max(31.3, 9.1,13.5,21.7,12.8,19.2) the arguments are
passed to Max in an array of double (referred in Max as list)
VB.Net also supports default values for optional parameters. The optional parameters
must be at the end of theargument list. The example below (interest.vb) demonstrates this feature
Imports SystemPublic Class Investment
Public Shared Function GetInterest(principal As Double, period As Integer, rate As Single, _Optional compound As Boolean = False) As Double
If compound ThenGetInterest = principal * (1 + rate/100) period - principal
ElseGetInterest = principal * period * rate / 100
End IfEnd Function
End ClassModule Test
Sub Main()Console.WriteLine("Simple interest on 10000 for 5 years at rate of 9% is {0:#.00}", _
Investment.GetInterest(10000,5,9)) value of fourth parameter is FalseConsole.WriteLine("Compound interest on 10000 for 5 years at rate of 9% is {0:#.00}", _
Investment.GetInterest(10000,5,9,True))End Sub
End Module
8/13/2019 Programming .NET With Visual Basic.net
13/121
Programming .NET With Visual Basic.NET
Copyright 2001 K.M.Hussain - 13
In VB.Net the arguments are passed to a method by value i.e a copy of variable is passedinstead of the original variable. Thus when a caller of a method passes some variable to
the method as an argument and the method alters the value of this argument, the original
value of the variable remains unchanged. VB.Net provides ByRefkeyword for passing
arguments by reference. swapper.vb uses this approach to swap values of variables.
Imports SystemPublic Class Swapper
Swap receives two integers by referencePublic Shared Sub Swap(ByRef p As Integer, ByRef q As Integer)
Dim t As Integer = pp = qq = t
End SubEnd Class
Module TestSub Main()
Dim m As Integer = 109, n As Integer = 73Console.WriteLine("m = {0} and n = {1}",m,n)Console.WriteLine("Invoking Swap")Swapper.Swap(m,n) passing m and n by reference to SwapConsole.WriteLine("m = {0} and n = {1}",m,n)
End SubEnd Module
8/13/2019 Programming .NET With Visual Basic.net
14/121
Programming .NET With Visual Basic.NET
Copyright 2001 K.M.Hussain - 14
Chapter 3: Object Oriented Programming in VB.NET
1.1 Classes and Namespaces: Object Oriented Programming (OOP) is essentially
programming in terms of smaller units called objects. An object oriented program iscomposed of one or more objects. Each objectholds some data (fieldsor attributes) as
defined by its class. The class also defines a set of functions (methodsor operations)which can be invoked on its objects. Generally the data is hidden within the object and
can be accessed only through functions defined by its class (encapsulation). One or moreobjects (instances) can be created from a class by a process called instantiation. The
process of deciding which attributes and operations will be supported by an object (i.e
defining the class) is called abstraction. We say the stateof the object is defined by theattributes it supports and its behaviouris defined by the operations it implements. The
termpassing a messageto an object means invoking its operation. Sometimes the set of
operations supported by an object is also referred to as the interfaceexposed by thisobject.
Given below is a simple class (item.vb) which defines an Item. Each item supports twoattributes, its cost and the percent profit charged on it and provides some operations.
Public Class ItemPrivate _cost As DoublePrivate _profit As SinglePrivate Shared _count As Integer
Public Sub New(Optional cost As Double = 0, Optional profit As Single = 0)If cost > 0 Then _cost = cost
_profit = profit
_count = _count + 1End Sub
Public Property Cost As DoubleGet
Cost = _costEnd GetSet
If value > 0 Then _cost = ValueEnd Set
End Property
Public Property Profit As SingleGet
Profit = _profitEnd GetSet
_profit = ValueEnd Set
8/13/2019 Programming .NET With Visual Basic.net
15/121
Programming .NET With Visual Basic.NET
Copyright 2001 K.M.Hussain - 15
End Property
Property which only supports Get operation must be marked ReadOnlyPublic Shared ReadOnly Property Count As Integer
Get
Count = _countEnd GetEnd Property
Overridable modifier will be explained laterPublic Overridable Function SellingPrice() As Double
SellingPrice = _cost * (1 + _profit / 100)End Function
Public Function EMI() As DoubleDim amount As Double = 1.12 * SellingPrice() ' 12% interest
EMI = amount / 12End FunctionEnd Class
Class Item defines two Privatemember variables, _cost and _profit. These variables arevisible only inside the body of class Item. An outsider can only access these variables
through special property methods(Cost and Profit). For example a user may create an
instance of the class as follows.
Dim p As Item = New Item()
p._cost = 1200 compile-time error, _cost is not accessible
p.Cost = 1200 works, invokes set method of Cost with value = 1200
A property implemented in a class is automatically translated by the VB.Net compiler to
a pair of methods. For example the Cost property in Item class is translated by the
compiler to:
Public Function get_Cost() As Double
get_Cost = _cost
End Function
Public Sub set_Cost(Value As Double)
If Value > 0 Then _cost = Value
End Sub
Which also explains the use of undeclared variable Value in the setpart of a property.
A non-shared (instance) variable is stored within object of the class, thus each object has
its own copy of a non-shared variable. A shared (class) variables on other hand is stored
within the class and is shared by all of its objects. In Item class _count is a shared
variable used for determining number of times the class has been instantiated. The value
of this variable can be obtained using the Count property of the class. Note the Count
8/13/2019 Programming .NET With Visual Basic.net
16/121
Programming .NET With Visual Basic.NET
Copyright 2001 K.M.Hussain - 16
property is marked shared which means a user may access it as Item.Count. As non-
shared member variables are not stored in a class, a shared method cannot directly
reference a non-shared member of the class.
A user instantiates a class by applying Newoperator to the class constructor(a sub
whose name is New). A class may define multiple constructors. If no constructor isdefined by the class a default (no argument) constructor is automatically made available
to the class. A user may instantiate and initialize Item as follows:
Dim p As Item = New Item() using default values for cost and profit
equivalently Dim p As New Item()
p.Cost = 1200;p.Profit = 9;
Dim q As Item = New Item(1500,8) passing values for cost and profit
equivalently Dim p As New Item(1500,8)
Item class also provides two utility methods for calculating selling price and the equalmonthly instalment (1 year scheme) for the item.
The program below(itemtest1.vb) uses Item class
Imports System
Module ItemTest1Sub Main()
Dim pc As Item = New Item(32000, 12)Dim ac As New Item(25000, 10)Console.WriteLine("Selling price of PC is {0} and its EMI is {1}", _
pc.SellingPrice(), pc.EMI())Console.WriteLine("Selling price of AC is {0} and its EMI is {1}", _
ac.SellingPrice(), ac.EMI())Console.WriteLine("Number of Items created: {0}", Item.Count)
End SubEnd Module
To compile itemtest1.vb either first compile item.vb to create a dll and then compile
itemtest1.vb referencing item.dll (Note: only public classes from one assembly can beaccessed from other assembly, hence class Item is declared public in item.vb)
vbc /t:library item.vb creates item.dll
vbc /r:item.dll itemtest1.vb creates itemtest1.exe
You can also compile itemtest.vb by using command
vbc itemtest1.vb item.vb creates only itemtest1.exe
One of the most important feature of OOP is subclassing. It involves creation of a new
(sub or derived) class based on an existing(super or base) class. The members of base
8/13/2019 Programming .NET With Visual Basic.net
17/121
Programming .NET With Visual Basic.NET
Copyright 2001 K.M.Hussain - 17
class are automatically made available to the derived class (inheritance). Subclassing
enforces an is-arelationship between two classes i.e an instance of the base class can be
replaced by an instance of the derived classin other words an instance of the derivedclass isalsoan instance of the base class.
For example let DClass be a subclass of BClass (In VB.Net, DClass : Inherits BClass),
the above rule makes it possible to write: Dim obj As BClass = New DClass() Thusfor compiler obj is an object of BClass however at runtime obj is assigned to an
instance of DClass. The opposite will obviously not compile.
Though the derived class inherits all the operations supported by the base class but for
some reason the derived class may want to change the behaviour (implementation) of an
operation it inherits. The derived class may do so either by overridingor by hidingthe
operation of the base class. The difference in the two approach can be described as
follows. Let DClass be a subclass of BClass and let both of these classes have their own
implementations for a method called SomeOperation(). Now consider statements:
Dim obj As BClass = New DClass()obj.SomeOperation()
If DClass overrides SomeOperation() of BClass, obj.SomeOperation() will be invoked
from DClass despite of the fact that obj is declared to be an object of BClass. This
behaviour is calledpolymorphism (capability of an operation to exhibit multiple
behaviours) or late-binding (determining address of operation to be invoked at run-time
and not at compile-time). However if DClass hides SomeOperation() of BClass then
obj.SomeOperation() will be invoked from BClass despite of the fact that obj is assigned
to an instance of DClass.
To override a method of base class the derived class must use Overrides modifier while
redeclaring this method and this is only allowed for those methods which have been
declared with Overridablemodifier in the base class. To hide a method of base class the
derived class must use Shadowmodifier while redeclaring this method, the same method
in base class may or may not be declared Overridable.
Given below is an implementation of a subclass of Item called SpecialItem
(specialitem.vb). This class adds a Discount property to Item and overrides its
SellingPrice (Overridable) method .
Public Class SpecialItemInherits Item
Private _discount As SinglePublic Sub New(c As Double, p As Single, d As Single)
MyBase.New(c,p)If d > 0 Then _discount = d
End Sub
Public Property Discount As Single
8/13/2019 Programming .NET With Visual Basic.net
18/121
Programming .NET With Visual Basic.NET
Copyright 2001 K.M.Hussain - 18
Getreturn _discount
End GetSet
If Value > 0 Then _discount = Value
End SetEnd Property
Public Overrides Function SellingPrice() As Doubledim price As Double = MyBase.SellingPrice()SellingPrice = price * (1 - _discount/100)
End FunctionEnd Class
Note a subclass constructor must first invoke the base class constructor, this is done by
invoking MyBase.New() from the constructor of the subclass. If no such arrangement
is made by the subclasser then the default (no argument) constructor of base class will becalled (absence of which will result in a compile time error). Also note how SellingPrice
method of SpecialItem invokes the same method from its base class using MyBase
keyword.
SpecialItem class does not reimplement the EMI method, when EMI method is invoked
on an instance of SpecialItem the implementation from Item will be invoked however
EMI method will properly invoke the SellingPrice method of SpecialItem. If instead of
overriding SellingPrice method, SpecialItem would have hidden it (replacing overrides
modifier by shadows modifier) then EMI method would call the SellingPrice of Item
which would not take in account the Discount.
The program below (itemtest2.vb) uses both Item and SpecialItem classes:
Imports System
Module ItemTest2Sub Main()
Dim pc As Item = New Item(32000, 12)Dim ac As SpecialItem = New SpecialItem(32000, 12,7)Console.WriteLine("Selling price of PC is {0} and its EMI is {1}", _
pc.SellingPrice(), pc.EMI())Console.WriteLine("Selling price of AC is {0} and its EMI is {1}", _
ac.SellingPrice(), ac.EMI())Console.WriteLine("Number of Items created: {0}", Item.Count)
End SubEnd Module
Compile this program as: vbc itemtest2.vb item.vb specialitem.vb
8/13/2019 Programming .NET With Visual Basic.net
19/121
Programming .NET With Visual Basic.NET
Copyright 2001 K.M.Hussain - 19
The output of the program will show that both Selling price and EMI of AC are lesser
than the Selling price and EMI of PC even though the cost and profit of both the items aresame.
The rule of inheritance (an instance of base class can be replaced by that of derived class)
allows us to place objects of SpecialItem in an array of Item objects. For example thecode below is legal:
Dim store As Item()= {New Item(1500, 7), New SpecialItem(22000, 10, 5), _New SpecialItem(3500,12,7), New Item(15000,0), New Item(750, 5)}
Now consider a routine to calculate total SellingPrice of all the items in the store.Dim total As Double = 0
Dim itm As Item
For Each itm In storetotal = total + itm.SellingPrice()
NextSince SellingPrice() is overridable in Item and has been overriden in SpecialItem, for
store(1) and store(2) the SellingPrice() method is invoked from SpecialItem (for compileritm is an object of Item). What if we have to calculate average discount on all the items in
the store. In code similar to above itm.Discount will not compile since compiler will look
for Discount property in Item class (itm is declared to be Item). The code below identifieswhich of the items in store are of type SpecialItem then converts these items to objects of
SpecialItem and sums their discount:
Dim total As Double = 0Dim itm As Item
For Each itm In store
If TypeOfitm IsSpecialItem
Dim sitm As SpecialItem = CType(itm, SpecialItem)total = total + sitm.SellingPrice()
End If
NextThe TypeOf - Is construct is used to check whether a given object is an instance of a
given class and the CType function is used to narrow object of base class to an object of
its derived class
Next consider a similar situation. A bank currently supports two types of accounts,
SavingsAccount and CurrentAccount (more types are expected in future). Both of these
account types support a Withdraw operation with obviously different behaviours. You
dont want one of these account type to be a subclass of other since the statement
SavingsAccount is a CurrentAccount or vice versa does not hold good and yet you
want to place the instances of these account type in a single array. A simple solution
would be to inherit both of these account types from a common base class say Account
and then create an array of Account.
Dim bank As Account() = {New SavingsAccount(), New CurrentAccount(), }
8/13/2019 Programming .NET With Visual Basic.net
20/121
Programming .NET With Visual Basic.NET
Copyright 2001 K.M.Hussain - 20
Both SavingsAccount and CurrentAccount are derived from Account and support
Withdraw(double amount) operation. Now lets write a routine which withdraws 500 fromall the accounts in bank array.
Dim acc As Account
For Each acc In bankacc.Withdraw(500)
Next
Naturally the compiler looks for Withdraw method in Account class and runtime invokesthe overriden method from the appropriate subclass. This clearly means Account class
must provide an overridable Withdraw method. But it cannot provide implementation for
this method because the implementation depends on the actual type of account. Such anoperation (method) without behaviour (implementation) is called an abstract method.
Account class will declare Withdraw to be an abstract method and the implementation to
this method will be provided by SavingsAccount and CurrentAccount by overriding it.On any grounds user must not be allowed to instantiate the Account class otherwise he
might invoke the codeless Withdraw method directly from the Account. Such a classwhich cannot be instantiated is called an abstract class. Only abstract classes can have
abstract methods. However its possible to create an abstract class without any abstractmethod.A subclass of an abstract class must provide implementation for all the abstract
method it inherits from its superclass or the subclass must itself be declared abstract.
VB.Net uses MustOverridekeyword to declare abstract methods and MustInheritkeyword to declare abstract classes. Note a MustOverridemethod is automatically
Overridableand must be defined in the derived class with Overridesmodifier (Shadowmodifer will cause a compile time error since inherited abstract methods cannot behidden)
Code below(bank.vb) contains an abstract Account class and its subclasses among other
classes (explanation follows the code)
Namespace Project.BankPublic Class InsufficientFundsExceptionInherits System.ExceptionEnd Class
Public Class IllegalTransferExceptionInherits System.ExceptionEnd Class
Public MustInherit Class AccountPublic MustOverride Sub Deposit(amount As Double)
Public MustOverride Sub Withdraw(amount As Double)
Public MustOverride ReadOnly Property Balance As Double
8/13/2019 Programming .NET With Visual Basic.net
21/121
Programming .NET With Visual Basic.NET
Copyright 2001 K.M.Hussain - 21
Public Sub Transfer(amount As Double, other As Account) Isoperator must be used to check whether two references are equalIf other Is Me Then Throw New IllegalTransferException()Me.Withdraw(amount) ' same as Withdraw(amount)
other.Deposit(amount)End SubEnd Class
Public MustInherit Class BankAccountInherits Account
Protected _balance As Double ' also accessible to any subclassFriend _id As String ' also accessible to any other class in this dll
Public ReadOnly Property ID As StringGet
ID = _idEnd GetEnd Property
Public Overrides ReadOnly Property Balance As DoubleGet
Balance = _balanceEnd Get
End Property
Public Overrides Sub Deposit(amount As Double)_balance = _balance + amount
End SubEnd Class
Public NotInheritable Class SavingsAccountInherits BankAccount
Public Const MIN_BALANCE As Double = 500.0Public Sub New()
_balance = MIN_BALANCE_id = "S/A"
End Sub
Public Overrides Sub Withdraw(amount As Double)If _balance - amount < MIN_BALANCE Then Throw New _InsufficientFundsException()_balance = _balance - amount
End SubEnd Class
Public Class CurrentAccount
8/13/2019 Programming .NET With Visual Basic.net
22/121
Programming .NET With Visual Basic.NET
Copyright 2001 K.M.Hussain - 22
Inherits BankAccountPublic const MAX_CREDIT As Double = 50000.0Public CurrentAccount()Public Sub New()
_id = "S/A"
End Sub
Public Overrides Sub Withdraw(amount As Double)If _balance - amount < -MAX_CREDIT Then Throw New _InsufficientFundsException()_balance = _balance - amount
End SubEnd Class
Public NotInheritable Class BankerPrivate Shared self As Banker
Private nextid As IntegerPrivate Sub New()nextid = 1001
End Sub
Public Shared Function GetBanker() As BankerIf self Is Nothing Then self = New Banker()GetBanker = self
End Function
Public Function OpenAccount(acctype As String) As BankAccountDim acc As BankAccountIf acctype = "SavingsAccount" Then
acc = New SavingsAccount()Else
If acctype = "CurrentAccount" Thenacc = New CurrentAccount()
ElseOpenAccount = NothingExit Function
End IfEnd Ifacc._id = acc._id & nextidnextid = nextid +1OpenAccount = acc
End FunctionEnd Class
End Namespace
Here are important points to note about bank.vb
8/13/2019 Programming .NET With Visual Basic.net
23/121
Programming .NET With Visual Basic.NET
Copyright 2001 K.M.Hussain - 23
1. All the classes are placed in a namespace Project.Bank. Namespaces are used to
organize related classes into a group and also to protect classes from name conflicts.A user may refer to Account class in namespace Project.Bank by its fully qualified
name, i.e Project.Bank.Accountor he might first mentionImports Project.Bank and
then refer to Account class asAccount.
2. Classes InsufficientFundsException and IllegalTransferException representexceptions since they are derived from System.Exception. Instances of subclasses
of System.Exception can be used along with Throwkeyword within a method
body to trigger an error situation. Throwing of an exception immediately abortsthe method and the control moves into the callers Catchblock for that exception.
3. The Account class is an abstract class. It defines two abstract methods and an
abstract get property for Balance. It also provides the Transfer method fortransferring an amount from an Account on which Transfer was invoked (which
is referred in body of Transfer using the Mekeyword) to another Account passed
as the other argument. If the source of transfer is exactly same object as itsdestination, the Transfer method throws IllegalTransferException.
4. The BankAccount class is derived from Account class but does not implement itsWithdraw method and as such has been declared abstract. This class defines two
member variables _balance and _id. _balance is declared as Protectedthis meansapart from the currrent class this member is accessible to the subclasses also. The
_id is declared Friendwhich means apart from the current class this member is
accessible to any other class in the current assembly (Protected Friendis alsoallowed and it means apart from the current class the member will be accessible only
to the subclasses or other classes in the current assembly)
5. SavingsAccount and CurrentAccount are two concrete implementations of Account.Both of these classes are derived from BankAccount and are declared
NotInheritablewhich
means that these classes cannot be further subclassed. SavingsAccount defines a
double constant called MIN_BALANCE and as it is public any user may access itsvalue as SavingsAccount.MIN_BALANCE (constants in VB.Net are shared) though
the value cannot be modified. Member _balance declared in BankAccount is
accessible in SavingsAccount because SavingsAccount is subclass of BankAccountand member _id is accessible because SavingsAccount and BankAccount belong to
same assembly.
6. Finally Banker class is an example of a singleton (only one instance)factory(createsinstances of other classes) class. Its main purpose is to create instances of
SavingsAccount and CurrentAccount and update their ID. The only constructor that
Banker has is declared private and as such it can only be instantiated from Banker
class. The shared method GetBanker allows an outsider to obtain a reference to theone and only one instance (self) of Banker which is initialized when
Banker.GetBanker is invoked for the first time. The OpenAccount method returns an
Account of the specified type, in case of a bad type it returns Nothing.
The program below (banktest1.vb) uses the above classes.
8/13/2019 Programming .NET With Visual Basic.net
24/121
Programming .NET With Visual Basic.NET
Copyright 2001 K.M.Hussain - 24
Imports Project.BankImports System
Module BankTest1Sub Main()
Dim b As Banker = Banker.GetBanker()Dim cust As BankAccount = b.OpenAccount("SavingsAccount")Dim vend As BankAccount = b.OpenAccount("CurrentAccount")cust.Deposit(12000)Console.Write("Enter amount to transfer: ")Dim amt As Double = Double.Parse(Console.ReadLine())try
cust.Transfer(amt,vend)catch e As InsufficientFundsException
Console.WriteLine("Transfer Failed")End Try
Console.WriteLine("Customer: Account ID: {0} and Balance: {1}",cust.ID, _cust.Balance)Console.WriteLine("Vendor: Account ID: {0 } and Balance: {1}",vend.ID, _
vend.Balance)End Sub
End Module
1.2 Interfaces and Delegates: Under VB.Net a class can be derived from one and onlybase class. If a class does not specify its superclass then the class is automatically derived
from System.Object. But what if a class need to inherit multiple characteristics. Consider
an abstract class called Profitable given below
Public MustInherit Class Profitable
Public MustOverride Sub AddInterest(rate As Single, period As Integer)
End Class
A bankable entity (not necessarily an account) which provides interest must be derived
from above class and provide an implementation for AddInterest. What ifSavingsAccount wants to support interest? It cannot subclass both BankAccount and
Profitable. To resolve this issue, VB.Net introduces a concept of Interface. An interface
can be regarded to be a pure abstract class as it can only contain abstract operations
(abstract classes may contain non-abstract operations also). A class may inherit from oneand only one other class but can inherit from multiple interfaces. When a class inherits
from an interface it must provide implementations for all the methods in that interface or
the class must be declared abstract. The above Profitable may now be defined as aninterface (add this to bank.vb).
Public Interface IProfitableSub AddInterest(rate As Single, period As Integer)
End Interface
8/13/2019 Programming .NET With Visual Basic.net
25/121
Programming .NET With Visual Basic.NET
Copyright 2001 K.M.Hussain - 25
Methods declared in an interface are Public and MustOverride by default and when a
class implements a method which it inherits from an interface the override modifier isautomatically understood.
The SavingsAccount class (update bank.vb) can inherit from both BankAccount and
IProfitable as follows:
Public NotInheritable Class SavingsAccountInherits BankAccountImplements IProfitable
Public Const MIN_BALANCE As Double = 500.0Public Sub New()
_balance = MIN_BALANCE_id = "S/A"
End Sub
Public Overrides Sub Withdraw(amount As Double)
If _balance - amount < MIN_BALANCE Then Throw New _InsufficientFundsException()_balance = _balance - amount
End Sub
Public Sub AddInterest(rate As Single, period As Integer) Implements _Profitable.AddInterest
_balance = _balance * (1 + rate * period /100)End Sub
End Class
The statement Dim acc As IProfitable = New SavingsAccount() compiles since
SavingsAccount implements IProfitable however Dim acc As IProfitable = New
CurrentAccount() will cause a compile-time error.
Next consider floowing two interfaces
Public Interface ITaxableSub Deduct()
End Interface
Public Interface IFinable
Sub Deduct()
End Interface
Now suppose we would like our CurrentAccount class to implement both of these
interfaces. As both of these interfaces contain members with same signature they must be
implemented as follows
8/13/2019 Programming .NET With Visual Basic.net
26/121
Programming .NET With Visual Basic.NET
Copyright 2001 K.M.Hussain - 26
Public Class CurrentAccountInherits BankAccountImplements ITaxable, IFinable
Public const MAX_CREDIT As Double = 50000.0Public CurrentAccount()
Public Sub New()_id = "S/A"End Sub
Public Overrides Sub Withdraw(amount As Double)If _balance - amount < -MAX_CREDIT Then Throw New _InsufficientFundsException()_balance = _balance - amount
End Sub
Private Sub ITaxable_Deduct() Implements ITaxable.Deduct
If _balance > 50000 Then _balance = _balance * 0.95End Sub
Private Sub IFinable_Deduct() Implements IFinable.DeductIf _balance < -0.5*MAX_CREDIT Then _balance = _balance * 0.98
End SubEnd Class
The member methods are implemented with names other than the names used in interface
declaration (as a convention we have used nameInterfaceName_MethodNamefor
implementation though this is not necessary). Note the members are implemented with
Private access-modifier which means they are oly accessible through an interfaceinstance. For example the right way to invoke ITaxable_Deduct() is
Dim acc As ITaxable = New CurrentAccount() declare acc to be an instance of
ITaxable
acc.Deduct() this will invoke ITaxable_Deduct() implemented in
CurrentAccount
VB.Net defines Delegatekeyword, which can be used to receive a reference to a
method. It is very useful in situations where a class needs to invoke a method
implemented by its user (such methods are also called callback methods). Our next class
(fixeddeposit.vb) FixedDeposit uses a delegate to invoke a method passed by its user for
determining the rate of interest.
Imports SystemNamespace Project.Bank
Scheme represents a method which takes a Double and an Integer as its arguments returns a SinglePublic Delegate Function Scheme(principal As Double, period As Integer) As Single
8/13/2019 Programming .NET With Visual Basic.net
27/121
Programming .NET With Visual Basic.NET
Copyright 2001 K.M.Hussain - 27
Public Class FixedDepositPrivate _deposit As DoublePrivate _duration As IntegerPrivate InterestRate As Scheme InterestRate is a method of type Scheme
Shared Sub New()Class initializerConsole.WriteLine()
End Sub
Public Sub New(p As Double, n As Integer, s As Scheme)_deposit = p_duration = nInterestRate = sConsole.WriteLine()
End Sub
Public ReadOnly Property Deposit As DoubleGet
Deposit = _depositEnd Get
End Property
Public ReadOnly Property Duration As IntegerGet
Duration = _durationEnd Get
End Property
Public ReadOnly Property Amount As DoubleGet
Dim rate As Single = InterestRate.Invoke(deposit,duration) 'callback users'method
Amount = _deposit * (1 + rate/100) _durationEnd Get
End Property
Protected Overrides Sub Finalize()DestructorConsole.WriteLine()
End SubEnd Class
End Namespace
The above class contains a shared constructoror a class initializer. This constructor is
invoked only once when the class is loaded by CLR. The static constructor is public bydefault and as it is automatically invoked by CLR it cannot accept arguments. This class
8/13/2019 Programming .NET With Visual Basic.net
28/121
Programming .NET With Visual Basic.NET
Copyright 2001 K.M.Hussain - 28
also overrides the Finalize()method inherited from System.ObjectThis metod is
automatically invoked whenever the memory allocated to an instance of the class isreleased back to the system by CLR (through garbage collection mechanism).
The program below (fdtest.vb) makes use of above class:
Imports Project.BankImports SystemClass FDTest
Public Shared Function MyRate(p As Double, n As Integer) As SingleIf n < 5 Then MyRate = 9 Else MyRate = 11
End Function
Public Function HisRate(p As Double, n As Integer) As SingleIf p < 20000 Then HisRate = 8 Else HisRate = 10
End Function
Shared Sub Main()Dim myfd As New FixedDeposit(25000,7,AddressOf MyRate)Dim hisfd As New FixedDeposit(25000,7, AddressOf New FDTest().HisRate)Console.WriteLine("I get {0:#.00}",myfd.Amount)Console.WriteLine("He gets {0:#.00}",hisfd.Amount)
End SubEnd Class
In the Main method an instance of Scheme delegate is created using method MyRate and
is passed to FixedDeposit constructor using AddressOf operator which saves thereference in its InterestRate member variable. When Amount get property of myfd is
called MyRate is invoked by FixedDeposit. Note how a Scheme delegate is created using
a non-shared method HisRate.
1.3 Rasing and Handling Events: An eventis a notification sent by a senderobject to a
listenerobject. The listener shows an interest in receiving an event by registering an
event handler method with the sender. When event occurs the sender invokes eventhandler methods of all of its registered listeners. In our bank.vb the Account class
provides a Transfer method for transferring funds from one account to another. We would
like target account to raise an event whenever a transfer is successful. Replace theAccount class in bank.vb by following code:
Public MustInherit Class AccountPublic Event FundsTransferred(source As Account, amount As Double) declares the
eventPublic MustOverride Sub Deposit(amount As Double)
Public MustOverride Sub Withdraw(amount As Double)
Public MustOverride ReadOnly Property Balance As Double
8/13/2019 Programming .NET With Visual Basic.net
29/121
Programming .NET With Visual Basic.NET
Copyright 2001 K.M.Hussain - 29
Private Sub OnFundsTransferred(source As Account, amount As Double)RaiseEvent FundsTransferred(source, amount) fires the event
End Sub
Public Sub Transfer(amount As Double, other As Account)If other Is Me Then Throw New IllegalTransferException()Me.Withdraw(amount) ' same as Withdraw(amount)other.Deposit(amount)other.OnFundsTransferred(Me, amount)
End SubEnd Class
First an called TransferHandler is declared. In the Transfer method the event is fired on
the other account. The program below (banktest2.vb) shows how to register an event
handler and handle the event.
Imports Project.BankImports System
Module BankTest2 The Event handling methodSub vend_FundsTransferred(source As Account, amount As Double)
Console.WriteLine("Vendor received amount {0}", amount)End SubSub Main()
Dim b As Banker = Banker.GetBanker()Dim cust As BankAccount = b.OpenAccount("SavingsAccount")Dim vend As BankAccount = b.OpenAccount("CurrentAccount")cust.Deposit(12000)Register the event handler with FundsTransferred event of vendAddHandler vend.FundsTransferred, AddressOf vend_FundsTransferredConsole.Write("Enter amount to transfer: ")Dim amt As Double = Double.Parse(Console.ReadLine())Try
cust.Transfer(amt,vend)Catch e As InsufficientFundsException
Console.WriteLine("Transfer Failed")End TryConsole.WriteLine("Customer: Account ID: {0} and Balance: {1}",cust.ID, _
cust.Balance)Console.WriteLine("Vendor: Account ID: {0 } and Balance: {1}",vend.ID, _
vend.Balance)End Sub
End Module
8/13/2019 Programming .NET With Visual Basic.net
30/121
Programming .NET With Visual Basic.NET
Copyright 2001 K.M.Hussain - 30
The event handler is registered by using AddHandler. This allows registeration of
multiple event handler methods. When event occurs all the handlers will be invoked.VB.Net also provides an alternative approach for handling events raised by objects.
The next program (banktest3.vb) demonstrates this approach
Imports Project.BankImports System
Module BankTest3Dim cust As BankAccountDim WithEvents vend As BankAccount we are interested in handling events raised by vend
This method handles FundsTransferred event raised by vendSub vend_FundsTransferred(source As Account, amount As Double) Handles _vend.FundsTransferred
Console.WriteLine("Vendor received amount {0}", amount)
End Sub
Sub Main()Dim b As Banker = Banker.GetBanker()cust = b.OpenAccount("SavingsAccount")vend = b.OpenAccount("CurrentAccount")cust.Deposit(12000)Console.Write("Enter amount to transfer: ")Dim amt As Double = Double.Parse(Console.ReadLine())Try
cust.Transfer(amt,vend)Catch e As InsufficientFundsException
Console.WriteLine("Transfer Failed")End TryConsole.WriteLine("Customer: Account ID: {0} and Balance: {1}",cust.ID, _
cust.Balance)Console.WriteLine("Vendor: Account ID: {0 } and Balance: {1}",vend.ID, _
vend.Balance)
End SubEnd Module
One last important feature of VB.Net language is the indexer. Indexer allows an instance
to behave like an array i.e it allows notation of type instance(index)to be used to access
certain information. The class RandomList mentioned below (randomlist.vb) generates alist of first nconsecative integers and provides an operation to shuffel this list. It provides
an indexer for retrieving the elements of the list. It also supports features which would
allow a user to iterate through the list using For-Eachstatement.
8/13/2019 Programming .NET With Visual Basic.net
31/121
Programming .NET With Visual Basic.NET
Copyright 2001 K.M.Hussain - 31
Imports SystemPublic Class RandomList
Private list As Integer()Private _current As Integer
Public Sub New(size As Integer)list = New Integer(size){}Dim i As IntegerFor i = 0 To size
list(i) = i+1Next
End Sub
Public Sub Shuffle()Dim gen As New Random()
Dim i As integerFor i = list.Length To 2 Step -1Dim j As Integer = gen.Next(0,i) random integer between 0 and iDim t As Integer = list(i-1)list(i-1)=list(j)list(j) = t
NextEnd Sub
Public ReadOnly Property Count As IntegerGet
Count = list.LengthEnd Get
End Property
support for indexed default propertyPublic ReadOnly Default Property Element(index As Integer) As Integer
GetElement = list(index)
End GetEnd Property
support for For-Each iteration statementPublic Function MoveNext() As Boolean
_current = _current + 1MoveNext = _current < list.Length
End Function
Public ReadOnly Property Current As IntegerGet
Current = list(_current)
8/13/2019 Programming .NET With Visual Basic.net
32/121
Programming .NET With Visual Basic.NET
Copyright 2001 K.M.Hussain - 32
End GetEnd Property
Public Function GetEnumerator() As RandomList_current = -1
GetEnumerator = MeEnd Function
Shared Sub Main()Dim list As New RandomList(9)Dim k As IntegerFor k = 0 To list.Count-1Console.WriteLine(list(k))Nextlist.Shuffle()Console.WriteLine()
For Each k In listConsole.WriteLine(k)Next
End SubEnd Class
Class RandomList accepts a size through its constructor and populates an internal array
with consecative integers. The Shuffle method shuffles the internal array by swappingelements at random positions. Next it provides the indexer which allows reading of
elements using () notation i.e the third element of a RandomList instance rl can be
accessed by rl(2).Any class which supports iteration through foreach statement must provide a method
called GetEnumerator() which returns a reference to an instance of a class which
provides a get property called Currentand a method calledMoveNext() which returns a
boolean value. Since RandomList itself provides Current property and MoveNext()method its GetEnumerator returns its own reference (Me). The For Each statement first
obtains a reference from GerEnumerator() and continuously returns the value returned by
the Current property of the reference as long as its MoveNext() method returns true. TheMain subroutine shows how to iterate through the RandomList instance using the indexer
and For-Each statement.
8/13/2019 Programming .NET With Visual Basic.net
33/121
Programming .NET With Visual Basic.NET
Copyright 2001 K.M.Hussain - 33
Chapter 4: Reflection
1.1 Exposing Assemblies and Types: Exposing and utilizing types at runtime is called
Reflection. The type of an object is stored as an instance of System.Type class the
reference to which can be obtained using one of the following methods.
1. From the declaration type: If declaration Dim var As AType is legal then
System.Type representing AType can be obtained using GetType operator as:
Dim t As Type = GetType(AType)
2. From an instance: Type of an instance obj can be obtained using GetType method
defined in System.Object as:
Dim t As Type = obj.GetType()
3. From the type name within current assembly: System.Type offers a shared
method called GetType to obtain a Type from a fully qualified name of the type. The
name will be searched in the current assembly.Dim t As Type = Type.GetType(FullyQualifiedTypeName)
4. From the type name within any assembly: First load the assembly and obtain a
reference to it. This reference can be used to obtain the Type with given name:
Dim asm As System.Reflection.Assembly = _
System.Reflection.Assembly.LoadFrom(AssemblyName)
Dim t As Type = asm.GetType(FullyQualifiedTypeName)
Alternatively one could also use:
Dim t As Type = _
Type.GetType(FullyQualifiedTypeName,AssemblyName)
The program below(showtypes.vb) displays all the Types defined in an assembly whose
name is passed in first command line argument:
Imports SystemImports System.Reflection
Module ShowTypesSub Main(args() As String)
Assembly is also a keyword in VB.Net so [Assembly] must be usedDim asm As [Assembly] = [Assembly].LoadFrom(args(0))
Dim types As Type() = asm.GetTypes()Dim t As TypeFor Each t in types
Console.WriteLine(t)Next
End SubEnd Module
8/13/2019 Programming .NET With Visual Basic.net
34/121
Programming .NET With Visual Basic.NET
Copyright 2001 K.M.Hussain - 34
Execute this program using command line: showmethods anyassembly.dll
Pass complete path to any .NET exe or dll to see the types declared in it.
The second program (showmembers.vb) takes assembly name and type name as its
command line arguments and displays all the members defined in that type of that
assembly.
Imports SystemImports System.Reflection
Module ShowTypesSub Main(args() As String)
Dim asm As [Assembly] = [Assembly].LoadFrom(args(0))Dim t As Type = asm.GetType(args(1))Dim members As MemberInfo() = t.GetMembers()Dim m As MemberInfo
For Each m in membersConsole.WriteLine(m)Next
End SubEnd Module
1.2 Dynamic Instantiation and Invocations: Using reflection it is also possible to
create an instance of a class and invoke its member methods at runtime. This feature canbe used to write more generic (dynamically extensible) programs which receive names of
classes at runtime. Consider one such program which is supposed to calculate the amount
that a user will receive if he invests a certain amount for a certain period of time in acertain investment policy. The rate of interest will depend on the policy in which he
invests. Our program must take the name of the class which implements policy at runtime
and perform the calculations. The code below(invpol.vb) provides implementations forvarious policies:
Public Interface PolicyFunction Rate(principal As Double, period As Integer) As Single
End Interface
Public Class BronzePolicyImplements Policy
Public Function Rate(p As Double, n As Integer) As Single Implements Policy.RateRate = 7
End FunctionEnd Class
Public Class SilverPolicyImplements Policy
Public Function Rate(p As Double, n As Integer) As Single Implements Policy.RateIf p < 25000 Then Rate = 8 Else Rate = 10
8/13/2019 Programming .NET With Visual Basic.net
35/121
Programming .NET With Visual Basic.NET
Copyright 2001 K.M.Hussain - 35
End FunctionEnd Class
Public Class GoldPolicyPublic Function Rate(p As Double, n As Integer) As Single
If n < 5 Then Rate = 9 Else Rate = 11End FunctionEnd Class
Public Class PlatinumPolicyImplements Policy
Public Function Rate(p As Double, n As Integer) As Single Implements Policy.RateIf p < 50000 Then Rate = 10 Else Rate = 12
If n >= 3 Then Rate = Rate + 1End Function
End Class
Each policy provides a Rate method which returns the rate of interest for a given
principal and for a given period. All policy classes implement Policy interface except
GoldPolicy which defines Rate without implementing policy. Compile invpol.vb to createinvpol.dll: vbc /t:library invpol.vbHere is our investment program (investment.vb) which accepts principal, period and
policy name as its arguments and displays the amount the investor will receive:
Imports SystemImports System.Reflection
Module InvestmentSub Main(args() As String)
Dim p As Double = Double.Parse(args(0))Dim n As Integer = Int32.Parse(args(1))Dim t As Type = Type.GetType(args(2))Dim pol As Policy = CType(Activator.CreateInstance(t), Policy)Dim r As Single = pol.Rate(p,n)Dim amount As Double = p*(1+r/100) nConsole.WriteLine("You will get {0:#.00}",amount)
End SubEnd Module
After obtaining the reference to Policy Type (t) we instantiate the type dynamically using
Activator.CreateInstance(t). For this to work the Type t must not be an abstract class and
must support a public default constructor. Activator.CreateInstance method declares toreturn the generic System.Object which we cast to Policy in order to invoke the Rate
method. This cast will work only if the type t implements Policy otherwise it will cause
an InvalidCastException. Compile investment.vb:
vbc /r:invpol.dll investment.vbExecute: investment 65000 6 SilverPolicy,invpol
8/13/2019 Programming .NET With Visual Basic.net
36/121
Programming .NET With Visual Basic.NET
Copyright 2001 K.M.Hussain - 36
The amount will be displayed. If GoldPolicy is used an exception will occur since
GoldPolicy does not implement policy. GoldPolicy does provide Rate method but toinvoke it we must cast the object returned by Activator.CreateInstance to Policy which
fails. Our next program (investmentdmi.vb) calls the Rate method using the so called
Dynamic Method Invocation. As this approach calls the method by its name the
conversion is not required, this version of investment program will work with all thepolicy classes in invpol.dll.
Imports SystemImports System.Reflection
Module InvestmentDMISub Main(args As String())
Dim p As Double = Double.Parse(args(0))Dim n As Integer = Int32.Parse(args(1))Dim t As Type = Type.GetType(args(2))
Dim pol As object = Activator.CreateInstance(t) no conversionDim ptypes As Type() = {GetType(Double),GetType(Integer)} Look for a method called Rate (Double, Integer)Dim m As MethodInfo = t.GetMethod("Rate",ptypes) Store the values of the argument in an array of object which can hold values of any typeDim pvalues As Object() = {p, n} Invoke the Rate method on pol instance with arguments stored in pvalues. Convert the return value of type object to SingleDim r As Single = CType(m.Invoke(pol, pvalues), Single)Dim amount As Double = p*(1+r/100) nConsole.WriteLine("You will get {0:#.00}",amount)
End SubEnd Module
Compile investmentdmi.vb using command vbc investmentdmi.vb
It will work with all four policies in invpol.dll
1.3 Creating and using Attributes: VB.Net provides a mechanism for defining
declarative tags, called attributes, which you can place on certain entities in your sourcecode to specify additional information. The information that attributes contain can be
retrieved at run time through reflection You can use predefined attributes or you can
define your own custom attributes. Attributes can be placed on most any declaration(though a specific attribute might restrict the types of declarations on which it is valid).
Syntactically, an attribute is specified by placing the name of the attribute, enclosed in
arrow brackets, in front of the declaration of the entity (class, member method etc) to
which it applies, For example:
entity declaration
8/13/2019 Programming .NET With Visual Basic.net
37/121
Programming .NET With Visual Basic.NET
Copyright 2001 K.M.Hussain - 37
Where Marker1 and Marker2 are attributes which can be applied to the entity that
follows.You can create your own custom attributes by defining an attribute class, a class that
derives directly or indirectly from System.Attribute. The Attribute class must be always
be named as SomethingAttribute so that can be used to apply this
attribute and this class must be marked with the predefined attribute AttributeUsagewhich specifies the type of the declaration to which this attribute can be applied.
The listing below (execattr.vb) defines two attributes Executable and Authorize.
Imports System applies only to a class Public Class ExecutableAttributeInherits AttributeEnd Class
applies to a method of a class Public Class AuthorizeAttributeInherits Attribute
Private _pwd As StringPublic Sub New(pwd As String)
_pwd = pwdEnd Sub
Public ReadOnly Property Password As StringGet
Password = _pwdEnd Get
End PropertyEnd Class
Next sample (executer.vb) is a program which takes a name of class at runtime and
invokes its Execute() method it does so only if the specified class has been marked with
Executable attribute. It also checks if the Execute method of the class has been marked
with Authorize attribute and if so it retrieves the password passed through the attribute
and forces the user to authorize before invoking Execute() method of the class.
Imports System
Imports System.Reflection
Module Executer
Sub Main()Dim args As String() = Environment.GetCommandLineArgs()Dim t As Type = Type.GetType(args(1)) args(1) = ClassName,AssemblyName check if the class supports Executable attribute (False -> dont search in' inheritance chain)If Not t.IsDefined(GetType(ExecutableAttribute), False)
8/13/2019 Programming .NET With Visual Basic.net
38/121
Programming .NET With Visual Basic.NET
Copyright 2001 K.M.Hussain - 38
Console.WriteLine("{0} is not executable", args(1))Exit Sub
End If lookup for a Execute method which takes no argumentsDim m As MethodInfo = t.GetMethod("Execute")
obtain AuthorizeAttribute if supported by this methodDim auth As AuthorizeAttribute = CType(Attribute.GetCustomAttribute(m, _GetType(AuthorizeAttribute)),AuthorizeAttribute)
If Not auth Is NothingConsole.Write("Enter Password: ")If Not Console.ReadLine() = auth.Password
Console.WriteLine("Password is incorrect")Exit Sub
End IfEnd Ifm.Invoke(Nothing, Nothing) Execute is a static method and takes no arg
End SubEnd Module
Compile above program using command: vbc executer.vb execattr.vb
Apps.vb provides few classes for testing executer program.
Imports System Public Class AClock
Public Shared Sub Execute()Console.WriteLine("Its {0}", DateTime.Now)
End SubEnd Class Public Class AGame
Public Shared Sub Execute()Dim r As Random = New Random()Dim p As Integer = r.Next(1,10)Console.Write("Guess a number between 1 and 10: ")Dim q As Integer = Int32.Parse(Console.ReadLine())If p = q Then
Console.WriteLine("You won!!!")Else
Console.WriteLine("You lost, correct number was {0}",p)End If
End SubEnd ClassPublic Class AMessage
Public Shared Sub Execute()Console.WriteLine("Hello World!")
End SubEnd Class
8/13/2019 Programming .NET With Visual Basic.net
39/121
Programming .NET With Visual Basic.NET
Copyright 2001 K.M.Hussain - 39
Classes AClock and AGame are both marked with Executable attribute and so executer
will execute them. Since Execute method of AGame is marked with Authorize attribute,executer will prompt the user for password if his password matches with tiger
AGame.Execute will be invoked. AMessage class will not be executed as it is not marked
with the Executable attribute. Compile apps.vb to create a dll using command
vbc /t:library apps.vb execattr.vbTest executer:
executer AClock,apps will show the current time
executer AGame,apps will prompt for password
executer AMessage,apps will not execute
8/13/2019 Programming .NET With Visual Basic.net
40/121
Programming .NET With Visual Basic.NET
Copyright 2001 K.M.Hussain - 40
Chapter 5: Multithreading
1.1 Processes and Threads: In this chapter we discuss concurrent programming ie
executing multiple blocks of code simultaneously. Lets first see how to launch a new
process from a .NET executable.The program below (processtest.vb) launches
notepad.exe and asynchronously counts up from 1 to 10000 and then destroys the notepadprocess.
Imports SystemImports System.Diagnostics for Process class
Module ProcessTestSub Main()
Dim p As Process = Process.Start("notepad.exe")Dim i As IntegerFor i = 1 To 10000
Console.WriteLine(i)Nextp.Kill()
End SubEnd Module
Compile: vbc /r:system.dll processtest.vb
When you execute processtest you will notice how two processes (processtest.exe and
notepad.exe) can execute concurrently. Threads are parts of same process which executeconcurrently. In .NET Base Class Library(BCL) the System.Threading namespace
provides various classes for executing and controlling threads. The program below(threadtest1.vb) executes two loops simultaneously using threads.
Imports SystemImports System.Threading for Thread class
Module ThreadTest1Sub SayHello()
Dim i As Integer = 1Do
Console.WriteLine("Hello {0}",i)
i = i + 1LoopEnd SubSub Main()
Dim t As Thread = New Thread(AddressOf SayHello)t.Start()Dim i As IntegerFor i = 1 To 10000
8/13/2019 Programming .NET With Visual Basic.net
41/121
Programming .NET With Visual Basic.NET
Copyright 2001 K.M.Hussain - 41
Console.WriteLine("Bye {0}",i)Nextt.Abort()
End SubEnd Module
We create a Thread instance by passing it an object of ThreadStart delegate which
contains a reference to our SayHello method. When the thread is started (using its Start
method) SayHello will be executed in an asynchronous manner. Compile and run theabove program, you will notice series of Hello and Bye messages appearing on the
screen. When the program is executed the CLR launches the main thread (the one which
executes Main method) within the body of main we launch thread t (which executes
SayHello method). While thread t goes in an infinite loop printing Hello on the consolethe main thread concurrently prints Bye on the console 10000 times, after which the main
thread kills thread t invoking its Abort() method before it itself terminates. If thread t
would not be aborted in this fashion it would continue to execute even after the main
thread terminates. We could also mark thread t as Back Ground thread, in which case twould automatically abort soon after the last foreground thread (main thread in this case)
would terminate. The program below (threadtest2.vb) shows how:
Imports SystemImports System.Threading
Module ThreadTest2Sub SayHello()
Dim i As Integer = 1Do
Console.WriteLine("Hello {0}",i)i = i + 1
LoopEnd SubSub Main()
Dim t As Thread = New Thread(AddressOf SayHello)t.IsBackground = Truet.Start()Dim i As IntegerFor i = 1 To 10000
Console.WriteLine("Bye {0}",i)Next
End SubEnd Module
Just running threads simultaneously is not the whole thing, we sometimes need to control
them In program below (sleepingthread.vb) the main thread prints Hello 15 timeswhile at the same time another thread t prints Welcome 5 times followed by a
Goodbye. The programs sees to it that the Goodbye message printed by thread t is
always the last message of the program. To achieve this control thread t puts itself to
8/13/2019 Programming .NET With Visual Basic.net
42/121
Programming .NET With Visual Basic.NET
Copyright 2001 K.M.Hussain - 42
sleep for 5 second after printing its Welcome messages, this time is big enough for the
main thread to print its Hello messages. After doing so the main threads interrupts thesleeping thread t, such an interruption causes the Sleep method to throw
ThreadInterruptedException. Thread t handles this exception and finally prints Goodbye
message.
Imports SystemImports System.Threading
Module SleepingThreadSub Run()
Dim i As IntegerFor i = 1 To 5
Console.WriteLine("Welcome {0}",i)NextTry
Thread.Sleep(5000)Catch e As ThreadInterruptedExceptionConsole.WriteLine("Sleep Interrupted")
End TryConsole.WriteLine("Goodbye")
End SubSub Main()
Dim t As Thread = New Thread(AddressOf Run)t.Start()Dim i As IntegerFor i = 1 To 15
Console.WriteLine("Hello {0}",i)Nextt.Interrupt()
End SubEnd Module
Our next program (joiningthread.vb) reverses the roles of main thread and thread t. Now
the main thread prints Welcome messages followed by Goodbye message and thread tprints Hello messages. After printing all the Welcome messages and before printing
Goodbye, the main thread joins itself to thread t (i.e blocks itself until t terminates) .
Imports SystemImports System.Threading
Module JoiningThreadSub Run()
Dim i As IntegerFor i = 1 To 15
Console.WriteLine("Hello {0}",i)Next
8/13/2019 Programming .NET With Visual Basic.net
43/121
Programming .NET With Visual Basic.NET
Copyright 2001 K.M.Hussain - 43
End SubSub Main()
Dim t As Thread = New Thread(AddressOf Run)t.Start()Dim i As Integer
For i = 1 To 5Console.WriteLine("Welcome {0}",i)Nextt.Join()Console.WriteLine("Goodbye")
End SubEnd Module
1.2 Thread Sysnchronization and Coordination: In program below (syncthreads.vb)
two threads simultaneously execute Withdraw method on the same instance of Account
class. Though this method checks for overwithdrawl but as both the threads are
simultaneously checking whether there is enough balance in the account beforededucting, there is quite a possiblity of over withdrawl
Imports SystemImports System.Threading
Class AccountPrivate balance As Double = 5000Sub Withdraw(amount As Double)
Console.WriteLine("Withdrawing {0}",amount)If amount > balance Then Throw New Exception("Insufficient Funds")Thread.Sleep(10) some other stuffbalance -= amountConsole.WriteLine("Balance {0}",balance)
End SubEnd Class
Module SyncThreadsDim acc As New Account
Sub Run()acc.Withdraw(3000)
End Sub
Sub Main()Dim t As Thread = New Thread(AddressOf Run)t.Start()acc.Withdraw(3000)
End SubEnd Module
8/13/2019 Programming .NET With Visual Basic.net
44/121
8/13/2019 Programming .NET With Visual Basic.net
45/121
Programming .NET With Visual Basic.NET
Copyright 2001 K.M.Hussain - 45
Imports SystemImports System.ThreadingModule WaitingThread
Dim obj As New Object
Sub Run()Dim i As IntegerFor i = 1 To 15
Console.WriteLine("Hello {0}",i)NextMonitor.Enter(obj)Monitor.Pulse(obj)Monitor.Exit(obj)
End SubSub Main()
Dim t As Thread = New Thread(AddressOf Run)
t.Start()Dim i As IntegerFor i = 1 To 5
Console.WriteLine("Welcome {0}",i)NextMonitor.Enter(obj)Monitor.Wait(obj)Monitor.Exit(obj)Console.WriteLine("Goodbye")
End SubEnd Module
1.3 Asunchronous Programming Model: Normally when a caller invokes a method,
the call is synchronousthat is the caller has to wait for the method to return before the
remaing code can be executed. .NET has an inbuilt support for asynchronous methodinvocation. Using this facility the caller can issue a request for invocation of a method
and concurrently execute the remaing code. For every delegate declared in an assembly
the compiler emits a class (subclass of System.MulticastDelegate) with Invoke,
BeginInvokeand EndInvokemethods. For example condider a delegate declared as:
Delegate Function MyWorker(ch As Char, max As Integer) As Integer
The compiler will emit MyWorker class:
Class MyWorker : Inherits System.MulticastDelegatePublic Function Invoke(ch As Char, max As Integer) As Integer
Public Function BeginInvoke(ch As Char, max As Integer, cb As _
System.AsyncCallback , asyncState as Object) As System.IAsyncResultPublic Function EndInvoke(ch As Char, max As Integer, result As _
System.IAsyncResult) As Integer
End Class
8/13/2019 Programming .NET With Visual Basic.net
46/121
Programming .NET With Visual Basic.NET
Copyright 2001 K.M.Hussain - 46
The BeginInvoke and EndInvoke methods can be used for asynchronous invocation of amethod pointed by MyWorker delegate. In the example below (asynctest1.vb) DoWork
method (which displays character ch max number of times) is invoked asynchronously
with character +, in the next statement this method is directly invoked with character
*. You will notice both + and * are displayed (1000 times each) on the consolesimultaneously. As an asynchronous call executes within its own background thread, we
have used Console.Read() to pause the main thread.
Imports SystemDelegate Function MyWorker(ch As Char, max As Integer) As IntegerModule AsyncTest1
Dim worker As MyWorker
Function DoWork(ch As Char, max As Integer) As IntegerDim t As Integer = Environment.TickCount returns the number of milliseconds
elapsed since the system startedDim i As IntegerFor i = 1 To max
Console.Write(ch)NextDoWork = Environment.TickCount - t
End Function
Sub Main()Console.WriteLine("Start")worker = AddressOf DoWorkworker.BeginInvoke("+", 1000,Nothing,Nothing) asynchronous callDoWork("*",1000) synchronous callConsole.Read() pause until user enters a key
End SubEnd Module
But how do we retrieve the value returned by DoWork if it is invoked asynchronously?The return value can be obtained by invoking EndInvoke method of delegate passing it
the IAsyncResult instance which is returned by BeginInvoke method. The EndInvoke
method blocks the current thread until asynchronous call is completed. Our next example
(asynctest2.vb) demonstrates this approach.
Imports System
Delegate Function MyWorker(ch As Char, max As Integer) As Integer
Module AsyncTest2Dim worker As MyWorker
Function DoWork(ch As Char, max As Integer) As Integer
8/13/2019 Programming .NET With Visual Basic.net
47/121
8/13/2019 Programming .NET With Visual Basic.net
48/121
Programming .NET With Visual Basic.NET
Copyright 2001 K.M.Hussain - 48
Sub Main()Console.WriteLine("Start")worker = AddressOf DoWorkDim result As IAsyncResult = worker.BeginInvoke("+", 1000, _
AddressOf CallMeBack,Nothing)
DoWork("*",1500)Console.Read()End Sub
End Module
8/13/2019 Programming .NET With Visual Basic.net
49/121
Programming .NET With Visual Basic.NET
Copyright 2001 K.M.Hussain - 49
Chapter 6: Streams
1.1 Input and Output Streams: The Stream class and its subclasses provide a generic
view of data sources and repositories, isolating the programmer from the specific details
of the operating system and underlying devices. Streams involve these three fundamental
operations:
1. Streams can be read from. Reading is the transfer of data from a stream into a datastructure, such as an array of bytes.
2. Streams can be written to. Writing is the transfer of data from a data structure into a
stream.
3. Streams can support seeking. Seeking is the querying and modifying of the currentposition within a stream.
All classes that represent streams inherit from the System.IO.Stream class. An applicationcan query a stream for its capabilities by using the CanRead, CanWrite, and CanSeek
properties. TheReadand Writemethods read and write data in a variety of formats. Forstreams that support seeking, the Seek and Positioncan be used to query and modify thecurrent position a stream. Some stream implementations perform local buffering of the
underlying data to improve performance. For such streams, the Flushmethod can be used
to clear any internal buffers and ensure that all data has been written to the underlyingdata source or repository. Calling Closeon a stream flushes any buffered data, essentially
calling Flushfor you. Closealso releases operating system resources such as file handles,
network connections, or memory used for any internal buffering
.The System.IO.FileStreamclass is for reading from and writing to files. This class can
be used to read and write bytes to a file. The System.IO.Fileclass, used in conjunction
with FileStream, is a utility class with static methods primarily for the creation ofFileStreamobjects based on file paths. The program below (readfile.vb) displays content
of a file whose name is passed through the command line.
Imports SystemImports System.IOImports System.Text For EncodingModule ReadFile
Sub Main()Dim args As String() = Environment.GetCommandLineArgs()Dim s As Stream = new FileStream(args(1), FileMode.Open)
Dim size As Integer = CInt(s.Length)Dim buffer As Byte() = New Byte(size){}s.Read(buffer,0,buffer.Length)s.Close()Dim text As String = Encoding.ASCII.GetString(buffer)Console.WriteLine(text)
End SubEnd Module
8/13/2019 Programming .NET With Visual Basic.net
50/121
Programming .NET With Visual Basic.NET
Copyright 2001 K.M.Hussain - 50
First we create a stream to the mentioned file for reading (FileMode.Open) then wecalculate the number of bytes that can be read from the stream and create a buffer of that
size. Next we read the data from the stream into our buffer. Finally we convert this array
of bytes into an ASCII text for displaying it on console. We can also obtain a read-only
stream to a file using Fileclass: Dim s As Stream = File.OpenRead(file_name); wherefile_name is a string containing the name of the file.
The next program (writefile.vb) writes text in first command line argument into a file insecond command line argument. If the file does not exists, it will be created else the text
will be appended to it.
Imports SystemImports System.IOImports System.Text For Encoding
Module WriteFileSub Main()Dim args As String() = Environment.GetCommandLineArgs()Dim s As Stream = new FileStream(args(2), FileMode.Append, FileAccess.Write)Dim text As String = args(1) + Environment..NewLi