Вопрос

Чтение Что быстрее?ByVal или ByRef? заставило меня задуматься, относятся ли комментарии там к Strings с точки зрения производительности.Поскольку строки копируются перед передачей, не гораздо ли эффективнее (если вызываемому абоненту не нужна копия курса строк) передавать строки? ByRef?

Спасибо,
КФП.

Редактировать: Рассмотрим этот код, который заставил меня подумать, что происходит какое-то копирование:

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

Он выводит:

ByVal: Hello World (ByVal)!
ByRef: foobar
Это было полезно?

Решение

Струны не скопировано перед передачей.Строки являются ссылочными типами, хотя они ведут себя как типы значений.

Вам следует использовать то, что имеет наибольший смысл в контексте ваших требований.(И если ваши требования сводятся к чему-то вроде «необходимо выжать каждую последнюю наносекунду производительности за счет всех других соображений», то вам, вероятно, следует использовать профилировщик, а не спрашивать о stackoverflow!)

Об этом почти наверняка не стоит беспокоиться, и я сомневаюсь, что когда-либо будет существенная разница в производительности.Единственная ситуация, в которой я вижу хоть какой-то шанс на разницу, — это прохождение большой типы значений.

Другие советы

Я решил проверить это на себе, чтобы получить более «научный» ответ.Они одинаковые.Если я использую код ниже, ByVal будет примерно на 2% медленнее, чем ByRef.Однако если я поменяю их местами так, что я буду синхронизировать ByRef перед ByVal, то ByRef будет примерно на 2% медленнее.Итак, что на самом деле имеет большее значение, чем ByRef или ByVal, в этом случае — это порядок, в котором они выполняются :)

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

Чтобы понять поведение типов классов, включая строки, обратите внимание на все параметры типа класса, переменные, поля, элементы массива и т. д.как хранение «идентификаторов объектов».Если Foo это переменная типа string, заявление Foo = 12345.ToString(); создаст новый идентификатор объекта (гипотетически, идентификатор объекта № 197) и создаст новый объект типа string с этим идентификатором, содержащим пять символов "12345".Затем он будет хранить Object ID#197 в переменную Foo.Если кто-то вызывает подпрограмму с параметром, отличным от ссылки param, и проходит Foo к этому, тогда param будет локальной переменной, содержащей Object ID #197.Заявление param += "6"; создаст новый объект (например.Идентификатор объекта № 521) строкового типа, содержащий шесть символов. "123456" и хранить Object ID #521 в param.Обратите внимание, что Foo все еще держится Object ID#197, и этот объект по-прежнему содержит строку из пяти символов "12345".

Если param прошел мимо ref, то утверждение param += "6" хранил бы Object ID #521 в Foo.Это все равно не привело бы к каким-либо заметным изменениям в Объекте № 197, за исключением, возможно, того, что он стал бы пригодным для сбора мусора (если Foo была единственной ссылкой на Объект № 197, ее перезапись означало бы, что нигде во вселенной больше не будет никаких ссылок на этот объект).

Обратите внимание, что, как правило, довольно легко рассуждать о неизменяемых типах классов, таких как string, даже не задумываясь об идентификаторах объектов, поскольку единственный способ изменить последовательность символов, представленную строковой переменной, — это сохранить там другой идентификатор объекта.Однако мышление в терминах идентификаторов объектов становится важным при работе с изменяемыми типами классов.Передача переменной типа класса Car, а не по ссылке, было бы эквивалентно копированию VIN-кода с одного листа бумаги на другой и передаче последнего листа бумаги некоторым работникам магазина и просьбе их что-то с ним сделать.Если в первом документе изначально была указана красная машина с VIN-кодом 15934, то, когда рабочие закончили, в первом документе могла быть указана синяя машина с VIN-кодом 15934, но это была бы та же самая машина.Ничто из того, что рабочие могли сделать с листком бумаги, который им дали, или что-либо, что они могли сделать с машиной, не изменило бы то, о какой машине говорилось в первой газете.С другой стороны, передача параметра по ссылке была бы больше похожа на то, как работники магазина передают лист бумаги с написанным на нем VIN и получают от них эту бумагу обратно, когда они закончат.Если бы рабочие могли вычеркнуть VIN и написать другой, то, когда они вернут листок бумаги, он мог бы относиться к той же машине или к другой машине;если речь идет о другом автомобиле, автомобиль, о котором первоначально говорилось, мог быть или не быть модифицирован, а автомобиль, о котором в конечном итоге говорится в статье, может иметь или не иметь никакого сходства с оригиналом.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top