web-dev-qa-db-ja.com

ByValとByRefの違いは?

違いはなんですか?私はいつもByValを使用していますが、いつすべきか、いつすべきでないかについてはよくわかりません...

18
Voldemort

参照を渡す場合、メソッドの値を変更すると、呼び出しサイトの変数も変更されます。

値を渡すと、メソッドで別の変数が作成された場合と同じになるため、変更しても、元の変数(呼び出しサイト)の値は変更されません。

したがって、実際には、通常、変数を値として渡す必要があります。明示的に必要な場合にのみ、参照として渡します。

10
Bruno Brant

ByRef =あなたはあなたの友人にあなたのタームペーパー(オリジナル)を渡し、彼はそれをマークアップしてあなたに返すことができます。

ByVal =あなたは姫にタームペーパーのコピーを渡し、彼はあなたに彼の変更を返しますが、あなたはそれらをあなた自身で元に戻さなければなりません。

私がそれを作ることができるのと同じくらい簡単です。

Byrefを使用する理由:
ByRefは、渡すオブジェクトにPOINTERを渡します。同じメモリ空間にいる場合、これはオブジェクトではなく「Word」だけを渡すことを意味します。渡すメソッドは、元のオブジェクトに変更を加えることができ、元のオブジェクトにあるため、元のオブジェクトに戻す必要はまったくありません。大規模なデータパスを高速化するのに役立ちます。 ByRefを使用して、オブジェクトを返す必要がないため、FUNCTION(VB内)ではなくSUBの使用を許可することもできます。

Byrefを使用しない理由:
メソッドは元のメソッドにアクセスできるため、行われた変更は即座に永続的になります。メソッドが失敗した場合、oblectが破損する可能性があります。 ByValを使用すると、コピーが作成され、コピー全体がメソッドに渡されます。その後、メソッドは情報を処理し、コピーを再調整するか、情報を報告するか、何もしません。

11

私はこの質問がほとんど答えられたことを知っています、しかし私はただ以下を追加したかったです...

関数に渡すオブジェクトはByRef/ByValの対象となりますが、そのオブジェクトに他のオブジェクトへの参照が含まれている場合は、ByRef/ByValに関係なく、呼び出されたメソッドによってそれらを変更できます。説明が不十分です。理解を深めるために、以下のコードを参照してください。

Public Sub Test()
    Dim testCase As List(Of String) = GetNewList()
    ByRefChange1(testCase)
    'testCase = Nothing
    testCase = GetNewList()

    ByValChange1(testCase)
    'testCase is unchanged
    testCase = GetNewList()

    ByRefChange2(testCase)
    'testCase contains the element "ByRef Change 2"
    testCase = GetNewList()

    ByValChange2(testCase)
    'testCase contains the element "ByVal Change 2"

End Sub

Public Function GetNewList() As List(Of String)
    Dim result As List(Of String) = New List(Of String)
    result.Add("Value A")
    result.Add("Value B")
    result.Add("Value C")
    Return result
End Function

Public Sub ByRefChange1(ByRef aList As List(Of String))
    aList = Nothing
End Sub

Public Sub ByValChange1(ByVal aList As List(Of String))
    aList = Nothing
End Sub

Public Sub ByRefChange2(ByRef aList As List(Of String))
    aList.Add("ByRef Change 2")
End Sub

Public Sub ByValChange2(ByVal aList As List(Of String))
    aList.Add("ByVal Change 2")
End Sub

編集:

また、この関数が呼び出されたかどうかを検討してください。

Public Sub ByValChange3(ByVal aList As List(Of String))
    aList.Add("ByVal Change 3")
    aList = New List(Of String)
    aList.Add("ByVal Change 4")
End Sub

この場合、「ByVal Change 3」が呼び出し元リストに追加されますが、「aList = New List」を指定した時点で、新しい参照を新しいオブジェクトにポイントし、呼び出し元から切り離されます。リスト。常識といつかあなたを捕まえるかもしれないので、心に留めておくべき何か。

5
Smudge202

ByRefは、2番目の戻り値のようなものです。オブジェクト自体ではなく、オブジェクトへの参照を関数に渡します。関数のByRefパラメータの値を変更すると、関数の終了後にそれらの変更が表示されます。それが十分に明確でなかった場合は、 これを読んでください および これ

5
kelloti

ByRef、1つの値には2つのアドレスがあります

したがって、x = 80の場合(80は値、xはアドレスの場合、たとえば変数yも80になる可能性があるため、xとyから80にアクセスできます)

0
user7587624

@Tomと@kellotiによる回答が役に立ちます。さらに説明するためのコード例を次に示します。

Private Function ValMessage(ByVal SomeMessage As String)
    SomeMessage = "Val Val Val" ' <-- this variable modification doesn't persist after the function finishes execution
    ValMessage = "Some Return Value"
End Function

Private Function RefMessage(ByRef SomeMessage As String)
    SomeMessage = "Ref Ref Ref" ' <-- this variable modification persists even after the function finishes execution
    RefMessage = "Some Return Value"
End Function

Private Sub DoStuff()
    Dim OriginalMessage As String
    Dim OtherMessage As String
    Dim AnotherMessage As String

    OriginalMessage = "Original"
    MsgBox ("ORIGINAL: " & OriginalMessage) '--> "Original"

    OtherMessage = ValMessage(OriginalMessage)
    MsgBox ("ORIGINAL: " & OriginalMessage) '--> "Original"

    AnotherMessage = RefMessage(OriginalMessage)
    MsgBox ("ORIGINAL: " & OriginalMessage) '--> "Ref Ref Ref" <--- this is the difference when you pass a paramter by reference
End Sub
0
s2t2

これがあなたの質問に答えることを願っています

Sub last_column_process()
Dim last_column As Integer

last_column = 234
MsgBox last_column

trying_byref x:=last_column
MsgBox last_column

trying_byval v:=last_column
MsgBox last_column

End Sub

Sub trying_byref(ByRef x)
x = 345
End Sub

Sub trying_byval(ByRef v)
v = 555
End Sub
0
Ashwith Ullal

最後のサンプルにタイプミスがあった可能性があると考えてください。最後のサブは「byref」ではなく「byval」である必要があります。 :)

また、trying_byvalにmsgboxステートメントを追加して、意味を理解できるようにしました。

Sub begin()
Dim last_column As Integer

last_column = 234
MsgBox "Begin:" & last_column

trying_byref x:=last_column
MsgBox "byref:" & last_column

trying_byval v:=last_column
MsgBox "byval:" & last_column
End Sub

Sub trying_byref(ByRef x)
x = 111
End Sub

Sub trying_byval(ByVal v)  '<--not ByRef, that was in sub trying_byref.
v = 222
MsgBox "In Here:" & v
End Sub
0
Rob Lawton

簡単な言葉で違いを説明しようと思います。

  • 引数を値で渡すと、パラメータのみが入力されます。これが最も安全な方法であるため、95%のケースでデフォルトで使用されます。

  • 引数を参照で渡すと、入力パラメーターと出力パラメーターの両方になります。出力パラメーターは、めったに使用されない副作用を作成する関数内で変更できます。

0