当通过ByVal时,列表值在这里更改了,为什么 ,不得更改。
Private Sub Button6_Click(sender As Object, e As EventArgs) Handles Button6.Click
Dim value As Integer = 1
Dim value2 As New List(Of Decimal)
value2.Add(1)
value2.Add(2)
' The integer value doesn't change here when passed ByVal.
Example1(value)
Console.WriteLine(value)
' The list value changeed here when passed ByVal.
Example3(value2)
Console.WriteLine(value)
结束子
Sub Example1(ByVal test As Integer)
test = 10
End Sub
Sub Example3(ByVal test As List(Of Decimal))
test.Add(3)
End Sub
解决了,该解决方案正在制作新副本:
Sub Example3(ByVal test As List(Of Decimal))
Dim testnew As New List(Of Decimal)
testnew.AddRange(test)
testnew.Add(3)
End Sub
答案 0 :(得分:1)
您需要对值类型和引用类型进行一些阅读,并按值和引用传递方法参数。它们是相关的,但不是同一件事。按值传递方法参数时,将创建要传递的变量的副本。如果变量是值类型,即结构,则意味着创建值的副本。如果变量是引用类型,即类,则意味着创建引用的副本。事实是,原始引用和副本仍然都引用同一对象。
引用类型存在的原因是,您不想在每次将大型对象分配到某个地方时都创建它们的副本。在将集合传递给方法的情况下,几乎总是会在方法内部进行的任何更改都希望反映在外部。在极少数情况下,您可以自行创建集合的副本并将其传递给您。
按值传递值类型时,将创建该值的副本。这意味着您在方法内部进行的任何更改都不会影响原始变量。您可以为该参数分配一个新值,也可以设置该值的属性,并且更改不会反映在方法之外。当然,值类型通常应该是不可变的,因此设置属性应该是不可能的,但是有时“规则”会被破坏。
按值传递引用类型时,将创建引用的副本。这意味着将不同的对象分配给方法内的参数不会影响原始变量。但是,仍然只有一个对象,由原始变量和参数引用。这样,如果您通过参数设置该对象的属性,则该更改将反映在原始变量中,因为它是同一对象。
通过引用传递值类型时,将创建对该值的新引用。这意味着您在方法内部进行的任何更改都会影响原始变量。您可以为参数分配一个新值,也可以设置值的属性,更改将反映在方法之外。
当您通过引用传递引用类型时,您将创建一个对原始引用的新引用。这意味着将不同的对象分配给方法内部的参数将影响原始变量。仍然只有一个对象,因此在参数上设置属性仍然会影响原始变量。
仅有四种可能性:按值的值类型,按值的引用类型,按引用的值类型和按引用的引用类型。在任何一种情况下都不会创建引用类型对象的副本,因此在任何一种情况下都不能通过方法参数设置引用类型对象的属性并使更改不会反映在原始变量中。
如果您想要原始对象的副本,则取决于您明确创建一个对象。您在方法内部还是外部进行此操作实际上取决于特定的情况。这意味着您需要将代码更改为此:
Sub Example3(ByVal test As List(Of Decimal))
Dim copy = test.ToList()
copy.Add(3)
End Sub
或者这个:
Dim copy = value2.ToList()
Example3(copy)
让我在这里重复要点:没有办法将引用类型的对象传递给方法,无法通过方法内部的参数修改对象,并且不影响原始变量(将其他对象分配给参数未修改该对象)。如果您希望方法内的修改不影响原始变量,则需要该对象的副本,并且唯一的方法是显式地进行操作。