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.