Compartilhar via


Solucionando problemas de procedimentos (Visual Basic)

This page lists some common problems that can occur when working with procedures.

Returning an Array Type from a Function Procedure

If a Function procedure returns an array data type, you cannot use the Function name to store values in the elements of the array. If you attempt to do this, the compiler interprets it as a call to the Function. The following example generates compiler errors.

Function allOnes(ByVal n As Integer) As Integer()

For i As Integer = 1 To n - 1

' The following statement generates a COMPILER ERROR.

allOnes(i) = 1

Next i

' The following statement generates a COMPILER ERROR.

Return allOnes()

End Function

The statement allOnes(i) = 1 generates a compiler error because it appears to call allOnes with an argument of the wrong data type (a singleton Integer instead of an Integer array). The statement Return allOnes() generates a compiler error because it appears to call allOnes with no argument.

Abordagem correta: Para modificar os elementos de uma matriz que será retornado, defina uma matriz interna como uma variávelde local. The following example compiles without error.

Function allOnes(ByVal n As Integer) As Integer()
    Dim i As Integer, iArray(n) As Integer
    For i = 0 To n - 1
        iArray(i) = 1
    Next i
    Return iArray
End Function

Argument Not Being Modified by Procedure Call

If you intend to allow a procedure to change a programming element underlying an argument in the calling code, you must pass it by reference. But a procedure can access the elements of a reference type argument even if you pass it by value.

  • Underlying Variable. To allow the procedure to replace the value of the underlying variable element itself, the procedure must declare the parameter ByRef (Visual Basic). Also, the calling code must not enclose the argument in parentheses, because that would override the ByRef passing mechanism.

  • Reference Type Elements. If you declare a parameter ByVal (Visual Basic), the procedure cannot modify the underlying variable element itself. However, if the argument is a reference type, the procedure can modify the members of the object to which it points, even though it cannot replace the variable's value. For example, if the argument is an array variable, the procedure cannot assign a new array to it, but it can change one or more of its elements. The changed elements are reflected in the underlying array variable in the calling code.

The following example defines two procedures that take an array variable by value and operate on its elements. Procedure increase simply adds one to each element. Procedure replace assigns a new array to the parameter a() and then adds one to each element. However, the reassignment does not affect the underlying array variable in the calling code because a() is declared ByVal.

Public Sub increase(ByVal a() As Long)
    For j As Integer = 0 To UBound(a)
        a(j) = a(j) + 1
    Next j
End Sub
Public Sub replace(ByVal a() As Long)
    Dim k() As Long = {100, 200, 300}
    a = k
    For j As Integer = 0 To UBound(a)
        a(j) = a(j) + 1
    Next j
End Sub

The following example makes calls to increase and replace.

Dim n() As Long = {10, 20, 30, 40}
Call increase(n)
MsgBox("After increase(n): " & CStr(n(0)) & ", " & 
    CStr(n(1)) & ", " & CStr(n(2)) & ", " & CStr(n(3)))
Call replace(n)
MsgBox("After replace(n): " & CStr(n(0)) & ", " & 
    CStr(n(1)) & ", " & CStr(n(2)) & ", " & CStr(n(3)))

O primeiro MsgBox chamada exibe "após increase(n): 11, 21, 31, 41". Because n is a reference type, increase can change its members, even though it is passed ByVal.

A segunda MsgBox chamada exibe "depois de substituir(n): 11, 21, 31, 41". Because n is passed ByVal, replace cannot modify the variable n by assigning a new array to it. When replace creates the new array instance k and assigns it to the local variable a, it loses the reference to n passed in by the calling code. When it increments the members of a, only the local array k is affected.

Abordagem correta: Para modificar um elemento de variável subjacente propriamente dito, passe por referência. The following example shows the change in the declaration of replace that allows it to replace one array with another in the calling code.

Public Sub replace(ByRef a() As Long)

Unable to Define an Overload

If you want to define an overloaded version of a procedure, you must use the same name but a different signature. If the compiler cannot differentiate your declaration from an overload with the same signature, it generates an error.

The signature of a procedure is determined by the procedure name and the parameter list. Each overload must have the same name as all the other overloads but must differ from all of them in at least one of the other components of the signature. For more information, see Sobrecarga de procedimento (Visual Basic).

The following items, even though they pertain to the parameter list, are not components of a procedure's signature:

  • Procedure modifier keywords, such as Public, Shared, and Static

  • Parameter names

  • Parameter modifier keywords, such as ByRef and Optional

  • The data type of the return value (except for a conversion operator)

You cannot overload a procedure by varying only one or more of the preceding items.

Abordagem correta: Para definir um procedimento sobrecarga, você deverá variar a assinatura. Because you must use the same name, you must vary the number, order, or data types of the parameters. In a generic procedure, you can vary the number of type parameters. In a conversion operator (Função CType (Visual Basic)), you can vary the return type.

Overload Resolution with Optional and ParamArray Arguments

If you are overloading a procedure with one or more Opcional (Visual Basic) parameters or a ParamArray (Visual Basic) parameter, you must avoid duplicating any of the implicit overloads. For information, see Considerações sobre procedimentos de sobrecarga (Visual Basic).

Calling a Wrong Version of an Overloaded Procedure

If a procedure has several overloaded versions, you should be familiar with all their parameter lists and understand how Visual Basic resolves calls among the overloads. Otherwise you could call an overload other than the intended one.

When you have determined which overload you want to call, be careful to observe the following rules:

  • Supply the correct number of arguments, and in the correct order.

  • Ideally, your arguments should have the exact same data types as the corresponding parameters. In any case, the data type of each argument must widen to that of its corresponding parameter. This is true even with the Opção declaração estrito set to Off. If an overload requires any narrowing conversion from your argument list, that overload is not eligible to be called.

  • If you supply arguments that require widening, make their data types as close as possible to the corresponding parameter data types. If two or more overloads accept your argument data types, the compiler resolves your call to the overload that calls for the least amount of widening.

You can reduce the chance of data type mismatches by using the Função CType (Visual Basic) conversion keyword when preparing your arguments.

Overload Resolution Failure

When you call an overloaded procedure, the compiler attempts to eliminate all but one of the overloads. If it succeeds, it resolves the call to that overload. If it eliminates all the overloads, or if it cannot reduce the eligible overloads to a single candidate, it generates an error.

The following example illustrates the overload resolution process.

Overloads Sub z(ByVal x As Byte, ByVal y As Double)
End Sub
Overloads Sub z(ByVal x As Short, ByVal y As Single)
End Sub
Overloads Sub z(ByVal x As Integer, ByVal y As Single)
End Sub
Dim r, s As Short
Call z(r, s)
Dim p As Byte, q As Short
' The following statement causes an overload resolution error.
Call z(p, q)

In the first call, the compiler eliminates the first overload because the type of the first argument (Short) narrows to the type of the corresponding parameter (Byte). It then eliminates the third overload because each argument type in the second overload (Short and Single) widens to the corresponding type in the third overload (Integer and Single). The second overload requires less widening, so the compiler uses it for the call.

In the second call, the compiler cannot eliminate any of the overloads on the basis of narrowing. It eliminates the third overload for the same reason as in the first call, because it can call the second overload with less widening of the argument types. However, the compiler cannot resolve between the first and second overloads. Each has one defined parameter type that widens to the corresponding type in the other (Byte to Short, but Single to Double). The compiler therefore generates an overload resolution error.

Abordagem correta: Para poder chamar um procedimento de sobrecarregado sem ambigüidade, use Função CType (Visual Basic) para coincidir com os tipos de dados do argumento para os tipos de parâmetro . The following example shows a call to z that forces resolution to the second overload.

Call z(CType(p, Short), CType(q, Single))

Overload Resolution with Optional and ParamArray Arguments

If two overloads of a procedure have identical signatures except that the last parameter is declared Opcional (Visual Basic) in one and ParamArray (Visual Basic) in the other, the compiler resolves a call to that procedure according to the closest match. For more information, see Resolução de sobrecarga (Visual Basic).

Consulte também

Conceitos

Procedimentos no Visual Basic

Subprocedimentos (Visual Basic)

Procedimentos de função (Visual Basic)

Procedimentos de propriedade (Visual Basic)

Procedimentos de operador (Visual Basic)

Parâmetros e argumentos de procedimento (Visual Basic)

Sobrecarga de procedimento (Visual Basic)

Considerações sobre procedimentos de sobrecarga (Visual Basic)

Resolução de sobrecarga (Visual Basic)