Pregunta

Lectura ¿Cual es mas rápido?¿PorVal o porRef? Me hizo preguntarme si los comentarios allí se aplicaban a Strings en términos de rendimiento.Dado que las cadenas se copian antes de pasarse, ¿no es mucho más eficiente (si el destinatario no necesita una copia del curso de cadenas) pasar cadenas? ByRef?

Gracias,
PPC.

Editar: Considere este código, que me hizo pensar que se estaba realizando algún tipo de copia:

Sub Main()
    Dim ByValStr As String = "Hello World (ByVal)!"
    Dim ByRefStr As String = "Hello World (ByRef)!"

    fooval(ByValStr)
    fooref(ByRefStr)

    Console.WriteLine("ByVal: " & ByValStr)
    Console.WriteLine("ByRef: " & ByRefStr)

    Console.ReadLine()
End Sub


Sub fooval(ByVal Str As String)
    Str = "foobar"
End Sub

Sub fooref(ByRef Str As String)
    Str = "foobar"
End Sub

Produce:

ByVal: Hello World (ByVal)!
ByRef: foobar
¿Fue útil?

Solución

Instrumentos de cuerda no son copiado antes de ser aprobado.Las cadenas son tipos de referencia, aunque se comportan en cierto modo como tipos de valores.

Debe utilizar lo que tenga más sentido en el contexto de sus necesidades.(Y si sus requisitos son algo así como "debe exprimir hasta el último nanosegundo de rendimiento a expensas de todas las demás consideraciones", entonces probablemente debería descifrar el generador de perfiles en lugar de preguntar en stackoverflow.)

Es casi seguro que esto es algo de lo que no necesita preocuparse y dudo que alguna vez haya una diferencia significativa en el rendimiento.La única situación en la que puedo ver alguna posibilidad de diferencia sería al pasar grande tipos de valor.

Otros consejos

Decidí comprobarlo por mí mismo para obtener una respuesta más "científica".Ellos son iguales.Si uso el código siguiente, ByVal es aproximadamente un 2% más lento que ByRef.Sin embargo, si los cambio, de modo que programe ByRef antes que ByVal, entonces ByRef es aproximadamente un 2% más lento.Entonces, lo que realmente importa más que ByRef o ByVal en este caso es el orden en que se ejecutan :)

Function CreateString()

    Dim i As Integer
    Dim str As String = ""

    For i = 1 To 10000
        str = str & "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
    Next i

    Return str
End Function

Sub fooval(ByVal Str As String)
    Str = Str & "foobar"
End Sub

Sub fooref(ByRef Str As String)
    Str = Str & "foobar"
End Sub

Private Sub Button1_Click(sender As System.Object, e As System.EventArgs) Handles Button1.Click
    Dim str As String = CreateString()
    Dim stopWatch As New Stopwatch
    Dim i As Integer

    stopWatch.Start()
    For i = 1 To 1000
        fooval(str)
    Next i
    stopWatch.Stop()
    Dim valtime As Long = stopWatch.ElapsedMilliseconds

    stopWatch.Restart()
    For i = 1 To 1000
        fooref(str)
    Next i
    stopWatch.Stop()
    Dim reftime As Long = stopWatch.ElapsedMilliseconds

    MsgBox("Val took " & valtime & " milliseconds and Ref took " & reftime & " milliseconds")
End Sub

Para comprender el comportamiento de los tipos de clases, incluidas las cadenas, considere todos los parámetros, variables, campos y elementos de matriz de los tipos de clases, etc.como contener "identificadores de objetos".Si Foo es una variable de tipo string, la declaración Foo = 12345.ToString(); creará una nueva identificación de objeto (hipotéticamente, ID de objeto n.° 197) y creará un nuevo objeto de tipo string con esa identificación, sosteniendo los cinco caracteres "12345".Luego almacenará Object ID#197 en la variable Foo.Si uno llama a una rutina con un parámetro sin referencia param, y pasa Foo a ello, entonces param será una variable local que tenga Object ID #197.La declaración param += "6"; crearía un nuevo objeto (p. ej.ID de objeto #521), de tipo cadena, que contiene los seis caracteres "123456" y almacenar Object ID #521 en param.Tenga en cuenta que Foo aún mantiene Object ID#197, y ese objeto todavía contiene la cadena de cinco caracteres "12345".

Si param había sido pasado por ref, entonces la declaración param += "6" habría almacenado Object ID #521 en Foo.Aún así no habría causado ningún cambio observable en el Objeto #197, excepto quizás para hacerlo elegible para la recolección de basura (si Foo había sido la única referencia al Objeto #197, sobrescribirlo significaría que ya no existiría ninguna referencia a ese objeto en ningún lugar del universo).

Tenga en cuenta que, en general, es bastante fácil razonar sobre tipos de clases inmutables como string, incluso sin pensar en términos de ID de objeto, ya que la única forma de cambiar la secuencia de caracteres representados por una variable de cadena es almacenar allí un ID de objeto diferente.Sin embargo, pensar en términos de ID de objeto se vuelve esencial cuando se trata de tipos de clases mutables.Pasar una variable de tipo clase Car, no por referencia, equivaldría a copiar un VIN de una hoja de papel a otra, y entregar esta última hoja de papel a algunos trabajadores de la tienda y pedirles que hagan algo con ella.Si el primer documento identificaba originalmente un automóvil rojo con VIN#15934, cuando los trabajadores terminaran, el primer documento podría identificar un automóvil azul con VIN#15934, pero sería el mismo automóvil.Nada de lo que los trabajadores pudieran hacer con el trozo de papel que les entregaron, ni nada de lo que pudieran hacer con el automóvil, cambiaría a qué automóvil se refería el primer documento.Por otro lado, pasar el parámetro por referencia sería más como que los trabajadores de la tienda recibieran una hoja de papel con el VIN escrito y se les devolviera el papel cuando terminaran.Si los trabajadores pudieran tachar el VIN y escribir otro, cuando devolvieran el papel podría referirse al mismo automóvil o a uno diferente;si se refiere a un automóvil diferente, el automóvil al que se refería originalmente puede haber sido modificado o no, y el automóvil al que termina haciendo referencia el documento puede o no tener ningún parecido con el original.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top