Duda: Diferencias entre ByVal y ByRef en vb.net

Iniciado por OscarCadenas_91, 25 Junio 2016, 07:55 AM

0 Miembros y 1 Visitante están viendo este tema.

OscarCadenas_91

hola estoy regresando despues de algun tiempo y me surge la siguiente duda cuando o cómo  se deben usar al pasar parametros  o argumentos a una subrutina o a una funcion.

Que diferencias hay en usar:
Código (vbnet) [Seleccionar]

'Caso 1
Private Sub Incrementar(valorA As Integer)
    valorA  = valorA +1
End Sub
'Caso 2
Private Sub Incrementar(ByRef valorA As Integer)
    valorA  = valorA +1
End Sub
'Caso 3
Private Sub Incrementar(ByVal valorA As Integer)
    valorA  = valorA +1
End Sub


Por lo que lei... tengo entendido que  pasar  argumento tipo ByVal crea una copia de la variable original, por lo que cualquier modificación hecha a dicha variable no afectará a la variable original y cuando se usa el  argumento tipo ByRef hace una referencia de la variable original, por lo que cualquier modificación hecha a dicha variable si afectará a la variable original.
Y ademas tengo entendido que tanto el caso 1 y el caso 2 son lo mismo ya que en el caso 1 viene implicitamente el ByRef

(Corríjanme si me equivoco)

Mis dudas que me surgen son:

Esto pasa de igual forma en una Funcion que retorne algun valor(Es necesario indicarle el tipo de Argumento)
como ejemplo:
Código (vbnet) [Seleccionar]

Private Function Incrementar(valorA As Integer) as Integer
valorA  = valorA +1
Return valorA 
End Function
Private Function Incrementar(ByVal valorA As Integer) as Integer

valorA = valorA +1
Return valorA 
End Function
Private Function Incrementar(ByRef valorA As Integer) as Integer
valorA  = valorA +1
Return valorA 
End Function



Cual es la forma correcta en la que deben escribirse en las Functions?


Eleкtro

#1
Cita de: OscarCadenas_91 en 25 Junio 2016, 07:55 AMtengo entendido que tanto el caso 1 y el caso 2 son lo mismo ya que en el caso 1 viene implicitamente el ByRef

(Corríjanme si me equivoco)

Te corrijo: eso no es así, sino todo lo contrario.

ByVal es un simple acrónimo para referirse a un argumento que se pasa por valor (by value), y ByRef para referirse a uno que se pasa por referencia (by reference). Aunque en lugar de acrónimos los llamaremos de forma global Keywords, y la idea de como funcionan esos keywords ya pareces tenerla clara; cuando pasamos un argumento por valor se crea una copia del objeto en la que cualquier modificación realizada en la copia no se reflejará en el objeto original.

En VB.NET, por defecto los argumentos se pasan por valor (ByVal), no por referencia (ByRef); por ende, el keyword ByVal está implícito en la firma del método del "Caso 1", siendo exactamente idéntica a la firma del método del "Caso 3".




Cita de: OscarCadenas_91 en 25 Junio 2016, 07:55 AMCual es la forma correcta en la que deben escribirse en las Functions?

El comportamiento de ByVal o ByRef se usa y afecta de la misma manera a los argumentos de un método, que los de una función.

¿Cual es la forma correcta de pasar un argumento a una función?, eso depende del propósito real que quieras llevar a cabo con la función en cuestión. En un principio el propósito de una función es ejecutar un algoritmo que resuelva un problema para al final devolver un resultado (o valor de retorno), así que generálmente no debería existir por tu parte la necesidad de pasar argumentos por referencia ...en una función.

Dicho esto, lo que si estás escribiendo de forma incorrecta son las firmas de todos esos métodos y funciones, me refiero a que solamente podrás compilar uno de esos 3 métodos/funciones, puesto que la firma de "Caso 1" es idéntica a la de "Caso 3" como ya expliqué, y la firma de ambos "Caso 1" y "Caso 3" toman un argumento del mismo data-type que la de "Caso 2" (Integer), pero éste necesariamente ha de diferenciarse en algo más que en el mecanismo de paso (ByVal/ByRef).

Aparte de eso, esta suma:
Código (vbnet) [Seleccionar]
valorA = valorA + 1

La puedes simplificar a:
Código (vbnet) [Seleccionar]
valorA += 1

Y por último decirte que ya existe una función que toma un valor entero por referencia, lo incrementa en 1 y devuelve el resultado: System.Threading.Interlocked.Increment() , y otra para disminuir un valor entero: System.Threading.Interlocked.Decrement() . Esto son consideradas funciones especiales por así decirlo, ya que su utilización es más que nada para simplificar código al evitar órdenes individuales para sumar variables que se usan como contador, de hecho resulta más rápido que realizar una incrementación individual y son funciones thread-safe.
Probablemente no encontrarás ninguna otra función definida en la librería de clases de .NET Framework que tome un argumento por referencia, puesto que como ya expliqué, generálmente no debería existir la necesidad de hacerlo en una función; un caso en el que sería productivo pasar un argumento por referencia sería que tu función usase el argumento para almacenar el resultado, y utilizase el valor de retorno para poder depurar el estado de la operación efectuada (éxito/error) como se puede ver en las funciones de la API de Windows.

Saludos








OscarCadenas_91

gracias Elektro. ahora si me quedo todo claro
muchas gracias por tomarte tiempo en responder.

saludos.