Pergunta

Leitura O que é mais rápido?ByVal ou ByRef? me fez pensar se os comentários ali contidos se aplicavam a Strings em termos de desempenho.Como as strings são copiadas antes de serem passadas, não é muito mais eficiente (se o receptor não precisar de uma cópia do curso de string) passar strings ByRef?

Obrigado,
PCP.

Editar: Considere este código, que me fez pensar que havia algum tipo de cópia acontecendo:

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

Ele produz:

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

Solução

Cordas não são copiado antes de ser aprovado.Strings são tipos de referência, embora se comportem como tipos de valor.

Você deve usar o que fizer mais sentido no contexto de seus requisitos.(E se seus requisitos forem algo como "é necessário aproveitar até o último nanossegundo de desempenho às custas de todas as outras considerações", então você provavelmente deveria decifrar o criador de perfil em vez de perguntar no stackoverflow!)

É quase certo que isso é algo com que você não precisa se preocupar e duvido que haja uma diferença significativa de desempenho.A única situação em que posso ver alguma chance de diferença seria ao passar grande tipos de valor.

Outras dicas

Decidi verificar por mim mesmo, para obter uma resposta mais "científica".Eles são os mesmos.Se eu usar o código abaixo, ByVal será cerca de 2% mais lento que ByRef.Se, no entanto, eu trocá-los, de modo a cronometrar ByRef antes de ByVal, então ByRef será cerca de 2% mais lento.Então, o que realmente importa mais do que ByRef ou ByVal neste caso é a ordem em que eles são executados :)

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 entender o comportamento dos tipos de classe, incluindo strings, considere todos os parâmetros, variáveis, campos e elementos de array de tipo de classe, etc.como contendo "IDs de objetos".Se Foo é uma variável do tipo string, a declaração Foo = 12345.ToString(); criará um novo ID de objeto (hipoteticamente, Object ID#197) e criará um novo objeto do tipo string com esse id, contendo os cinco caracteres "12345".Ele irá então armazenar Object ID#197 na variável Foo.Se alguém chamar uma rotina com um parâmetro não-ref param, e passa Foo para isso, então param será uma variável local contendo Object ID #197.A declaração param += "6"; criaria um novo objeto (por exemploID do objeto #521), do tipo string, contendo os seis caracteres "123456" e armazenar Object ID #521 em param.Observe que Foo ainda mantém Object ID#197, e esse objeto ainda contém a sequência de cinco caracteres "12345".

Se param tinha sido passado ref, então a declaração param += "6" teria armazenado Object ID #521 em Foo.Ainda não teria causado nenhuma alteração observável no Objeto #197, exceto talvez para torná-lo elegível para coleta de lixo (se Foo tivesse sido a única referência ao Objeto #197, substituí-lo significaria que não existiria mais qualquer referência a esse objeto em qualquer lugar do universo).

Observe que geralmente é muito fácil raciocinar sobre tipos de classes imutáveis ​​como string, mesmo sem pensar em termos de Object IDs, já que a única maneira de alterar a sequência de caracteres representada por uma variável string é armazenar ali um Object ID diferente.Pensar em termos de IDs de objetos torna-se essencial, entretanto, ao lidar com tipos de classes mutáveis.Passando uma variável do tipo classe Car, e não por referência, seria equivalente a copiar um VIN de um pedaço de papel para outro e entregar o último pedaço de papel a alguns trabalhadores da loja e pedir-lhes que façam algo com ele.Se o primeiro artigo identificasse originalmente um carro vermelho com VIN#15934, então, quando os trabalhadores terminassem, o primeiro artigo poderia identificar um carro azul com VIN#15934, mas seria o mesmo carro.Nada que os trabalhadores pudessem fazer com o pedaço de papel que receberam, nem nada que pudessem fazer com o carro, mudaria a qual carro o primeiro papel se referia.Por outro lado, passar o parâmetro por referência seria mais como dar aos trabalhadores da loja um pedaço de papel com o VIN escrito e receber o papel de volta quando terminassem.Se os trabalhadores pudessem riscar o VIN e escrever outro, então, quando devolvessem o pedaço de papel, ele poderia referir-se ao mesmo carro ou a um carro diferente;se se referir a um carro diferente, o carro a que se referia originalmente pode ou não ter sido modificado, e o carro a que o artigo acaba se referindo pode ou não ter qualquer semelhança com o original.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top