Programming .NET With Visual Basic.net

download Programming .NET With Visual Basic.net

of 121

Transcript of Programming .NET With Visual Basic.net

  • 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