10. Parameters to Procedures

 

All the code of Visual Basic applications is written in procedures. There are four different types of procedures in Visual Basic:

     The first is a sub, which does not return a value.

     The second is a Function that returns a value.

     The third is the event handling code.

     The fourth is a property module that also contains code.

 

In VB, code cannot be written anywhere but in the above four procedures. The advantage of using procedures is that they make applications more readable, since code that is oft repeated, is positioned within them. It would not be wrong to say that without procedures, no application can be written in VB.

 

The main logic behind having procedures is to write the code once, and then, call it several times from different places. By writing procedures, the program can be broken down into smaller logical units. It is always easier to debug 10 small procedures, rather than debugging one large program.

 

It is on account of the presence of procedures that the functions like WriteLine are available, and which can be used without us having to worry about how they are written.

The sub access modifier is 'public' by default, and thus, a sub can be called from anywhere in the program.

 

a.vb

class zzz

shared Sub Main()

End Main

End class

 

Error

c:\il\a.vb(3) : error BC30678: 'End' statement not valid.

 

The sub Main requires an 'end sub', or else the above stated error is generated. In the world of VB, there is no 'begin' statement, but there is a mandatory 'end' statement.

 

a.vb

class zzz

shared Sub Main()

call abc

End sub

shared sub abc

System.Console.WriteLine("hi")

end sub

End class

 

Output

hi

 

To call a sub or a function, the 'call' statement may be used. This, however is optional, and hence, is not implemented in right earnest. But you are bound to encounter it sometime.

 

Passing Parameters

 

a.vb

class zzz

shared Sub Main()

End sub

sub abc( i , j as integer)

end sub

End class

 

Error

c:\il\a.vb(4) : error BC30529: All parameters must be explicitly typed if any are.

 

Since the option of 'strict' is switched off, we are not required to specify the data types of the parameters. They default to type Object.

 

The erratic and fastidious behavior witnessed above, is the fallout of having specified the type for only one parameter, and not for all of them. You should either specify the types for all the parameters or for none of them. Any half-baked action results in an error being hurled at us.

 

a.vb

class zzz

shared Sub Main()

End sub

function abc( abc as integer)

end function

End class

 

Error

c:\il\a.vb(4) : error BC30530: Parameter cannot have the same name as its defining function.

 

There are subtle differences between functions and subs. In a sub, the parameters can have any name, but this is not true of a function.  You may recall that in a function, there are two ways of returning values; The first is by using the return statement, and the second is by simply initializing the name of the function.

 

If a parameter is assigned the same name as a function, the compiler is sure to feel baffled. This is because, it is an extremely arduous task to ascertain whether the programmer is setting the return value, or is changing the value of the parameter. This error applies to functions only, since subs do not return values.

 

a.vb

class zzz

shared Sub Main()

dim j as integer = 100

dim a as new zzz

a.abc(j)

System.Console.WriteLine(j)

j = 100

a.abc((j))

System.Console.WriteLine(j)

End sub

sub abc( byref i as integer)

i = 10

end sub

End class

 

Output

10

100

 

When parameters are passed by reference, the changes made in the sub are also reflected in the original variable. Therefore, the first call to sub abc changes the value of j from 100 to 10. So far, so good!

 

After resetting the value of j back to 100, the sub abc is called again, but this time, j is enclosed within a pair of round brackets. The brackets are a subtle way of informing the compiler that the parameter is being passed by value and not by reference. Thus, the second call, which is a call by value, does not lead to a change in the value of the variable j. Even if the parameter i is set to byval, the use of round brackets shall not cause any error.

 

When it comes to passing parameters, there are four distinct possibilities to mull over. The parameters can either be 'byval' or 'byref' types, or they may be 'value' or 'reference' types.

 

It is easiest to understand the concept of passing parameters by value. Here, any change in the value of the variable in the procedure, is not reflected in the original variable.

Passing parameters by reference is very distinct from the above. The value contained in the original variable, changes with any change introduced in the variable in the sub. Reference type variables are actually pointers to the original data.

 

A 'pass by value' affects only the value of the variable or the member, without affecting the original variable; whereas, a 'pass by ref' changes both, the object, i.e. the original variable it is pointing to, as well as, its members.

 

The advantage of 'pass by ref' is that the calling sub can change the value of the parameters. There is no significant overhead in passing a variable either by ref or by value. However, it is advantageous to pass larger value types such as structures by ref, and not by value, or else, a large number of variables will have to be copied on to the stack.

 

Optional Arguments

 

a.vb

class zzz

shared Sub Main()

dim a as new zzz

a.abc(100,200)

a.abc(100,10)

a.abc(50)

End sub

sub abc( i as integer , optional j as integer = 10)

System.Console.WriteLine("{0} {1}", i , j)

end sub

End class

 

Output

100 200

100 10

50 10

 

At times, there exist a large number of parameters to a procedure. This is where the concept of optional parameters comes handy.

 

The sub abc has two parameters, i and j. The parameter j is assigned a value of 10. It is optional, since it is tagged with the 'optional' keyword.

 

However, the sub abc can be called with two parameters, 100 and 200, as a result of which, the 'optional' keyword is devoid of any effect at all. The default value is overwritten with the new value of 100. Hence, the output shows the value of j as 200.

 

The second call to the sub abc results in assigning the default value of 10 to the second parameter. However, there is no technique for notifying the sub abc about whether the call has been made with two parameters or with a single one. So, it behaves like it did earlier, and reassigns the value of 10 to the second parameter.

 

The last call to sub abc is made with one parameter only. Therefore, the first parameter i assumes this new value of 50, thus, resulting in the second parameter j assuming its default value of 10.

 

The 'optional' keyword proves to be useful, since the user is not required to call the procedure with all its parameters. The parameters that have been overlooked are assigned their default values. However, the sub has no way of identifying the parameters that it has been called with. Now, replace the above sub statement with the following:

 

sub abc( i as integer , optional j as integer )

 

Error

c:\il\a.vb(8) : error BC30812: Optional parameters must specify a default value.

 

The optional parameter must have a default value, or else, the very essence of the optional keyword is lost. This is the only way of assigning a value to the optional parameter.

 

a.vb

class zzz

shared Sub Main()

End sub

sub abc( i as integer = 10)

end sub

End class

 

Error

c:\il\a.vb(4) : error BC32024: Default values cannot be supplied for parameters that are not declared 'Optional'.

 

The reverse is also true. A parameter cannot be assigned a default value, unless it is prefixed with the 'optional' keyword.

 

a.vb

class zzz

dim k as integer = 10

shared Sub Main()

End sub

sub abc( i as integer , optional j as integer = k )

end sub

End class

 

Error

c:\il\a.vb(5) : error BC30059: Constant expression is required.

 

The second condition imposed on optional arguments is that, the value has to be a constant expression, which can be determined at compile time. Thus, the instance variable k, which has a value of 10, is not declared as a constant, since its value can be changed before invoking the sub abc. Thus, an error is thrown.

 

a.vb

class zzz

dim k as integer = 10

shared Sub Main()

End sub

sub abc( i as integer , optional j as integer = i )

end sub

End class

 

Error

c:\il\a.vb(5) : error BC30451: Name 'i' is not declared.

 

Furthermore, other parameters cannot be used to supply a value to the default parameter. The other parameters are not visible to each other, as has been pointed out by the error message.

 

a.vb

class zzz

shared Sub Main()

End sub

sub abc( optional i as integer = 10, j as integer )

end sub

End class

 

Error

c:\il\a.vb(4) : error BC30202: 'Optional' expected.

 

The last rule is that, if we make any one parameter optional, all the parameters following it have to be made optional. Therefore, since the first parameter i has been made optional, the parameter j, which follows i, must also be made optional.

 

a.vb

class zzz

shared Sub Main()

dim a as new zzz

a.abc(100,,1000)

End sub

sub abc( i as integer , optional j as integer = 10 , optional k as integer = 30)

System.Console.WriteLine("{0} {1} {2}",i,j,k)

end sub

End class

 

Output

100 10 1000

 

In the above example, the second and the third parameters are declared as optional. While calling the abc sub, we intend to skip the second parameter, but we would like to specify the third parameter. This is obtained by not specifying any value between the commas, as revealed above. Use of optional parameters is another way of overloading variables, where the data type is the same.

 

a.vb

class zzz

shared Sub Main()

dim a as new zzz

End sub

sub abc( i as integer , optional j as integer = 10 )

end sub

sub abc( i as integer )

end sub

End class

 

Error

c:\il\a.vb(5) : error BC30300: 'Public Sub abc(i As Integer, [j As Integer = 10])' and 'Public Sub abc(i As Integer)' cannot overload each other because they differ only by optional parameters.

 

The above error emanates from the fact that the two abc subs that have been overloaded, differ only in the second sub, which has an optional parameter. We had mentioned earlier that procedures can share the same name, but must have different parameters. They would be deemed to be distinct, since the method signatures would vary.

 

In the above case, we can have both the subs abc, with the same single integer as a parameter. However, the compiler would be thoroughly bewildered as to which abc to call. Therefore, it would report an error.

 

The first sub abc can be called with either one, or two parameters, while the second sub abc is to be called only with one parameter. But, when the sub abc is called with one single parameter, the compiler is awe-struck, as both the subs fit the bill. Observe that the default values in the error message are placed within square brackets.

 

 

 

a.vb

class zzz

shared Sub Main()

dim a as new zzz

End sub

sub abc( i as integer , optional j as integer = 10 )

end sub

sub abc( i as integer , optional j as string = "hi")

end sub

End class

 

Error

c:\il\a.vb(5) : error BC30696: 'Public Sub abc(i As Integer, [j As Integer = 10])' and 'Public Sub abc(i As Integer, [j As String = "hi"])' cannot overload each other because they differ only by the types of optional parameters.

 

The error appears much the same as the one shown above. Both the abc subs have the first parameter as an integer, but the second one is optional. The types of the second parameter are different. The ambiguity arises when the sub abc is called with a single parameter, since the VB compiler realizes that both the abc subs can be executed under such a situation.

 

a.vb

class zzz

shared Sub Main()

dim a as new zzz

End sub

End class

class yyy

overridable sub abc( i as integer , optional j as string = "hi")

end sub

end class

class xxx

inherits yyy

overrides sub abc( i as integer , optional j as string = "bye")

end sub

end class

 

Error

c:\il\a.vb(12) : error BC30307: 'Public Overrides Sub abc(i As Integer, [j As String = "bye"])' cannot override 'Public Overridable Sub abc(i As Integer, [j As String = "hi"])' because they differ by the default values of optional parameters.

 

The error is generated because the sub in the base class has an optional value of "hi", while the sub in the derived class has an optional value of "bye".

 

Overriding a method in the base class calls for the derived class to be identical in all respects, including the default values. The same concept applies to overriding and overloading also. Hence, we will not reiterate them here.

 

a.vb

class zzz

shared Sub Main()

dim a as new zzz

End sub

End class

class yyy

overridable sub abc( byval i as integer)

end sub

end class

class xxx

inherits yyy

overrides sub abc( byref i as integer)

end sub

end class

 

Error

c:\il\a.vb(12) : error BC30398: 'Public Overrides Sub abc(ByRef i As Integer)' cannot override 'Public Overridable Sub abc(i As Integer)' because they differ by a parameter that is marked as 'ByRef' versus 'ByVal'.

 

While we are converging around the subject of overloading methods, it would be pertinent to mention that the above error creeps in, since the two subs abc have the parameter i specified as byval in the base class, and as byref in the derived class. They must be either byval or byref in both, the base class, as well as the derived class.

 

a.vb

class zzz

shared Sub Main()

End sub

End class

class yyy

sub abc( i as integer , optional j as aaa = 12)

end sub

end class

structure aaa

dim i k as integer

end structure

 

Error

c:\il\a.vb(6) : error BC31405: Optional parameters cannot have structure types.

 

The optional parameters cannot have a type of a structure specified for them. Since the optional parameter in the sub is specified to be of type structure aaa, the error is reported.

 

So far, we have been passing parameters by position. This is because, we have been passing them in the same sequence as they had been defined in the sub or function. Now, we shall pass them by name instead.

 

a.vb

class zzz

shared Sub Main()

dim a as new zzz

a.abc(1,"hi",k:=2)

a.abc(20,j:="no",k:=10)

a.abc(i:=200,j:="no",k:=20)

End sub

sub abc( i , j , k )

System.Console.WriteLine("{0} {1} {2}",i,j,k)

end sub

End class

 

Output

1 hi 2

20 no 10

200 no 20

 

The sub abc takes three parameters, i, j and k. We can pass them either by position, i.e. by specifying the parameters as we have been doing so far, or by employing the 'pass by name' method. In this method, we use the name of the parameter, followed by the := sign, and then, followed by the actual value. The sub that is called has no means of identifying the method that has been used.

 

a.abc(200 , k := 20 , "no")

 

c:\il\a.vb(6) : error BC30241: Named argument expected.

 

We do not have 'carte blanche', i.e. complete discretion, to act in any manner that we desire. The basic rule in VB is that, once we initiate the process of passing parameters using the concept of 'call by name', we cannot switch to 'call by position' midway. We have to stick to the same method till the end of the program.

 

The single biggest benefit of 'call by name' comes to the fore, when a method has a vast number of optional parameters. 'Call by name' is easier to implement, since there is no need to place inessential commas between blank parameters. Whether we are passing parameters by value or by name, the requisite parameters have to be specified.

 

a.vb

class zzz

shared Sub Main()

End sub

shared sub new( i as integer)

end sub

End class

 

Error

c:\il\a.vb(4) : error BC30479: Shared 'Sub New' cannot have any parameters.

 

While we are on the subject of parameters, we wish to enlighten you about the fact that the static constructor cannot have any parameters. This is because, the static constructor is called at the time of loading the object, and at this stage, no control can be exercised over it.

 

a.vb

class zzz

shared Sub Main()

End sub

Public Property aa() As Integer

Get

End Get

Set (byref i As Integer)

End Set

End Property

End class

 

Error

c:\il\a.vb(7) : error BC31065: 'Set' parameter cannot be declared 'ByRef'.

 

A property parameter in the set cannot have a byref, since it is not allowed to change the value of the original variable. The Set accessor is called, whenever the value of the property has to be changed. It is not used to change the value of the variable that sets the value of the property.

 

a.vb

class zzz

shared Sub Main()

End sub

Public default Property aa() As Integer

Get

End Get

Set (i as integer)

End Set

End Property

End class

 

Error

c:\il\a.vb(4) : error BC31048: Properties with no required parameters cannot be declared 'Default'.

 

A default property or an indexer requires a parameter, since that is the only available means of using it as an index into an array of values.

 

a.vb

imports system

class zzz

shared Sub Main()

dim a as new zzz

a.abc("Hi",10,20,30)

a.abc("Bye")

Dim b() As integer = {100,200}

a.abc("No", b)

End sub

sub abc( k as string, paramarray s() as integer)

dim i,j as integer

j = s.GetUpperBound(0)

System.Console.WriteLine("{0} {1}" , k , j)

For i = 0 To s.GetUpperBound(0)

System.Console.Write(s(i) & " ")

Next i

System.Console.WriteLine()

end sub

End class

 

Output

Hi 2

10 20 30

Bye -1

No 1

100 200

 

The program has a procedure that acts like a WriteLine function, where a multiple number of parameters can be specified. Normally, the hawk-eyed VB compiler ensures that the number of parameters allotted to the procedure, does not exceed its limit. The only way of ascertaining this is by using a parameter array.

 

The sub abc takes two parameters, i.e. a string and a paramarray of type integer. The paramarray keyword stands for an 'array of parameters', which can take a varying number of arguments. The first call to the sub abc takes one string and three individual integers. The string value is assigned to the string parameter, and the three integers are stored in  's', which is a paramarray type. Thus, 's' now becomes an array of three integers.

 

The array type has a function called GetUpperBound, which returns the largest dimension or upper bound of the size of the array. The parameter 0 is a dimension parameter. Since the array comprises of 3 members, the function returns 2, which is 1 less than the size.

 

We display the return value of this function, and then, use the 'for next' loop to flaunt the individual members. Had the GetUpperBound function returned the actual size of the array, we would then have had to subtract 1 from the value contained in variable j. This loop prints out the individual members of the array. The sub abc is then called with only one parameter. The value of -1 returned by the GetUpperBound function signifies that the value is nothing or null.

 

In the third case, we create an array 'b' of two integers, and pass only this array as a parameter. The sub abc is oblivious to whether we are passing an array or individual values. However, the end result is that we obtain an array containing all the integers.

 

This is the manner in which we can handle a varying number of arguments. Let us consider the restrictions that are imposed upon parameter arrays.

 

a.vb

class zzz

shared Sub Main()

End sub

sub abc( k as string, paramarray s() as integer , paramarray t() as string)

end sub

End class

 

Error

c:\il\a.vb(4) : error BC30192: ParamArray parameter must be last in parameter list.

 

We can have only one paramarray per method. The above error has come about, since there exist two paramarrays of different types, which is not permissible.

 

The second condition is that the paramarray has to be the last parameter in the sequence.

 

a.vb

class zzz

shared Sub Main()

End sub

sub abc( k as string, byref paramarray s() as integer )

end sub

End class

 

Error

c:\il\a.vb(4) : error BC30667: ParamArray parameters must be declared 'ByVal'.

 

The third restriction is that the paramarray has to be passed as byval, and not as byref. This is very obvious, since if both were allowed, the system would have had to figure out which of the original variables can be modified. The documentation recommends the use of the byval keyword, even though it is the default value. The sub with the paramarray parameter receives a one-dimensional array. The default is an empty array of the paramarray data type.

 

a.vb

class zzz

shared Sub Main()

End sub

sub abc( optional k as string = "hi", paramarray s() as integer )

end sub

End class

 

Error

c:\il\a.vb(4) : error BC30046: Method cannot have both a ParamArray and Optional parameters.

 

Life is full of 'either-or' choices. If we use the 'optional' keyword, the 'paramarray' keyword cannot be specified. Thus, we can have either 'optional' or 'paramarray' parameters.

 

a.vb

class zzz

shared Sub Main()

dim a as new zzz

a.abc(s:=10)

End sub

sub abc(paramarray s() as integer )

end sub

End class

 

Error

c:\il\a.vb(4) : error BC30587: Named argument cannot match a ParamArray parameter.

 

There is no way by which a named argument can be used to specify a paramarray parameter. This is because, the paramarray parameters are varying in number, and they have to be separated by spaces. This surely would confound the compiler. Hence, only parameters by position can be used.

 

a.vb

class zzz

shared Sub Main()

End sub

sub abc(paramarray s as integer )

end sub

End class

 

Output

c:\il\a.vb(4) : error BC30050: ParamArray parameter must be an array.

 

The paramarray parameter must be declared as an array, since its job is to store the multiple values that can be theoretically passed.

 

a.vb

class zzz

shared Sub Main()

End sub

sub abc(paramarray s(,) as integer )

end sub

End class

 

Error

c:\il\a.vb(4) : error BC30051: ParamArray parameter must be a one-dimensional array.

 

The second condition is that the paramarray can only be a one-dimensional array.

 

An overloaded procedure must satisfy certain criteria, i.e. the overloaded procedures must have the same name, or else, overloading makes no sense. Since the names are identical, the overloaded procedures must differ from each other in three different ways:

     The first is that the procedures must have different number of arguments.

     The second is in respect of the order of the arguments.

     The third is relates to the data types of the arguments.                         

 

The three aforementioned aspects put together, are collectively called the 'signature' of the procedure.

 

The modifiers of 'pubic', 'shared' and 'static' do not form a part of the procedure signature. The other entities that do not belong to the method signature are argument names, keywords like 'byref' and 'optional', and the return data types of the functions.

 

a.vb

class zzz

shared Sub Main()

End sub

End class

class aaa

overloads function abc() as integer

end function

overloads function abc() as string

end function

end class

 

Error

c:\il\a.vb(6) : error BC30301: 'Public Overloads Function abc() As Integer' and 'Public Overloads Function abc() As String' cannot overload each other because they differ only by return types.

 

The above error crops up, since the two abc functions encompass the same parameter lists, but they return an integer in one case, while a string in the other. The return value of a function is not mission-critical, since the value need not be stored.

 

Therefore, functions with different return values cannot be overloaded. However, functions that overload each other with different argument lists may have different return values.

 

a.vb

class zzz

shared Sub Main()

End sub

End class

class aaa

overloads sub abc()

end sub

overloads function abc() as string

end function

end class

 

 

 

Error

c:\il\a.vb(6) : error BC31073: 'abc' conflicts with a function by the same name declared in 'aaa'.

 

The aforementioned error is tossed at us because the sub abc does not take any parameters, and simultaneously, the function abc that ensues, is also devoid of any parameters. Thus, the compiler is unable to discriminate between the sub and the function, since they both have the same signature.

 

By assigning the function and the sub with different parameter lists, the error ebbs off. Internally, VB does not distinguish between subs and functions. If a function and a property both have the same name, the above error is reported.

 

For the sake of revision, we repeat that whenever a function like abc( i as integer, optional j as string = "hi") is created, in effect, we are creating two functions: one with a single integer and the other with an integer and a string. Therefore, another function with the above signature cannot be created. These rules get more complicated when multiple argument lists are involved.

 

a.vb

class zzz

shared Sub Main()

dim a as new zzz

a.abc(10)

a.abc(10,20)

a.abc(10,20,30)

End sub

overloads sub abc(paramarray i() as integer)

System.Console.WriteLine("paramarray")

end sub

overloads sub abc(i as integer )

System.Console.WriteLine("single")

end sub

End class

 

Output

single

paramarray

paramarray

 

The above example demonstrates the complexities associated with the paramarray during 'procedure overloading'. There are two subs called abc. However, since the signatures for all of them are different, no compiler errors are generated.

 

The signatures are different because, the first sub takes a paramarray, while the second one takes a single integer. When the sub abc is called with a single integer, there is bound to be a dilemma as to which of the subs is to be called, since they both fit the bill.

 

In the first call, the system prefers the single sub with an integer as parameter. For the second and the third calls of the sub abc, the system calls the sub with the single paramarray, since the sub with the single parameter does not fit the bill.

 

We have tried to introduce one more definition in

 

overloads sub abc(i as integer , paramarray j() as integer)

System.Console.WriteLine("two")

end sub

 

We had hoped that it would correspond with all the three calls. However, we land up with errors galore, as the compiler gets utterly baffled!

 

A sub with a paramarray parameter represents at least three subs. The first is a sub that has a single dimensional array, the second is a sub with no parameter, and a third is a sub that has a series of individual parameters, of the data type of  paramarray.

 

Before concluding this treatise on procedures, let us examine a few error messages that we have not touched upon so far.

 

a.vb

class zzz

shared Sub Main()

End sub

sub abc()

exit property

end sub

End class

 

Error

c:\il\a.vb(5) : error BC30066: 'Exit Property' is not valid in a Function or Sub.

 

Unlike a return statement, an Exit property statement cannot be used to quit out of a property. In the same way, we cannot replace the word 'property' with 'function'. It will cast an error, as depicted below:

 

C:\il\a.vb(5) : error BC30067: 'Exit Function' is not valid in a Sub or Property.

 

a.vb

class zzz

shared Sub Main()

End sub

function New

end function

End class

 

Error

c:\il\a.vb(4) : error BC30493: Constructor must be declared as a Sub, not as a Function.

 

The constructor must be declared as a sub and not as a function, since constructors do not return values. By defining them as functions, we are explicitly stating that they do return values.

 

a.vb

class zzz

shared Sub Main()

End sub

sub New handles e.abc

end sub

End class

Error

c:\il\a.vb(4) : error BC30497: 'Sub New' cannot handle events.

 

The constructor cannot handle any events, since it can never be called explicitly. Thus, using the 'handles' keyword with it generates a compiler error. A constructor's singular task is to get called only at the time of creation of an object. Thus, it cannot handle events.

 

a.vb

class zzz

shared Sub Main()

End sub

sub new implements yyy.abc

end sub

End class

 

Error

c:\il\a.vb(4) : error BC31042: 'Sub New' cannot implement interface members.

 

The constructor is also unable to implement any interface functions.

 

a.vb

Public Class zzz

Shared Sub Main()

End Sub

sub new

me.new

end sub

End Class

 

Error

c:\il\a.vb(4) : error BC30297: Constructor 'Public Sub New()' cannot call itself:

 

A method is capable of calling itself. This is a well-known concept called 'recursion'. A considerable number of computer problems are resolved by using recursion. However, a constructor cannot call itself. If it does so, the above error is hurled at us.

 

a.vb

class zzz

shared Sub Main()

End sub

End class

class aaa

sub new

end sub

sub new (paramarray a() as integer)

end sub

end class

class bbb

inherits aaa

end class

 

Error

c:\il\a.vb(11) : error BC32036: Class 'bbb' must declare a 'Sub New' because its base class 'aaa' has more than one accessible 'Sub New' that can be called with no arguments.

 

The class aaa has two constructors, one without any parameters, and the other with a paramarray, which also expects no parameters. The class bbb is derived from the class aaa. This gives out the above error, as there are two 'new' subs in the base class, and they both cannot be called with parameters. To dodge this error, simply add a sub new to the class bbb, as follows:

 

class bbb

inherits aaa

sub new

end sub

end class

 

Error

c:\il\a.vb(13) : error BC32038: First statement of this 'Sub New' must be a call to 'MyBase.New' or 'MyClass.New' because base class 'aaa' of 'bbb' has more than one accessible 'Sub New' that can be called with no arguments.

 

 

This gives rise to a different error, since the addition of a sub in class bbb does not resolve the earlier error of identifying the sub 'new' as being called from the base class.

 

sub new

mybase.new

end sub

 

However, by adding a call to the base class constructor, the error retires from sight.

 

a.vb

class zzz

shared Sub Main()

End sub

End class

class yyy

shared Sub Main()

End sub

End class

 

Error

vbc : error BC30738: 'Sub Main' is declared more than once in 'a': zzz.Main(), yyy.Main()

 

There cannot be more than one occurrence of the main sub in the program. The above error substantiates this fact. Neither of the two classes zzz or yyy can contain a main sub in them. It is because, the system would not know as to which sub main to call, while executing the program.

 

a.vb

Public Class zzz

Shared Sub Main()

End Sub

function vijay()

dim vijay as integer

End function

End Class

 

Error

c:\il\a.vb(5) : error BC30290: Local variable cannot have the same name as the function containing it.

 

A variable and a function cannot have the same name, since it would create an imbroglio when the variable has to be initialized. A similar error message occurs when a function and a parameter share the same name. This has already been explained earlier in the chapter.

 

There are certain error messages that never get generated. One of them is 'Identifier is too long, since the largest size of an identifier is 16384 characters'. We obviously do not have the time to create a variable as sizeable as this.

 

Another error that cannot be displayed is, "Maximum number of errors has been exceeded". This is because, the compiler will stop only when it encounters a total of 100 errors!

 

a.vb

class zzz

shared Sub Main()

+ 45

End sub

End class

 

Error

c:\il\a.vb(3) : error BC30035: Syntax error.

 

It is but natural to feel peeved at the petulant conduct of some people, and hence, there is a desperate urge to let the steam off. The same is true of the compiler. When it bumps into an error that does not fall into a predefined category, it reports it as a Syntax error.

 

a.vb

Public Class zzz

dim a as private integer

Shared Sub Main()

End Sub

End Class

 

Error

c:\il\a.vb(2) : error BC30180: Keyword does not name a type.

 

Every statement has its own set of rules. For instance, the Dim statement expects a type following the 'as' keyword. Since 'private' is not a type but a keyword, the above error message is generated.

 

a.vb

Public Class zzz

Shared Sub private Main()

End Sub

End Class

 

Error

c:\il\a.vb(2) : error BC30183: Keyword is not valid as an identifier.

 

In the same vein, the sub requires the name of the sub or an identifier, whereas, it has actually been furnished with the 'private' keyword. An identifier cannot be a keyword.

 

a.vb

Public Class zzz

a as integer

Shared Sub Main()

End Sub

End Class

 

Error

c:\il\a.vb(3) : error BC30188: Declaration expected.

 

The VB program comprises of both, declarative and the nondeclarative statements. A nondeclarative statement, such as an assignment or a loop, cannot occur outside a procedure. Thus, whenever there is some gibberish present outside a procedure, the above error is thrown. A similar error message is received when a variable is created without using the Dim statement.

 

 

 

a.vb

for i = 1 to 10

Public Class zzz

Shared Sub Main()

End Sub

End Class

 

Error

c:\il\a.vb(1) : error BC30689: Statement cannot appear outside of a method body.

 

Similarly, the 'for' statement cannot be used outside a method. The error, even with a slight difference, applies to all executable statements, and are permissible only within methods.

 

a.vb

Public Class zzz

Shared Sub Main()

dim a as new zzz

a.abc(10 : 20)

End Sub

sub abc ( i as integer)

end sub

End Class

 

Error

c:\il\a.vb(4) : error BC30198: ')' expected.

 

The parameters to a sub or a function, must be separated by commas. If we use colons instead, the above error is generated. Despite removing the colon, another error gets generated, which is as follows:

 

Error

c:\il\a.vb(4) : error BC32017: Comma, ')', or a valid expression continuation expected.

 

a.vb

Public Class zzz

Shared Sub Main()

dim b(2) as integer = {1 2}

End Sub

End Class

 

Error

c:\il\a.vb(3) : error BC30370: '}' expected.

 

Bypassing the comma for the array would lead to yet another error, which states that the } sign is expected. Also, the compiler casts another error, which states that an array cannot be created and initialized at the same time, with its dimension specified.

 

a.vb

class zzz

shared Sub Main()

End sub

sub abc( s as integer, s as integer)

end sub

End class

 

Error

c:\il\a.vb(4) : error BC30237: Parameter already declared with name 's'.

 

There are some errors that are present for the sake of completeness, like the one just discussed, where the two parameters have been assigned the same name.