Solucionar problemas de procedimientos (Visual Basic)

Esta página muestra algunos problemas comunes que pueden aparecer al trabajar con procedimientos.

Devolver una matriz de tipo desde un procedimiento de función

Si un procedimiento Function devuelve un tipo de datos de matriz, no puede utilizar el nombre Function para almacenar valores en los elementos de la matriz. Si se intenta hacerlo, el compilador lo interpreta como una llamada a la función Function. En el siguiente ejemplo se generan errores de compilador.

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

La instrucción allOnes(i) = 1 genera un error de compilador porque llama a allOnes con un argumento de tipo de datos erróneo (un objeto singleton Integer en lugar de una matriz Integer). La instrucción Return allOnes() genera un error de compilador porque llama a allOnes sin argumento.

Enfoque correcto: para poder modificar los elementos de una matriz que se debe devolver, defina una matriz interna como variable local. En el siguiente ejemplo se compila sin errores.

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

Argumento no modificado por una llamada a procedimiento

Si intenta permitir a un procedimiento que cambie un elemento de programación subyacente a un argumento en el código de llamada, debe pasarlo por referencia. No obstante, un procedimiento puede tener acceso a los elementos de un argumento de tipo de referencia aun cuando se pase por valor.

  • Variable subyacente Para permitir al procedimiento reemplazar el valor del propio elemento variable subyacente, el procedimiento debe declarar el parámetro ByRef (Visual Basic). El código de llamada no debe incluir tampoco el argumento entre paréntesis, porque eso reemplazaría el mecanismo para pasar argumentos ByRef.

  • Elementos de tipo de referencia. Si declara un parámetro ByVal (Visual Basic), el procedimiento no puede modificar el propio elemento variable subyacente. No obstante, si el argumento es un tipo de referencia, el procedimiento puede modificar los miembros del objeto al que señala, aunque no puede reemplazar el valor de la variable. Por ejemplo, si el argumento es una variable de matriz, el procedimiento no puede asignarle otra matriz, pero sí puede cambiar uno o varios de sus elementos. La modificación de los elementos queda reflejada en la variable de matriz subyacente al código de llamada.

En el siguiente ejemplo se definen dos procedimientos que aceptan una variable de matriz por valor y operan con sus elementos. El procedimiento increase suma sencillamente una unidad a cada elemento. El procedimiento replace asigna una nueva matriz al parámetro a() y, a continuación, agrega una unidad a cada elemento. La reasignación, sin embargo, no afecta a la variable de matriz subyacente al código de llamada porque a() se declara 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

En el ejemplo siguiente se realizan llamadas a increase y 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)))

La primera llamada MsgBox muestra "After increase(n): 11, 21, 31, 41". Como n es un tipo de referencia, increase puede cambiar sus miembros, aunque se pase ByVal.

La segunda llamada MsgBox muestra "After replace(n): 11, 21, 31, 41". Como n se pasa ByVal, replace no puede modificar la variable n asignándole una nueva matriz. Cuando replace crea una nueva instancia de matriz k y la asigna a la variable local a, pierde la referencia a n que le ha pasado el código de llamada. Cuando incrementa los miembros de a, esto sólo afecta a la matriz local k.

Enfoque correcto: para poder modificar un elemento variable subyacente en sí, páselo por referencia. En el ejemplo siguiente se muestra el cambio en la declaración de replace que permite reemplazar una matriz por otra en el código de llamada.

Public Sub replace(ByRef a() As Long)

No se puede definir una sobrecarga

Si desea definir una versión sobrecargada de un procedimiento, debe utilizar el mismo nombre pero con una firma diferente. Si el compilador no puede diferenciar su declaración de una sobrecarga con la misma firma, genera un error.

El nombre de procedimiento y la lista de parámetros determinan la firma de un procedimiento. Cada sobrecarga debe tener el mismo nombre que todas las demás sobrecargas pero debe diferenciarse de todas ellas en al menos uno de los componentes de la firma. Para obtener más información, vea Sobrecarga de procedimiento (Visual Basic).

Los elementos siguientes, aunque pertenecen a la lista de parámetros, no son componentes de la firma de un procedimiento:

  • Palabras clave que modifican a los procedimientos, como Public, Shared y Static

  • Nombres de parámetros

  • Palabras clave de modificadores de parámetros, como ByRef y Optional

  • Tipo de datos del valor devuelto (excepto para un operador de conversión)

No es posible sobrecargar un procedimiento cambiando únicamente uno o varios de los elementos anteriores:

Enfoque correcto: para poder definir una sobrecarga de procedimiento, debe variar la firma. Como debe utilizar el mismo nombre, debe variar el número, orden o tipos de datos de los parámetros. En un procedimiento genérico, puede variar el número de parámetros de tipo. En un operador de conversión (CType (Función) (Visual Basic)), puede variar el tipo de valor devuelto.

Resolución de sobrecarga con argumentos Optional y ParamArray

Si sobrecarga un procedimiento con uno o varios parámetros Optional (Visual Basic) o un parámetro ParamArray (Visual Basic), debe evitar duplicar las sobrecargas implícitas. Para obtener más información, vea Consideraciones sobre la sobrecarga de procedimientos (Visual Basic).

Llamar a una versión incorrecta de un procedimiento sobrecargado

Si un procedimiento tiene varias versiones sobrecargadas, debe estar familiarizado con todas las listas de parámetros y comprender cómo resuelve Visual Basic las llamadas entre las sobrecargas. De lo contrario podría llamar a una sobrecarga distinta de la que desea.

Cuando haya determinado a qué sobrecarga desea llamar, observe cuidadosamente las reglas siguientes:

  • Proporcione el número correcto de argumentos y en el orden correcto.

  • Lo ideal es que sus argumentos tengan los mismos tipos de datos exactos que los parámetros correspondientes. En cualquier caso, el tipo de datos de cada argumento debe ampliarse al de su parámetro correspondiente. Esto es verdad incluso con Option Strict (Instrucción) establecido en Off. Si una sobrecarga requiere cualquier conversión de restricción de la lista de argumentos, no se debe llamar a esta sobrecarga.

  • Si proporciona argumentos que requieren ampliación, haga que sus tipos de datos se acerquen lo más posible a los tipos de datos de los parámetros correspondientes. Si dos o más sobrecargas aceptan los tipos de datos de argumentos, el compilador resuelve la llamada con la sobrecarga que solicita la menor cantidad de ampliación.

Puede reducir las posibilidades de que aparezcan discordancias del tipo de datos mediante la palabra clave de conversión CType (Función) (Visual Basic) cuando prepara los argumentos.

Error de resolución de sobrecarga

Cuando llama a un procedimiento sobrecargado, el compilador intenta eliminar todas menos una de las sobrecargas. Si lo consigue, resuelve la llamada con esa sobrecarga. Si elimina todas las sobrecargas o si no puede reducir las sobrecargas seleccionables a un candidato único, genera un error.

Este proceso de resolución de las sobrecargas se ilustra en el siguiente ejemplo:

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)

En la primera llamada, el compilador elimina la primera sobrecarga porque el tipo del primer argumento (Short) se restringe al tipo del parámetro correspondiente (Byte). A continuación, elimina la tercera sobrecarga porque cada tipo de argumento de la segunda sobrecarga (Short y Single) se amplía al tipo correspondiente a la tercera sobrecarga (Integer y Single). La segunda sobrecarga requiere una ampliación menor, y por eso el compilador la utiliza en la llamada.

En la segunda llamada, el compilador no puede eliminar ninguna sobrecarga teniendo en cuenta la restricción. Elimina la tercera sobrecarga por el mismo motivo por el que la eliminó en la primera llamada, porque puede llamar a la segunda sobrecarga con una ampliación menor de los tipos de argumentos. Sin embargo, el compilador no puede decidirse entre la primera y la segunda sobrecarga. Cada una de ellas tiene un tipo de parámetro definido que se amplía al tipo correspondiente de la otra (Byte a Short, pero Single a Double). Por lo tanto, el compilador genera un error de resolución de sobrecarga.

Enfoque correcto: para poder llamar a un procedimiento sobrecargado sin ambigüedad, utilice CType (Función) (Visual Basic) para que los tipos de datos de argumentos coincidan con los tipos de parámetros. En el ejemplo siguiente se muestra una llamada a z que fuerza a la resolución a la segunda sobrecarga.

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

Resolución de sobrecarga con argumentos Optional y ParamArray

Si dos sobrecargas de un procedimiento tienen las mismas firmas excepto que el último parámetro está declarado Optional (Visual Basic) en una y ParamArray (Visual Basic) en la otra, el compilador resuelve una llamada a ese procedimiento según la coincidencia más próxima. Para obtener más información, vea Resolución de sobrecarga (Visual Basic).

Vea también

Conceptos

Procedimientos en Visual Basic

Subprocedimientos (Visual Basic)

Procedimientos de función (Visual Basic)

Procedimientos de propiedad (Visual Basic)

Procedimientos de operador (Visual Basic)

Argumentos y parámetros de procedimiento (Visual Basic)

Sobrecarga de procedimiento (Visual Basic)

Consideraciones sobre la sobrecarga de procedimientos (Visual Basic)

Resolución de sobrecarga (Visual Basic)