Buscador

Array de parámetros

Cuando en la lista de parámetros de un procedimiento utilizamos la palabra clave ParamArray junto al nombre del último parámetro de la lista, dicho parámetro será considerado un array, por lo que al hacer la llamada al procedimiento podremos pasarle un número variable de valores, que manejaremos a través del array. El Código fuente 109 muestra un ejemplo.

Sub Main()
Dim Valor As Integer
Dim Ciudad As String
Dim Nombre As String
Valor = 7954
Ciudad = "Valencia"
Nombre = "Jorge"
' en la llamada al procedimiento Prueba()
' todos los valores que pasemos a continuación
' del primer parámetro, serán depositados
' en el array de parámetros
Prueba(Valor, Ciudad, "mesa", Nombre)
Console.ReadLine()
End Sub

' el parámetro MasDatos del procedimiento es un array
' de parámetros variables
Sub Prueba(ByVal Importe As Integer, ByVal ParamArray MasDatos() As String)
Dim Contador As Integer
' mostrar el primer parámetro
Console.WriteLine("Parámetro Importe: {0}", Importe)
Console.WriteLine()
' el resto de parámetros del procedimiento
' están en el array, los obtenemos recorriendolo
' con(una) estructura For...Next
Console.WriteLine("Contenido del array de parámetros MasDatos():")
For Contador = 0 To UBound(MasDatos)
Console.WriteLine("Elemento: {0} - Valor: {1}", _
Contador, MasDatos(Contador))
Next
End Sub
Código fuente 109

Parámetros opcionales

Un parámetro opcional es aquel que no es necesario especificar al hacer la llamada a un procedimiento. Para indicar en la declaración de un procedimiento que un parámetro es opcional, debemos utilizar la palabra clave Optional seguida de la especificación del parámetro, y finalizar con la asignación de un valor por defecto para el parámetro. Teniendo en cuenta además, que a partir del primer parámetro opcional en la lista de un procedimiento, todos los parámetros sucesivos también deben ser opcionales. En el Código fuente 108 creamos una función en la que declaramos un parámetro opcional. Después hacemos dos llamadas a dicho procedimiento, pasando y omitiendo el parámetro opcional respectivamente en cada llamada.

Sub Main()
Dim Localidad As String
Dim Importe As Integer
Dim Resultado As Integer
' ---------------------
Localidad = "Sevilla"
Importe = 15044
' paso de todos los parámetros al procedimiento
Resultado = Calcular(Localidad, Importe)
Console.WriteLine("Primera llamada, valor devuelto: {0}", Resultado)
' ---------------------
Localidad = "Madrid"
' paso sólo del primer parámetro al procedimiento,
' esto hará que se utilice el valor por defecto
' del parámetro opcional
Resultado = Calcular(Localidad)
Console.WriteLine("Segunda llamada, valor devuelto: {0}", Resultado)
Console.ReadLine()
End Sub
Function Calcular(ByVal Ciudad As String, Optional ByVal Cantidad As Integer =
5500) As Integer
Console.WriteLine("Valores de los parámetros")
Console.WriteLine("Ciudad: {0} - Cantidad: {1}", Ciudad, Cantidad)
Return Cantidad + 100
End Function
Código fuente 108

Paso de parámetros por posición y por nombre - II

Podemos mezclar ambos tipos de paso en la llamada a un procedimiento, teniendo en cuenta que los parámetros en los que no utilicemos paso por nombre, deberemos situarlos en su posición correcta. El Código fuente 107 muestra un ejemplo con una variación sobre el ejemplo anterior.


Prueba(Localidad, Fecha:=DiaHoy, Cantidad:=Importe)
Código fuente 107

Paso de parámetros por posición y por nombre - I

Cuando al llamar a un procedimiento con parámetros, pasamos estos en el mismo orden en el que están especificados en la declaración del procedimiento, se dice que se ha realizado un paso de parámetros por posición. Existe además, otro modo de paso de parámetros en el cuál no estamos obligados a situarlos en el mismo orden que indica la declaración, es el llamado paso de parámetros por nombre. En este tipo de paso, debemos situar en la llamada al procedimiento el nombre del parámetro, seguido de los signos de dos puntos e igual ( := ) y finalmente el valor a pasar. El Código fuente 106 muestra unos ejemplos con ambos tipos de paso de parámetros.

Sub Main()
Dim Localidad As String
Dim Importe As Integer
Dim DiaHoy As Date
' ---------------------
Localidad = "Sevilla"
Importe = 15044
DiaHoy = #2/10/2002#
' paso de parámetros por posición
Prueba(Localidad, Importe, DiaHoy)
' ---------------------
Localidad = "Madrid"
Importe = 250
DiaHoy = #5/8/2002#
' paso de parámetros por nombre
Prueba(Cantidad:=Importe, Fecha:=DiaHoy, Ciudad:=Localidad)
Console.ReadLine()
End Sub
Sub Prueba(ByVal Ciudad As String, ByVal Cantidad As Integer, ByVal Fecha As Date)
Console.WriteLine("Valores de los parámetros")
Console.WriteLine("Ciudad: {0} - Cantidad: {1} - Fecha: {2}", Ciudad, Cantidad,
Fecha)
End Sub
Código fuente 106

Paso por referencia (ByRef) - II

Lo que ocurre en el fuente anterior a nivel de gestión interna en memoria de los parámetros es lo siguiente: cuando se realiza la llamada al procedimiento y se pasa el parámetro, el entorno detecta que se trata de un parámetro pasado por referencia, y tanto la variable del código llamador como la del procedimiento llamado utilizan la misma dirección de memoria o referencia hacia los datos, por lo que los cambios realizados en un procedimiento afectarán también al otro. La Figura 68 muestra una representación gráfica de este proceso.


Figura 68. Esquema de gestión interna de variables en el paso por referencia.

Paso por referencia (ByRef) - I

Cuando pasamos un parámetro por referencia a un procedimiento, si modificamos dentro del procedimiento la variable que contiene el parámetro, dichos cambios en este caso sí afectarán al código llamador. Debemos situar en este caso en el procedimiento, la palabra clave ByRef antes del nombre del parámetro. Cambiemos el código del anterior ejemplo, haciendo que en este caso, el parámetro sea pasado por referencia y observemos los resultados. Ver el Código fuente 105.

Sub Main()
Dim Nombre As String
Nombre = "Juan"
Console.WriteLine("Valor de la variable antes de llamar a Prueba(): {0}",
Nombre)
' llamamos a un procedimiento
' y le pasamos una variable por referencia
Prueba(Nombre)
' el cambio realizado al parámetro en el procedimiento
' ha afectado a la variable Nombre, que aquí contiene
' el mismo valor que se asignó en el procedimiento
Console.WriteLine("Valor de la variable al volver a Main(): {0}", Nombre)
Console.ReadLine()
End Sub

Sub Prueba(ByRef ValorMostrar As String)
' modificamos el valor del parámetro
ValorMostrar = "Elena"
Console.WriteLine("Valor del parámetro dentro de Prueba(): {0}", ValorMostrar)
End Sub
Código fuente 105

Paso por valor (ByVal) - II

Lo que ocurre en el fuente anterior a nivel de gestión interna en memoria de los parámetros es lo siguiente: cuando se realiza la llamada al procedimiento y se pasa el parámetro, el entorno detecta que se trata de un parámetro pasado por valor, por lo que crea una nueva variable en memoria que será la que manipulemos dentro del procedimiento. La Figura 67 muestra una representación gráfica de este proceso.
Figura 67. Esquema de gestión interna de variables en el paso por valor.
En el entorno de .NET Framework, por defecto, todos los parámetros son pasados por valor. Esto lo puede comprobar el lector de un modo muy simple: si al declarar un parámetro no especifica el tipo de paso, el IDE automáticamente situará junto a ese parámetro la palabra clave ByVal. Se recomienda siempre que sea posible el paso de parámetros por valor, ya que ayuda a generar un código más optimizado y contribuye a mejorar la encapsulación.

Paso por valor (ByVal) - I

Cuando pasamos un parámetro por valor a un procedimiento, la variable que contiene el parámetro puede ser modificada dentro del procedimiento, sin que estos cambios afecten al valor original en el código llamador. Debemos situar en este caso en el procedimiento, la palabra clave ByVal antes del nombre del parámetro. Ver Código fuente 104.

Sub Main()
Dim Nombre As String
Nombre = "Juan"
' llamamos a un procedimiento
' y le pasamos una variable por valor
Prueba(Nombre)
' la variable que hemos pasado al procedimiento,
' al volver aquí no ha sido cambiada, debido a que
' ha sido pasada por valor, sigue conteniendo
' la cadena "Juan"
Console.WriteLine("Valor de la variable dentro de Main(): {0}", Nombre)
Console.ReadLine()
End Sub
Sub Prueba(ByVal ValorMostrar As String)
' modificamos el valor del parámetro,
' este cambio no afecta a la variable Nombre
ValorMostrar = "Elena"
Console.WriteLine("Valor del parámetro dentro de Prueba(): {0}", ValorMostrar)
End Sub
Código fuente 104

Modos de paso de parámetros a un procedimiento

Existen dos modos en el lenguaje de pasar parámetros a un procedimiento: por valor y por referencia. Este aspecto del lenguaje está relacionado con la forma en que el contenido de los parámetros es gestionado internamente en memoria. Ello nos permitirá según el tipo de paso empleado, poder alterar el valor del parámetro en el código que realizó la llamada.

Tipo de dato de un parámetro

Al igual que hacemos cuando declaramos una variable, al declarar un parámetro debemos especificar el tipo de dato que el parámetro va a contener. Esto será o no obligatorio, en función del modificador establecido en la instrucción Option Strict. En el Código fuente 103 hemos añadido un parámetro de tipo String al procedimiento Prueba( ). Cuando llamemos desde otro procedimiento a Prueba( ), al pasar desde el código llamador una cadena de caracteres, bien de forma literal o en una variable; el contenido de dicha cadena se traspasará a la variable situada en la lista de parámetros del procedimiento, que posteriormente visualizaremos en la consola.

Sub Main()
Dim Nombre As String
Nombre = "Juan"
Prueba(Nombre)
Prueba("Esto es una prueba")

Console.ReadLine()
End Sub
Sub Prueba(ByVal ValorMostrar As String)
Console.WriteLine("El valor del parámetro pasado es {0}", ValorMostrar)
End Sub
Código fuente 103

Protocolo de llamada o firma de un procedimiento

A la lista de parámetros de un procedimiento se le denomina protocolo de llamada o firma (signature) del procedimiento. Se trata de un concepto que cubriremos posteriormente en el apartado dedicado a la sobrecarga de procedimientos.

Paso de parámetros a procedimientos

Un parámetro consiste en un valor que es pasado a un procedimiento. Dicho valor puede ser una variable, constante o expresión. Los procedimientos pueden recibir parámetros en forma de lista de variables separada por comas, siguiendo la sintaxis que vemos en el Código fuente 102.

[Optional] [ByVal | ByRef] [ParamArray] NombreParametro As TipoDato
Código fuente 102

Las reglas y cuestiones sobre paso de parámetros descritas en los siguientes apartados son válidas tanto para procedimientos como para funciones, excepto en aquellos lugares donde se indique lo contrario.

Llamada a un procedimiento Function

Para realizar una llamada o ejecutar un procedimiento Function debemos escribir su nombre en un punto del programa al igual que hacemos con los procedimientos Sub; en este aspecto ambos tipos de procedimiento son iguales. Por otro lado, los puntos que marcan las diferencias entre un Function y un Sub son los siguientes: 
• Un procedimiento Function devuelve un valor, de modo que si queremos obtenerlo, debemos asignar la llamada a la función a una variable. Los procedimientos Sub no pueden devolver valores. 
Debido precisamente a la capacidad de un procedimiento Function de devolver un valor, podemos situar la llamada a una función dentro de una expresión, y operar con el valor de retorno dentro de la expresión, lo cual dota a nuestro código de una mayor flexibilidad. Los procedimientos Sub no pueden formar parte de expresiones. En el Código fuente 101 vemos varios ejemplos de llamadas a la función Calcular( ), según el modo en que vamos a manipular su valor de retorno.


Module Module1
Sub Main()
Dim Resultado As Integer
Dim NuevoValor As Integer
' llamada a una función sin recoger el valor de retorno,
' por este motivo, dicho valor se pierde
Calcular()
' llamada a una función obteniendo el valor
' de retorno y asignando el valor a una variable
Resultado = Calcular()
Console.WriteLine("La variable Resultado contiene: {0}", Resultado)
' llamada a una función como parte de una expresión
NuevoValor = 1500 + Calcular() * 2
Console.WriteLine("La variable NuevoValor contiene: {0}", NuevoValor)
Console.ReadLine()
End Sub
Function Calcular() As Integer
Dim MiValor As Integer
Console.WriteLine("Introducir un número de 1 a 100")
MiValor = Console.ReadLine()
Return MiValor

' también podemos utilizar esta
' sintaxis para devolver el valor
' de retorno de la función:
'Calcular = MiValor
End Function
End Module
Código fuente 101