サブ/ファンクション配列パラメータが変更されました

私はパラメータとして文字列の配列を持つSubを持っています:

Private Sub des(ByVal array() As String)

    Dim i As Integer

    For i = 0 To UBound(array)
        array(i) = "hy"
    Next

End Sub

私のメイン関数内の関数を呼び出すとき、strの値は配列がByVal関数に渡されても変わります:

Dim str() As String

str = {"11111", "22222", "33333", "44444", "5555", "66666"}

des(str)

私はSubの配列のコピーを作成しようとしましたが、それでもmain関数で変わります。

Private Sub des(ByVal array() As String)

    Dim i As Integer

    Dim array2() As String
    array2 = array

    For i = 0 To UBound(array)
        array(i) = "hy"
    Next

End Sub

私はあなたが配列ByValを渡すことができないサイトで読む。これは本当ですか?もしそうなら、どうすればいいですか?

2

4 答え

これを試して:

    Dim i As Integer

    Dim array2() As String
    array2 = array.Clone()

    For i = 0 To UBound(array2)
        array2(i) = "hy"
    Next

重要な違いは、実際には配列の浅いコピーを作成する .Clone()であり、array2の値を変更すると、メインコードの str

1
追加された

Visual Basic .NETでは、配列としてパラメータを指定する場合、注意する必要がある2つの重要な規則があります。

配列自体は、ByValとByRefとして渡すことができます。

     

配列の要素は、関数またはサブルーチンからいつでも変更できます。

サブプロセス(サブルーチンまたは関数)内の配列の要素を変更することができることは既に知っています。

したがって、これらの2つのサブルーチンを考えると、

Private Sub desval(ByVal array() As String)
    array = {}
End Sub

Private Sub desref(ByRef array() As String)
    array = {}
End Sub

そして、この非常に単純な補助サブルーチン(ここではConsoleを使用します):

Private Sub printArr(ByVal array() As String)
    For Each str In array
        Console.WriteLine(str)
    Next
End Sub

以下の簡単なテストを行うことができます:

Dim arr1() as String = {"abc", "xyz", "asdf"}

Console.WriteLine("Original array:")
printArr(arr1)
Console.WriteLine()
Console.WriteLine("After desval:")
desval(arr1)
printArr(arr1)
Console.WriteLine()
Console.WriteLine("After desref:")
desref(arr1)
printArr(arr1)
1
追加された

配列ByValを渡せないサイトを読みました。これは本当ですか?

いいえ、それは真実ではありません。

.NET Frameworkの配列は参照型です。配列を作成すると、 System.Array のオブジェクトが作成され、その参照が参照変数に割り当てられます。

des メソッドを呼び出すと、配列オブジェクトの参照が渡されます。 des メソッドでは、ByValパラメータは System.Array 型の参照パラメータ変数であり、配列オブジェクトの参照のコピーを受け取ります。

MSDN article - Passing Arguments by Value and by Reference (Visual Basic)

1
追加された

配列は参照型です。つまり、関数に配列を渡すと、渡されるのは常に配列のコピーではなく参照になります。関数内の配列は、呼び出しコード内の配列と同じ配列オブジェクトを参照します。

2番目の例では、同じことが起こります(これはコピーではありませんです)。これまでに行ったことは同じオブジェクトへの別の参照です。そのため、Boeckmのソリューションが機能し、 Clone()の呼び出しは新しい配列を作成し、元の配列の値のコピーである値を割り当てます。

1
追加された