Domanda

Lettura Quale è più veloce?ByVal o ByRef? mi sono chiesto se i commenti in là si applicassero a Strings in termini di prestazioni.Poiché le stringhe vengono copiate prima di essere passate, non è molto più efficiente (se il callee non ha bisogno di una copia del corso di stringa) passare le stringhe ByRef?

Grazie,
PCP.

Modificare: Considera questo codice, che mi ha fatto pensare che ci fosse una sorta di copia in corso:

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

Uscite:

ByVal: Hello World (ByVal)!
ByRef: foobar
È stato utile?

Soluzione

stringhe non sono copiati prima di passare.Le stringhe sono tipi di riferimento, anche se si comportano in qualche modo come i tipi di valore.

Dovresti usare ciò che rende il più senso nel contesto delle tue esigenze.(E se le vostre esigenze sono qualcosa come "devono spremere ogni ultimo nanosecondo di prestazioni a spese di tutte le altre considerazioni", probabilmente dovresti spezzare il profiler piuttosto che chiedere su Stackoverflow!)

Questo è quasi certamente qualcosa di cui non devi preoccuparti, e dubito che sia mai una differenza di prestazione significativa.L'unica situazione in cui posso vedere qualsiasi possibilità di differenza sarebbe quando si passa Big tipi di valore.

Altri suggerimenti

Ho deciso di controllarlo per me stesso, per ottenere una risposta più "scientifica".Loro sono la stessa cosa.Se utilizzo il codice qui sotto, ByVal è di circa il 2% più lento del Byref.Se, tuttavia, lo scambiano in giro, in modo che sto tempando Byref prima di Byval, allora Byref è di circa il 2% più lento.Quindi, ciò che in realtà è importante più di ByRef o ByVal in questo caso è l'ordine in cui funzionano :)

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
.

Per comprendere il comportamento dei tipi di classe, incluse le stringhe, considera tutti i parametri, le variabili, i campi e gli elementi dell'array di classe, ecc.come in possesso di "id oggetto".Se Foo è una variabile di tipo string, dichiarazione Foo = 12345.ToString(); creerà un nuovo ID oggetto (ipoteticamente, ID oggetto#197) e creerà un nuovo oggetto di tipo string con quell'id, tenendo i cinque caratteri "12345".Sarà quindi memorizzare Object ID#197 nella variabile Foo.Se si chiama una routine con un parametro non-ref param, e passa Foo ad esso, allora param sarà una variabile locale holding Object ID #197.Dichiarazione param += "6"; creerebbe un nuovo oggetto (ad es.ID oggetto # 521), di tipo string, contenente i sei caratteri "123456" e conservare Object ID #521 in param.Si noti che Foo tiene ancora Object ID#197, e quell'oggetto tiene ancora la stringa di cinque caratteri "12345".

Se param era stato passato ref, poi la dichiarazione param += "6" avrebbero immagazzinato Object ID #521 in Foo.Non avrebbe comunque causato alcuna modifica osservabile all'Oggetto # 197, tranne forse per renderlo idoneo per la garbage collection (se Foo era stato l'unico riferimento all'Oggetto #197, sovrascrivendolo significherebbe che non ci sarebbe più alcun riferimento a quell'oggetto in qualsiasi parte dell'universo).

Si noti che è generalmente abbastanza facile ragionare su tipi di classe immutabili come string, anche senza pensare in termini di ID oggetto, poiché l'unico modo per cambiare la sequenza di caratteri rappresentati da una variabile stringa è memorizzare un ID oggetto diverso lì.Pensare in termini di ID oggetto diventa essenziale, tuttavia, quando si tratta di tipi di classe mutabili.Passaggio di una variabile di tipo classe Car, non da ref, sarebbe equivalente a copiare un VIN da un foglio di carta a un altro, e consegnare quest'ultimo foglio di carta ad alcuni lavoratori del negozio, e chiedendo loro di fare qualcosa con esso.Se il primo documento identificava originariamente un'auto rossa con VIN # 15934, allora quando i lavoratori sono stati fatti il primo documento potrebbe identificare un'auto blu con VIN # 15934, ma sarebbe la stessa auto.Nulla che i lavoratori potessero fare con il foglio di carta che gli era stato dato, né nulla che potessero fare con l'auto, cambierebbe l'auto a cui si riferiva il primo foglio.D'altra parte, passare il parametro per riferimento sarebbe più simile ai lavoratori del negozio un pezzo di carta con il VIN scritto su di esso, e ottenere la carta da loro quando sono stati fatti.Se i lavoratori potevano cancellare il VIN e scriverne un altro, allora quando restituivano il foglio di carta potrebbe riferirsi alla stessa auto o a un'auto diversa;se si riferisce a un'auto diversa, l'auto a cui si riferiva originariamente può o non può essere stata modificata e l'auto a cui il documento finisce per riferirsi può o non può avere alcuna somiglianza con l'originale.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top